@eleven-am/pondsocket 0.1.8 → 0.1.10
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/package.json +1 -2
- package/pondBase/baseClass.d.ts +3 -1
- package/pondBase/pondBase.js +1 -1
- package/pondBase/pubSub.d.ts +10 -5
- package/pondBase/pubSub.js +6 -0
- package/pondBase/pubSub.test.js +14 -0
- package/pondBase/simpleBase.d.ts +0 -5
- package/pondClient/channel.d.ts +19 -19
- package/pondClient/channel.js +98 -122
- package/pondClient/socket.d.ts +13 -14
- package/pondClient/socket.js +69 -103
- package/pondSocket/channel.js +6 -6
- package/pondSocket/channel.test.js +2 -2
- package/pondSocket/endpoint.js +1 -4
- package/pondSocket/endpoint.test.js +72 -95
- package/pondSocket/pondChannel.js +2 -10
- package/pondSocket/server.test.js +18 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eleven-am/pondsocket",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "PondSocket is a fast simple socket server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"socket",
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
"url": "git+https://github.com/Eleven-am/pondSocket.git"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"rxjs": "^7.5.6",
|
|
32
31
|
"ws": "^8.8.1"
|
|
33
32
|
},
|
|
34
33
|
"devDependencies": {
|
package/pondBase/baseClass.d.ts
CHANGED
|
@@ -49,5 +49,7 @@ export declare class BaseClass {
|
|
|
49
49
|
* /api/id?name=abc should return { name: 'abc' }
|
|
50
50
|
* /api/id?name=abc&age=123 should return { name: 'abc', age: '123' }
|
|
51
51
|
*/
|
|
52
|
-
protected _parseQueries(path: string):
|
|
52
|
+
protected _parseQueries(path: string): {
|
|
53
|
+
[p: string]: string;
|
|
54
|
+
};
|
|
53
55
|
}
|
package/pondBase/pondBase.js
CHANGED
|
@@ -52,7 +52,7 @@ class PondBase extends simpleBase_1.SimpleBase {
|
|
|
52
52
|
const newPond = new PondBase();
|
|
53
53
|
for (const doc of this) {
|
|
54
54
|
const foreignDoc = pond.find((d) => d[foreignKey] === doc.doc[key]);
|
|
55
|
-
newPond.set(doc.id, {
|
|
55
|
+
newPond.set(doc.id, Object.assign(Object.assign({}, doc.doc), { [key]: (foreignDoc === null || foreignDoc === void 0 ? void 0 : foreignDoc.doc) || null }));
|
|
56
56
|
}
|
|
57
57
|
return newPond;
|
|
58
58
|
}
|
package/pondBase/pubSub.d.ts
CHANGED
|
@@ -5,21 +5,26 @@ export declare class Subscription {
|
|
|
5
5
|
export declare class Broadcast<T, A> {
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* @desc
|
|
9
|
-
* @param handler - The handler to call when the broadcast is published
|
|
8
|
+
* @desc Gets the number of subscribers
|
|
10
9
|
*/
|
|
11
|
-
|
|
10
|
+
get subscriberCount(): number;
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
|
-
* @desc
|
|
13
|
+
* @desc Subscribe to the broadcast
|
|
14
|
+
* @param handler - The handler to call when the broadcast is published
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
subscribe(handler: (data: T) => A): Subscription;
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* @desc Publish to the broadcast
|
|
20
20
|
* @param data - The data to publish
|
|
21
21
|
*/
|
|
22
22
|
publish(data: T): A | undefined;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @dec clears all subscribers
|
|
26
|
+
*/
|
|
27
|
+
clear(): void;
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
export declare class Subject<T, A> extends Broadcast<T, A> {
|
package/pondBase/pubSub.js
CHANGED
package/pondBase/pubSub.test.js
CHANGED
|
@@ -82,6 +82,20 @@ describe('Broadcast', () => {
|
|
|
82
82
|
expect(subscriber2).toHaveBeenCalledWith('Hello');
|
|
83
83
|
expect(subscriber3).not.toHaveBeenCalled();
|
|
84
84
|
});
|
|
85
|
+
it('should clear all subscribers', () => {
|
|
86
|
+
const broadcast = new pubSub_1.Broadcast();
|
|
87
|
+
const subscriber1 = jest.fn();
|
|
88
|
+
const subscriber2 = jest.fn();
|
|
89
|
+
broadcast.subscribe(subscriber1);
|
|
90
|
+
broadcast.subscribe(subscriber2);
|
|
91
|
+
broadcast.publish('Hello');
|
|
92
|
+
broadcast.clear();
|
|
93
|
+
broadcast.publish('Hello Again');
|
|
94
|
+
expect(subscriber1).toHaveBeenCalledWith('Hello');
|
|
95
|
+
expect(subscriber1).not.toHaveBeenCalledWith('Hello Again');
|
|
96
|
+
expect(subscriber2).toHaveBeenCalledWith('Hello');
|
|
97
|
+
expect(subscriber2).not.toHaveBeenCalledWith('Hello Again');
|
|
98
|
+
});
|
|
85
99
|
});
|
|
86
100
|
describe('Subject', () => {
|
|
87
101
|
it('should be defined', () => {
|
package/pondBase/simpleBase.d.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
export declare class PondDocument<T> {
|
|
2
|
-
private readonly _id;
|
|
3
|
-
private readonly _getDoc;
|
|
4
|
-
private readonly _removeDoc;
|
|
5
|
-
private readonly _updateDoc;
|
|
6
|
-
|
|
7
2
|
constructor(id: string, removeDoc: () => void, updateDoc: (value: T) => PondDocument<T>, getDoc: () => T);
|
|
8
3
|
|
|
9
4
|
get id(): string;
|
package/pondClient/channel.d.ts
CHANGED
|
@@ -1,34 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {ClientMessage, PondAssigns, PondMessage, PondPresence, ServerMessage} from "../pondSocket";
|
|
2
|
+
import {Broadcast, Subscription} from "../pondBase";
|
|
3
3
|
|
|
4
4
|
export declare type ChannelParams = PondAssigns;
|
|
5
5
|
|
|
6
6
|
export declare class Channel {
|
|
7
|
-
readonly channel: string;
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
constructor(name: string, receiver: Broadcast<ServerMessage, void>, broadcaster: Broadcast<ClientMessage, void>, params?: ChannelParams);
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* @desc Connects to the channel.
|
|
13
12
|
*/
|
|
14
|
-
join():
|
|
13
|
+
join(): void;
|
|
15
14
|
|
|
16
15
|
/**
|
|
17
16
|
* @desc Disconnects from the channel.
|
|
18
17
|
*/
|
|
19
18
|
leave(): void;
|
|
20
19
|
|
|
21
|
-
/**
|
|
22
|
-
* @desc Monitors the presence state of the channel.
|
|
23
|
-
* @param callback - The callback to call when the presence state changes.
|
|
24
|
-
*/
|
|
25
|
-
onPresenceUpdate(callback: (presence: PondPresence[]) => void): Subscription;
|
|
26
|
-
|
|
27
20
|
/**
|
|
28
21
|
* @desc Monitors the channel for messages.
|
|
22
|
+
* @param event - The event to monitor.
|
|
29
23
|
* @param callback - The callback to call when a message is received.
|
|
30
24
|
*/
|
|
31
|
-
onMessage(
|
|
25
|
+
onMessage(event: string, callback: (message: PondMessage) => void): Subscription;
|
|
32
26
|
|
|
33
27
|
/**
|
|
34
28
|
* @desc Broadcasts a message to the channel, including yourself.
|
|
@@ -44,6 +38,14 @@ export declare class Channel {
|
|
|
44
38
|
*/
|
|
45
39
|
broadcastFrom(event: string, payload: PondMessage): void;
|
|
46
40
|
|
|
41
|
+
/**
|
|
42
|
+
* @desc Sends a message to specific clients in the channel.
|
|
43
|
+
* @param event - The event to send.
|
|
44
|
+
* @param payload - The message to send.
|
|
45
|
+
* @param recipient - The clients to send the message to.
|
|
46
|
+
*/
|
|
47
|
+
sendMessage(event: string, payload: PondMessage, recipient: string[]): void;
|
|
48
|
+
|
|
47
49
|
/**
|
|
48
50
|
* @desc Updates the presence state of the current client in the channel.
|
|
49
51
|
* @param presence - The presence state to update.
|
|
@@ -51,16 +53,14 @@ export declare class Channel {
|
|
|
51
53
|
updatePresence(presence: PondPresence): void;
|
|
52
54
|
|
|
53
55
|
/**
|
|
54
|
-
* @desc
|
|
55
|
-
* @param
|
|
56
|
-
* @param payload - The message to send.
|
|
57
|
-
* @param recipient - The clients to send the message to.
|
|
56
|
+
* @desc Monitors the presence state of the channel.
|
|
57
|
+
* @param callback - The callback to call when the presence state changes.
|
|
58
58
|
*/
|
|
59
|
-
|
|
59
|
+
onPresence(callback: (change: PondPresence | null, presence: PondPresence[]) => void): Subscription;
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
|
-
* @desc
|
|
62
|
+
* @desc Monitors the connection state of the channel.
|
|
63
63
|
* @param callback - The callback to call when the connection state changes.
|
|
64
64
|
*/
|
|
65
|
-
onConnectionChange(callback: (connected: boolean) => void):
|
|
65
|
+
onConnectionChange(callback: (connected: boolean) => void): Subscription;
|
|
66
66
|
}
|
package/pondClient/channel.js
CHANGED
|
@@ -1,163 +1,139 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Channel = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
12
|
-
this.
|
|
13
|
-
this.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
4
|
+
const pondSocket_1 = require("../pondSocket");
|
|
5
|
+
const pondBase_1 = require("../pondBase");
|
|
6
|
+
class Channel {
|
|
7
|
+
constructor(name, receiver, broadcaster, params) {
|
|
8
|
+
this._name = name;
|
|
9
|
+
this._joinParams = params || {};
|
|
10
|
+
this._broadcaster = broadcaster;
|
|
11
|
+
this._connection = new pondBase_1.Subject(false);
|
|
12
|
+
this._receiver = new pondBase_1.Broadcast();
|
|
13
|
+
this._subscription = receiver.subscribe(data => {
|
|
14
|
+
if (data.channelName === name) {
|
|
15
|
+
this._receiver.publish(data);
|
|
16
|
+
this._connection.publish(true);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
this._presence = new pondBase_1.Subject({
|
|
20
|
+
change: null,
|
|
21
|
+
presence: []
|
|
22
|
+
});
|
|
17
23
|
}
|
|
18
|
-
Object.defineProperty(Channel.prototype, "isActive", {
|
|
19
|
-
get: function () {
|
|
20
|
-
return this._connectedSubject.value;
|
|
21
|
-
},
|
|
22
|
-
enumerable: false,
|
|
23
|
-
configurable: true
|
|
24
|
-
});
|
|
25
24
|
/**
|
|
26
25
|
* @desc Connects to the channel.
|
|
27
26
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
_this._subject.next(message);
|
|
40
|
-
else if (message.event === "KICKED_FROM_CHANNEL")
|
|
41
|
-
_this.leave();
|
|
27
|
+
join() {
|
|
28
|
+
const joinMessage = {
|
|
29
|
+
action: pondSocket_1.ClientActions.JOIN_CHANNEL,
|
|
30
|
+
channelName: this._name,
|
|
31
|
+
event: pondSocket_1.ClientActions.JOIN_CHANNEL,
|
|
32
|
+
payload: this._joinParams
|
|
33
|
+
};
|
|
34
|
+
this._receiver.subscribe(data => {
|
|
35
|
+
if (data.action === pondSocket_1.ServerActions.PRESENCE) {
|
|
36
|
+
this._presence.publish(data.payload);
|
|
37
|
+
}
|
|
42
38
|
});
|
|
43
|
-
this.
|
|
44
|
-
|
|
45
|
-
};
|
|
39
|
+
this._broadcaster.publish(joinMessage);
|
|
40
|
+
}
|
|
46
41
|
/**
|
|
47
42
|
* @desc Disconnects from the channel.
|
|
48
43
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return sub;
|
|
64
|
-
};
|
|
44
|
+
leave() {
|
|
45
|
+
const leaveMessage = {
|
|
46
|
+
action: pondSocket_1.ClientActions.LEAVE_CHANNEL,
|
|
47
|
+
channelName: this._name,
|
|
48
|
+
event: pondSocket_1.ClientActions.LEAVE_CHANNEL,
|
|
49
|
+
payload: {}
|
|
50
|
+
};
|
|
51
|
+
this._broadcaster.publish(leaveMessage);
|
|
52
|
+
this._connection.publish(false);
|
|
53
|
+
this._subscription.unsubscribe();
|
|
54
|
+
this._connection.clear();
|
|
55
|
+
this._receiver.clear();
|
|
56
|
+
this._presence.clear();
|
|
57
|
+
}
|
|
65
58
|
/**
|
|
66
59
|
* @desc Monitors the channel for messages.
|
|
60
|
+
* @param event - The event to monitor.
|
|
67
61
|
* @param callback - The callback to call when a message is received.
|
|
68
62
|
*/
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
};
|
|
63
|
+
onMessage(event, callback) {
|
|
64
|
+
return this._receiver.subscribe(data => {
|
|
65
|
+
if (data.action === pondSocket_1.ServerActions.MESSAGE && data.event === event)
|
|
66
|
+
callback(data.payload);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
76
69
|
/**
|
|
77
70
|
* @desc Broadcasts a message to the channel, including yourself.
|
|
78
71
|
* @param event - The event to send.
|
|
79
72
|
* @param payload - The message to send.
|
|
80
73
|
*/
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
channelName: this.
|
|
84
|
-
payload: payload,
|
|
85
|
-
event: event,
|
|
86
|
-
action: pondSocket_1.ClientActions.BROADCAST
|
|
74
|
+
broadcast(event, payload) {
|
|
75
|
+
const message = {
|
|
76
|
+
action: pondSocket_1.ClientActions.BROADCAST, channelName: this._name, payload: payload, event: event
|
|
87
77
|
};
|
|
88
|
-
this.
|
|
89
|
-
}
|
|
78
|
+
this._broadcaster.publish(message);
|
|
79
|
+
}
|
|
90
80
|
/**
|
|
91
81
|
* @desc Broadcasts a message to every other client in the channel except yourself.
|
|
92
82
|
* @param event - The event to send.
|
|
93
83
|
* @param payload - The message to send.
|
|
94
84
|
*/
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
channelName: this.
|
|
98
|
-
payload: payload,
|
|
99
|
-
event: event,
|
|
100
|
-
action: pondSocket_1.ClientActions.BROADCAST_FROM
|
|
85
|
+
broadcastFrom(event, payload) {
|
|
86
|
+
const message = {
|
|
87
|
+
action: pondSocket_1.ClientActions.BROADCAST_FROM, channelName: this._name, payload: payload, event: event
|
|
101
88
|
};
|
|
102
|
-
this.
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* @desc Updates the presence state of the current client in the channel.
|
|
106
|
-
* @param presence - The presence state to update.
|
|
107
|
-
*/
|
|
108
|
-
Channel.prototype.updatePresence = function (presence) {
|
|
109
|
-
this._socket.next({
|
|
110
|
-
action: pondSocket_1.ClientActions.UPDATE_PRESENCE,
|
|
111
|
-
channelName: this.channel,
|
|
112
|
-
event: "PRESENCE",
|
|
113
|
-
payload: presence
|
|
114
|
-
});
|
|
115
|
-
};
|
|
89
|
+
this._broadcaster.publish(message);
|
|
90
|
+
}
|
|
116
91
|
/**
|
|
117
92
|
* @desc Sends a message to specific clients in the channel.
|
|
118
93
|
* @param event - The event to send.
|
|
119
94
|
* @param payload - The message to send.
|
|
120
95
|
* @param recipient - The clients to send the message to.
|
|
121
96
|
*/
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
channelName: this.
|
|
97
|
+
sendMessage(event, payload, recipient) {
|
|
98
|
+
const message = {
|
|
99
|
+
action: pondSocket_1.ClientActions.SEND_MESSAGE_TO_USER,
|
|
100
|
+
channelName: this._name,
|
|
126
101
|
payload: payload,
|
|
127
102
|
event: event,
|
|
128
|
-
addresses:
|
|
129
|
-
action: pondSocket_1.ClientActions.SEND_MESSAGE_TO_USER
|
|
103
|
+
addresses: recipient
|
|
130
104
|
};
|
|
131
|
-
this.
|
|
132
|
-
}
|
|
105
|
+
this._broadcaster.publish(message);
|
|
106
|
+
}
|
|
133
107
|
/**
|
|
134
|
-
* @desc
|
|
135
|
-
* @param
|
|
108
|
+
* @desc Updates the presence state of the current client in the channel.
|
|
109
|
+
* @param presence - The presence state to update.
|
|
110
|
+
*/
|
|
111
|
+
updatePresence(presence) {
|
|
112
|
+
const message = {
|
|
113
|
+
action: pondSocket_1.ClientActions.UPDATE_PRESENCE,
|
|
114
|
+
channelName: this._name,
|
|
115
|
+
payload: presence,
|
|
116
|
+
event: pondSocket_1.ClientActions.UPDATE_PRESENCE
|
|
117
|
+
};
|
|
118
|
+
this._broadcaster.publish(message);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* @desc Monitors the presence state of the channel.
|
|
122
|
+
* @param callback - The callback to call when the presence state changes.
|
|
136
123
|
*/
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
124
|
+
onPresence(callback) {
|
|
125
|
+
return this._presence.subscribe(data => {
|
|
126
|
+
callback(data.change, data.presence);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
142
129
|
/**
|
|
143
|
-
* @desc
|
|
144
|
-
* @
|
|
130
|
+
* @desc Monitors the connection state of the channel.
|
|
131
|
+
* @param callback - The callback to call when the connection state changes.
|
|
145
132
|
*/
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
payload: _this._params
|
|
153
|
-
}); }, function () { return ({
|
|
154
|
-
action: "LEAVE_CHANNEL",
|
|
155
|
-
channelName: _this.channel,
|
|
156
|
-
event: "LEAVE_CHANNEL",
|
|
157
|
-
payload: _this._params
|
|
158
|
-
}); }, function (message) { return message.channelName === _this.channel; });
|
|
159
|
-
return observable;
|
|
160
|
-
};
|
|
161
|
-
return Channel;
|
|
162
|
-
}());
|
|
133
|
+
onConnectionChange(callback) {
|
|
134
|
+
return this._connection.subscribe(data => {
|
|
135
|
+
callback(data);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
163
139
|
exports.Channel = Channel;
|
package/pondClient/socket.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {Channel, ChannelParams} from "./channel";
|
|
2
|
-
import {
|
|
2
|
+
import {PondMessage} from "../pondSocket";
|
|
3
3
|
|
|
4
4
|
declare type PondParams = {
|
|
5
5
|
[key: string]: string;
|
|
@@ -11,32 +11,31 @@ export declare class PondClient {
|
|
|
11
11
|
constructor(endpoint: string, params?: PondParams);
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* @desc
|
|
14
|
+
* @desc Returns the current state of the socket.
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
getState(): PondState;
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* @desc
|
|
19
|
+
* @desc Connects to the server and returns the socket.
|
|
20
20
|
*/
|
|
21
|
-
|
|
21
|
+
connect(backoff?: number): void;
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* @desc
|
|
25
|
-
* @param channel - The name of the channel.
|
|
26
|
-
* @param params - The params to send to the server.
|
|
24
|
+
* @desc Disconnects the socket from the server.
|
|
27
25
|
*/
|
|
28
|
-
|
|
26
|
+
disconnect(): void;
|
|
29
27
|
|
|
30
28
|
/**
|
|
31
29
|
* @desc An event that is triggered when the socket receives a message.
|
|
30
|
+
* @param event - The event to subscribe to.
|
|
32
31
|
* @param callback - The callback to be called when the event is triggered.
|
|
33
32
|
*/
|
|
34
|
-
onMessage(
|
|
33
|
+
onMessage(event: string, callback: (message: PondMessage) => void): import("../pondBase").Subscription;
|
|
35
34
|
|
|
36
35
|
/**
|
|
37
|
-
* @desc
|
|
36
|
+
* @desc Creates a channel with the given name and params.
|
|
37
|
+
* @param name - The name of the channel.
|
|
38
|
+
* @param params - The params to send to the server.
|
|
38
39
|
*/
|
|
39
|
-
|
|
40
|
+
createChannel(name: string, params?: ChannelParams): Channel;
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
-
export {};
|
package/pondClient/socket.js
CHANGED
|
@@ -1,48 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
3
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
4
|
-
if (!m) return o;
|
|
5
|
-
var i = m.call(o), r, ar = [], e;
|
|
6
|
-
try {
|
|
7
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
8
|
-
}
|
|
9
|
-
catch (error) { e = { error: error }; }
|
|
10
|
-
finally {
|
|
11
|
-
try {
|
|
12
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
13
|
-
}
|
|
14
|
-
finally { if (e) throw e.error; }
|
|
15
|
-
}
|
|
16
|
-
return ar;
|
|
17
|
-
};
|
|
18
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
3
|
exports.PondClient = void 0;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
function PondClient(endpoint, params) {
|
|
27
|
-
this.socketState = "CLOSED";
|
|
28
|
-
/**
|
|
29
|
-
* @desc A retry strategy for the socket.
|
|
30
|
-
* @param maxTries - The maximum number of retries.
|
|
31
|
-
* @param ms - The number of milliseconds to wait before retrying.
|
|
32
|
-
*/
|
|
33
|
-
this._retryStrategy = function (maxTries, ms) {
|
|
34
|
-
return (0, rxjs_1.pipe)((0, operators_1.retryWhen)(function (attempts) {
|
|
35
|
-
var observableForRetries = (0, rxjs_1.zip)((0, rxjs_1.range)(1, maxTries), attempts)
|
|
36
|
-
.pipe((0, operators_1.map)(function (_a) {
|
|
37
|
-
var _b = __read(_a, 1), elemFromRange = _b[0];
|
|
38
|
-
return elemFromRange;
|
|
39
|
-
}), (0, operators_1.map)(function (i) { return i * i; }), (0, rxjs_1.switchMap)(function (i) { return (0, rxjs_1.timer)(i * ms); }));
|
|
40
|
-
var observableForFailure = (0, rxjs_1.throwError)(new Error("Could not connect to server"))
|
|
41
|
-
.pipe((0, rxjs_1.materialize)(), (0, rxjs_1.delay)(1000), (0, rxjs_1.dematerialize)());
|
|
42
|
-
return (0, rxjs_1.concat)(observableForRetries, observableForFailure);
|
|
43
|
-
}));
|
|
44
|
-
};
|
|
45
|
-
var address;
|
|
4
|
+
const channel_1 = require("./channel");
|
|
5
|
+
const pondBase_1 = require("../pondBase");
|
|
6
|
+
const pondSocket_1 = require("../pondSocket");
|
|
7
|
+
class PondClient {
|
|
8
|
+
constructor(endpoint, params) {
|
|
9
|
+
let address;
|
|
46
10
|
try {
|
|
47
11
|
address = new URL(endpoint);
|
|
48
12
|
}
|
|
@@ -50,83 +14,85 @@ var PondClient = /** @class */ (function () {
|
|
|
50
14
|
address = new URL(window.location.toString());
|
|
51
15
|
address.pathname = endpoint;
|
|
52
16
|
}
|
|
53
|
-
|
|
17
|
+
const query = new URLSearchParams(params);
|
|
54
18
|
address.search = query.toString();
|
|
55
|
-
|
|
19
|
+
const protocol = address.protocol === "https:" ? "wss:" : "ws:";
|
|
56
20
|
if (address.protocol !== "wss:" && address.protocol !== "ws:")
|
|
57
21
|
address.protocol = protocol;
|
|
58
22
|
this.address = address;
|
|
59
|
-
this.
|
|
23
|
+
this._socketState = "CLOSED";
|
|
24
|
+
this._channels = {};
|
|
25
|
+
this._broadcaster = new pondBase_1.Broadcast();
|
|
26
|
+
this._receiver = new pondBase_1.Broadcast();
|
|
60
27
|
}
|
|
61
28
|
/**
|
|
62
|
-
* @desc
|
|
29
|
+
* @desc Returns the current state of the socket.
|
|
63
30
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return;
|
|
68
|
-
this.socketState = "CONNECTING";
|
|
69
|
-
var socket = (0, webSocket_1.webSocket)({
|
|
70
|
-
url: this.address.toString(),
|
|
71
|
-
openObserver: {
|
|
72
|
-
next: function () {
|
|
73
|
-
_this.socketState = "OPEN";
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
closeObserver: {
|
|
77
|
-
next: function () {
|
|
78
|
-
_this.socketState = "CLOSED";
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
closingObserver: {
|
|
82
|
-
next: function () {
|
|
83
|
-
_this.socketState = "CLOSING";
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
this.socket = socket;
|
|
88
|
-
this.subscription = socket.pipe(this._retryStrategy(100, 1000)).subscribe();
|
|
89
|
-
return this;
|
|
90
|
-
};
|
|
31
|
+
getState() {
|
|
32
|
+
return this._socketState;
|
|
33
|
+
}
|
|
91
34
|
/**
|
|
92
|
-
* @desc
|
|
35
|
+
* @desc Connects to the server and returns the socket.
|
|
93
36
|
*/
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
37
|
+
connect(backoff = 1) {
|
|
38
|
+
const socket = new WebSocket(this.address.toString());
|
|
39
|
+
const sub = this._receiver.subscribe((message) => {
|
|
40
|
+
socket.send(JSON.stringify(message));
|
|
41
|
+
});
|
|
42
|
+
socket.onopen = () => {
|
|
43
|
+
this._socketState = "OPEN";
|
|
44
|
+
};
|
|
45
|
+
socket.onclose = () => {
|
|
46
|
+
this._socketState = "CLOSED";
|
|
47
|
+
sub.unsubscribe();
|
|
48
|
+
};
|
|
49
|
+
socket.onmessage = (message) => {
|
|
50
|
+
const data = JSON.parse(message.data);
|
|
51
|
+
this._broadcaster.publish(data);
|
|
52
|
+
};
|
|
53
|
+
socket.onerror = () => {
|
|
54
|
+
this._socketState = "CLOSED";
|
|
55
|
+
sub.unsubscribe();
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
this.connect(backoff * 2);
|
|
58
|
+
}, backoff * 1000);
|
|
59
|
+
};
|
|
60
|
+
this._socket = socket;
|
|
61
|
+
}
|
|
97
62
|
/**
|
|
98
|
-
* @desc
|
|
99
|
-
* @param channel - The name of the channel.
|
|
100
|
-
* @param params - The params to send to the server.
|
|
63
|
+
* @desc Disconnects the socket from the server.
|
|
101
64
|
*/
|
|
102
|
-
|
|
103
|
-
var
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
65
|
+
disconnect() {
|
|
66
|
+
var _a;
|
|
67
|
+
Object.values(this._channels).forEach(channel => channel.leave());
|
|
68
|
+
this._socketState = "CLOSED";
|
|
69
|
+
this._broadcaster.clear();
|
|
70
|
+
this._receiver.clear();
|
|
71
|
+
(_a = this._socket) === null || _a === void 0 ? void 0 : _a.close();
|
|
72
|
+
this._channels = {};
|
|
73
|
+
}
|
|
108
74
|
/**
|
|
109
75
|
* @desc An event that is triggered when the socket receives a message.
|
|
76
|
+
* @param event - The event to subscribe to.
|
|
110
77
|
* @param callback - The callback to be called when the event is triggered.
|
|
111
78
|
*/
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
callback(data.event, data.payload);
|
|
79
|
+
onMessage(event, callback) {
|
|
80
|
+
return this._broadcaster.subscribe(data => {
|
|
81
|
+
if (data.action === pondSocket_1.ServerActions.MESSAGE && data.event === event)
|
|
82
|
+
callback(data.payload);
|
|
117
83
|
});
|
|
118
|
-
}
|
|
84
|
+
}
|
|
119
85
|
/**
|
|
120
|
-
* @desc
|
|
86
|
+
* @desc Creates a channel with the given name and params.
|
|
87
|
+
* @param name - The name of the channel.
|
|
88
|
+
* @param params - The params to send to the server.
|
|
121
89
|
*/
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return PondClient;
|
|
131
|
-
}());
|
|
90
|
+
createChannel(name, params) {
|
|
91
|
+
if (this._channels[name])
|
|
92
|
+
return this._channels[name];
|
|
93
|
+
const channel = new channel_1.Channel(name, this._broadcaster, this._receiver, params);
|
|
94
|
+
this._channels[name] = channel;
|
|
95
|
+
return channel;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
132
98
|
exports.PondClient = PondClient;
|
package/pondSocket/channel.js
CHANGED
|
@@ -29,7 +29,7 @@ class Channel extends pondBase_1.BaseClass {
|
|
|
29
29
|
* @desc Gets the channel's data
|
|
30
30
|
*/
|
|
31
31
|
get data() {
|
|
32
|
-
const result = {
|
|
32
|
+
const result = Object.assign({}, this._channelData);
|
|
33
33
|
return Object.freeze(result);
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
@@ -37,7 +37,7 @@ class Channel extends pondBase_1.BaseClass {
|
|
|
37
37
|
* @param data
|
|
38
38
|
*/
|
|
39
39
|
set data(data) {
|
|
40
|
-
this._channelData = {
|
|
40
|
+
this._channelData = Object.assign(Object.assign({}, this._channelData), data);
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
43
|
* @desc Gets the channel's presence
|
|
@@ -78,9 +78,9 @@ class Channel extends pondBase_1.BaseClass {
|
|
|
78
78
|
const clientId = user.client.clientId;
|
|
79
79
|
if (this.hasUser(clientId))
|
|
80
80
|
throw new Error(`User with clientId ${clientId} already exists in channel ${this.name}`);
|
|
81
|
-
this._channelPresence.set(clientId, {
|
|
81
|
+
this._channelPresence.set(clientId, Object.assign(Object.assign({}, user.presence), { id: clientId }));
|
|
82
82
|
this._channelAssigns.set(clientId, user.assigns);
|
|
83
|
-
this._channelData = Object.assign({
|
|
83
|
+
this._channelData = Object.assign(Object.assign(Object.assign({}, this._channelData), user.channelData));
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
86
86
|
* @desc Removes a user or group of users from the channel
|
|
@@ -129,8 +129,8 @@ class Channel extends pondBase_1.BaseClass {
|
|
|
129
129
|
updateUser(clientId, presence, assigns) {
|
|
130
130
|
const client = this._retrieveUser(clientId);
|
|
131
131
|
if (client) {
|
|
132
|
-
client.assigns.updateDoc(Object.assign({
|
|
133
|
-
const presenceDoc = Object.assign({
|
|
132
|
+
client.assigns.updateDoc(Object.assign(Object.assign({}, client.assigns.doc), assigns));
|
|
133
|
+
const presenceDoc = Object.assign(Object.assign({}, client.presence.doc), presence);
|
|
134
134
|
if (!this.areEqual(presenceDoc, client.presence.doc))
|
|
135
135
|
client.presence.updateDoc(presenceDoc);
|
|
136
136
|
}
|
|
@@ -220,10 +220,10 @@ describe('Channel', () => {
|
|
|
220
220
|
});
|
|
221
221
|
it('should be possible to remove multiple users at once', () => {
|
|
222
222
|
const { channel, user } = (0, exports.createChannel)('test');
|
|
223
|
-
const user1 = {
|
|
223
|
+
const user1 = Object.assign({}, user);
|
|
224
224
|
user1.client.clientId = 'test1';
|
|
225
225
|
channel.addUser(user1);
|
|
226
|
-
const user2 = {
|
|
226
|
+
const user2 = Object.assign({}, user);
|
|
227
227
|
user2.client.clientId = 'test2';
|
|
228
228
|
channel.addUser(user2);
|
|
229
229
|
expect(channel.info.presence.length).toBe(2);
|
package/pondSocket/endpoint.js
CHANGED
|
@@ -66,10 +66,7 @@ class Endpoint extends pondBase_1.BaseClass {
|
|
|
66
66
|
*/
|
|
67
67
|
authoriseConnection(request, socket, head, data) {
|
|
68
68
|
const doc = this._sockets.createGenericDocument();
|
|
69
|
-
const req = {
|
|
70
|
-
headers: request.headers,
|
|
71
|
-
...data, clientId: doc.id
|
|
72
|
-
};
|
|
69
|
+
const req = Object.assign(Object.assign({ headers: request.headers }, data), { clientId: doc.id });
|
|
73
70
|
const resolver = (assigns, data) => {
|
|
74
71
|
if (data.error) {
|
|
75
72
|
socket.write(`HTTP/1.1 ${data.error.code} ${data.error.message}\r\n\r\n`);
|
|
@@ -1,4 +1,13 @@
|
|
|
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
|
+
};
|
|
2
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
13
|
};
|
|
@@ -23,7 +32,7 @@ describe('endpoint', () => {
|
|
|
23
32
|
expect(new endpoint_1.Endpoint(socketServer, handler)).toBeInstanceOf(endpoint_1.Endpoint);
|
|
24
33
|
});
|
|
25
34
|
// Functionality tests
|
|
26
|
-
it('should be able to close a socket',
|
|
35
|
+
it('should be able to close a socket', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
36
|
const { socket, server } = createPondSocket();
|
|
28
37
|
expect(server).toBeDefined();
|
|
29
38
|
const endpoint = socket.createEndpoint('/api/:path', (req, res) => {
|
|
@@ -33,14 +42,14 @@ describe('endpoint', () => {
|
|
|
33
42
|
endpoint.closeConnection(req.clientId);
|
|
34
43
|
}, 100);
|
|
35
44
|
});
|
|
36
|
-
|
|
45
|
+
yield (0, superwstest_1.default)(server)
|
|
37
46
|
.ws('/api/socket')
|
|
38
47
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
39
48
|
.wait(200)
|
|
40
49
|
.expectClosed();
|
|
41
50
|
server.close();
|
|
42
|
-
});
|
|
43
|
-
it('should be able to list connections',
|
|
51
|
+
}));
|
|
52
|
+
it('should be able to list connections', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
53
|
const { socket, server } = createPondSocket();
|
|
45
54
|
let connectionsCount = 0;
|
|
46
55
|
expect(server).toBeDefined();
|
|
@@ -49,17 +58,17 @@ describe('endpoint', () => {
|
|
|
49
58
|
connectionsCount = endpoint.listConnections().length;
|
|
50
59
|
res.accept();
|
|
51
60
|
});
|
|
52
|
-
|
|
61
|
+
yield (0, superwstest_1.default)(server)
|
|
53
62
|
.ws('/api/socket')
|
|
54
63
|
.expectUpgrade(res => expect(res.statusCode).toBe(101));
|
|
55
|
-
|
|
64
|
+
yield (0, superwstest_1.default)(server)
|
|
56
65
|
.ws('/api/socket')
|
|
57
66
|
.expectUpgrade(res => expect(res.statusCode).toBe(101));
|
|
58
67
|
server.close(); // Close the server to stop the connection from being kept alive
|
|
59
68
|
expect(connectionsCount).toBe(1);
|
|
60
69
|
expect(endpoint.listConnections().length).toBe(2); // The connections are still in the list
|
|
61
|
-
});
|
|
62
|
-
it('should be capable of sending messages to all clients',
|
|
70
|
+
}));
|
|
71
|
+
it('should be capable of sending messages to all clients', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
63
72
|
const { socket, server } = createPondSocket();
|
|
64
73
|
expect(server).toBeDefined();
|
|
65
74
|
let users = 0;
|
|
@@ -69,7 +78,7 @@ describe('endpoint', () => {
|
|
|
69
78
|
if (users > 0)
|
|
70
79
|
endpoint.broadcast('TEST', { message: 'Hello everyone' });
|
|
71
80
|
});
|
|
72
|
-
|
|
81
|
+
yield (0, superwstest_1.default)(server)
|
|
73
82
|
.ws('/api/socket')
|
|
74
83
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
75
84
|
.expectJson({
|
|
@@ -82,7 +91,7 @@ describe('endpoint', () => {
|
|
|
82
91
|
message: 'Hello everyone'
|
|
83
92
|
}
|
|
84
93
|
});
|
|
85
|
-
|
|
94
|
+
yield (0, superwstest_1.default)(server)
|
|
86
95
|
.ws('/api/secondSocket')
|
|
87
96
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
88
97
|
.expectJson({
|
|
@@ -96,8 +105,8 @@ describe('endpoint', () => {
|
|
|
96
105
|
}
|
|
97
106
|
});
|
|
98
107
|
server.close();
|
|
99
|
-
});
|
|
100
|
-
it('should be able to accept connections on this handler',
|
|
108
|
+
}));
|
|
109
|
+
it('should be able to accept connections on this handler', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
101
110
|
const { socket, server } = createPondSocket();
|
|
102
111
|
expect(server).toBeDefined();
|
|
103
112
|
const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
|
|
@@ -122,22 +131,20 @@ describe('endpoint', () => {
|
|
|
122
131
|
const message = {
|
|
123
132
|
action: enums_1.ClientActions.JOIN_CHANNEL, channelName: '/test/socket', event: 'TEST', payload: {}
|
|
124
133
|
};
|
|
125
|
-
|
|
134
|
+
yield (0, superwstest_1.default)(server)
|
|
126
135
|
.ws('/api/socket')
|
|
127
136
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
128
137
|
.sendJson(message)
|
|
129
138
|
.expectJson(); // receives a presence message, this can not be matched because the payload is dynamic
|
|
130
|
-
|
|
139
|
+
yield (0, superwstest_1.default)(server)
|
|
131
140
|
.ws('/api/socket')
|
|
132
141
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
133
|
-
.sendJson({
|
|
134
|
-
...message, channelName: '/socket/socket'
|
|
135
|
-
})
|
|
142
|
+
.sendJson(Object.assign(Object.assign({}, message), { channelName: '/socket/socket' }))
|
|
136
143
|
.expectJson(); // receives a presence message, this can not be matched because the payload is dynamic
|
|
137
144
|
expect([...endpoint['_channels'].generator()]).toHaveLength(2);
|
|
138
145
|
server.close();
|
|
139
|
-
});
|
|
140
|
-
it('should refuse connections if there are no handlers',
|
|
146
|
+
}));
|
|
147
|
+
it('should refuse connections if there are no handlers', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
141
148
|
const { socket, server } = createPondSocket();
|
|
142
149
|
expect(server).toBeDefined();
|
|
143
150
|
const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
|
|
@@ -154,22 +161,21 @@ describe('endpoint', () => {
|
|
|
154
161
|
const message = {
|
|
155
162
|
action: enums_1.ClientActions.JOIN_CHANNEL, channelName: '/test/socket', event: 'TEST', payload: {}
|
|
156
163
|
};
|
|
157
|
-
|
|
164
|
+
yield (0, superwstest_1.default)(server)
|
|
158
165
|
.ws('/api/socket')
|
|
159
166
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
160
167
|
.sendJson(message)
|
|
161
168
|
.expectJson(); // receives a presence message, this can not be matched because the payload is dynamic
|
|
162
|
-
|
|
169
|
+
yield (0, superwstest_1.default)(server)
|
|
163
170
|
.ws('/api/socket')
|
|
164
171
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
165
|
-
.sendJson({
|
|
166
|
-
|
|
167
|
-
})
|
|
172
|
+
.sendJson(Object.assign(Object.assign({}, message), { channelName: '/socket/socket' // This channel handler does not exist
|
|
173
|
+
}))
|
|
168
174
|
.expectJson(); // receives a presence message, this can not be matched because the payload is dynamic
|
|
169
175
|
expect([...endpoint['_channels'].generator()]).toHaveLength(1);
|
|
170
176
|
server.close();
|
|
171
|
-
});
|
|
172
|
-
it('should send an error when we send an incomplete message',
|
|
177
|
+
}));
|
|
178
|
+
it('should send an error when we send an incomplete message', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
173
179
|
const { socket, server } = createPondSocket();
|
|
174
180
|
expect(server).toBeDefined();
|
|
175
181
|
const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
|
|
@@ -186,7 +192,7 @@ describe('endpoint', () => {
|
|
|
186
192
|
const message = {
|
|
187
193
|
action: enums_1.ClientActions.LEAVE_CHANNEL, channelName: '/test/socket', event: 'TEST', payload: {}
|
|
188
194
|
};
|
|
189
|
-
|
|
195
|
+
yield (0, superwstest_1.default)(server)
|
|
190
196
|
.ws('/api/socket')
|
|
191
197
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
192
198
|
.sendJson(message)
|
|
@@ -198,12 +204,10 @@ describe('endpoint', () => {
|
|
|
198
204
|
message: "Channel /test/socket does not exist"
|
|
199
205
|
}
|
|
200
206
|
});
|
|
201
|
-
|
|
207
|
+
yield (0, superwstest_1.default)(server)
|
|
202
208
|
.ws('/api/socket')
|
|
203
209
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
204
|
-
.sendJson({
|
|
205
|
-
...message, action: null
|
|
206
|
-
})
|
|
210
|
+
.sendJson(Object.assign(Object.assign({}, message), { action: null }))
|
|
207
211
|
.expectJson({
|
|
208
212
|
action: enums_1.ServerActions.ERROR,
|
|
209
213
|
event: "error",
|
|
@@ -212,12 +216,10 @@ describe('endpoint', () => {
|
|
|
212
216
|
message: "No action provided",
|
|
213
217
|
}
|
|
214
218
|
});
|
|
215
|
-
|
|
219
|
+
yield (0, superwstest_1.default)(server)
|
|
216
220
|
.ws('/api/socket')
|
|
217
221
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
218
|
-
.sendJson({
|
|
219
|
-
...message, action: enums_1.ClientActions.BROADCAST, channelName: null
|
|
220
|
-
})
|
|
222
|
+
.sendJson(Object.assign(Object.assign({}, message), { action: enums_1.ClientActions.BROADCAST, channelName: null }))
|
|
221
223
|
.expectJson({
|
|
222
224
|
action: enums_1.ServerActions.ERROR,
|
|
223
225
|
event: "error",
|
|
@@ -226,12 +228,10 @@ describe('endpoint', () => {
|
|
|
226
228
|
message: "No channel name provided",
|
|
227
229
|
}
|
|
228
230
|
});
|
|
229
|
-
|
|
231
|
+
yield (0, superwstest_1.default)(server)
|
|
230
232
|
.ws('/api/socket')
|
|
231
233
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
232
|
-
.sendJson({
|
|
233
|
-
...message, action: enums_1.ClientActions.BROADCAST_FROM, payload: null
|
|
234
|
-
})
|
|
234
|
+
.sendJson(Object.assign(Object.assign({}, message), { action: enums_1.ClientActions.BROADCAST_FROM, payload: null }))
|
|
235
235
|
.expectJson({
|
|
236
236
|
action: enums_1.ServerActions.ERROR,
|
|
237
237
|
event: "error",
|
|
@@ -241,7 +241,7 @@ describe('endpoint', () => {
|
|
|
241
241
|
}
|
|
242
242
|
});
|
|
243
243
|
// send incorrect Json message
|
|
244
|
-
|
|
244
|
+
yield (0, superwstest_1.default)(server)
|
|
245
245
|
.ws('/api/socket')
|
|
246
246
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
247
247
|
.send('"action": "JOIN_CHANNEL", "channelName": "/test/socket", "event": "TEST", "payload": {}}')
|
|
@@ -255,8 +255,8 @@ describe('endpoint', () => {
|
|
|
255
255
|
});
|
|
256
256
|
expect([...endpoint['_channels'].generator()]).toHaveLength(1);
|
|
257
257
|
server.close();
|
|
258
|
-
});
|
|
259
|
-
it('should send an error when the channel exists but other things happen',
|
|
258
|
+
}));
|
|
259
|
+
it('should send an error when the channel exists but other things happen', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
260
260
|
const { socket, server } = createPondSocket();
|
|
261
261
|
expect(server).toBeDefined();
|
|
262
262
|
const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
|
|
@@ -282,28 +282,22 @@ describe('endpoint', () => {
|
|
|
282
282
|
const message = {
|
|
283
283
|
action: enums_1.ClientActions.JOIN_CHANNEL, channelName: '/test/socket', event: 'TEST', payload: {}
|
|
284
284
|
};
|
|
285
|
-
|
|
285
|
+
yield (0, superwstest_1.default)(server)
|
|
286
286
|
.ws('/api/socket')
|
|
287
287
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
288
288
|
.sendJson(message)
|
|
289
289
|
.expectJson() // receives a presence message, this can not be matched because the payload is dynamic
|
|
290
|
-
.sendJson({
|
|
291
|
-
...message, event: '/test/TEST2', action: enums_1.ClientActions.BROADCAST,
|
|
292
|
-
})
|
|
290
|
+
.sendJson(Object.assign(Object.assign({}, message), { event: '/test/TEST2', action: enums_1.ClientActions.BROADCAST }))
|
|
293
291
|
.expectJson({
|
|
294
292
|
action: "ERROR", event: "error", channelName: "/test/socket", payload: {
|
|
295
293
|
message: "Message rejected", code: 403
|
|
296
294
|
}
|
|
297
295
|
})
|
|
298
|
-
.sendJson({
|
|
299
|
-
...message, channelName: "/test/socket", action: enums_1.ClientActions.BROADCAST,
|
|
300
|
-
})
|
|
296
|
+
.sendJson(Object.assign(Object.assign({}, message), { channelName: "/test/socket", action: enums_1.ClientActions.BROADCAST }))
|
|
301
297
|
.expectJson({
|
|
302
298
|
action: enums_1.ServerActions.MESSAGE, payload: {}, event: "TEST", channelName: "/test/socket"
|
|
303
299
|
})
|
|
304
|
-
.sendJson({
|
|
305
|
-
...message, action: enums_1.ClientActions.SEND_MESSAGE_TO_USER,
|
|
306
|
-
})
|
|
300
|
+
.sendJson(Object.assign(Object.assign({}, message), { action: enums_1.ClientActions.SEND_MESSAGE_TO_USER }))
|
|
307
301
|
.expectJson({
|
|
308
302
|
action: enums_1.ServerActions.ERROR,
|
|
309
303
|
event: "error",
|
|
@@ -314,8 +308,8 @@ describe('endpoint', () => {
|
|
|
314
308
|
});
|
|
315
309
|
expect(endpoint.listChannels()).toHaveLength(1);
|
|
316
310
|
server.close();
|
|
317
|
-
});
|
|
318
|
-
it('should be capable of sending messages to a specific user',
|
|
311
|
+
}));
|
|
312
|
+
it('should be capable of sending messages to a specific user', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
319
313
|
const { socket, server } = createPondSocket();
|
|
320
314
|
expect(server).toBeDefined();
|
|
321
315
|
const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
|
|
@@ -341,22 +335,20 @@ describe('endpoint', () => {
|
|
|
341
335
|
const message = {
|
|
342
336
|
action: enums_1.ClientActions.JOIN_CHANNEL, channelName: '/test/socket', event: 'TEST', payload: {}
|
|
343
337
|
};
|
|
344
|
-
|
|
338
|
+
yield (0, superwstest_1.default)(server)
|
|
345
339
|
.ws('/api/socket')
|
|
346
340
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
347
341
|
.sendJson(message)
|
|
348
342
|
.expectJson() // receives a presence message, this can not be matched because the payload is dynamic
|
|
349
|
-
.sendJson({
|
|
350
|
-
...message, action: enums_1.ClientActions.BROADCAST_FROM, payload: {
|
|
343
|
+
.sendJson(Object.assign(Object.assign({}, message), { action: enums_1.ClientActions.BROADCAST_FROM, payload: {
|
|
351
344
|
message: {
|
|
352
345
|
action: enums_1.ServerActions.MESSAGE, payload: {}, event: "TEST", channelName: "/test/socket"
|
|
353
346
|
}
|
|
354
|
-
}
|
|
355
|
-
});
|
|
347
|
+
} }));
|
|
356
348
|
expect(endpoint.listChannels()).toHaveLength(1);
|
|
357
349
|
server.close();
|
|
358
|
-
});
|
|
359
|
-
it('should be able to update user presence on user demand',
|
|
350
|
+
}));
|
|
351
|
+
it('should be able to update user presence on user demand', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
360
352
|
const { socket, server } = createPondSocket();
|
|
361
353
|
expect(server).toBeDefined();
|
|
362
354
|
const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
|
|
@@ -369,22 +361,18 @@ describe('endpoint', () => {
|
|
|
369
361
|
const message = {
|
|
370
362
|
action: enums_1.ClientActions.JOIN_CHANNEL, channelName: '/test/socket', event: 'TEST', payload: {}
|
|
371
363
|
};
|
|
372
|
-
|
|
364
|
+
yield (0, superwstest_1.default)(server)
|
|
373
365
|
.ws('/api/socket')
|
|
374
366
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
375
367
|
.sendJson(message)
|
|
376
368
|
.expectJson() // receives a presence message, this can not be matched because the payload is dynamic
|
|
377
|
-
.sendJson({
|
|
378
|
-
...message, action: enums_1.ClientActions.UPDATE_PRESENCE, payload: {
|
|
369
|
+
.sendJson(Object.assign(Object.assign({}, message), { action: enums_1.ClientActions.UPDATE_PRESENCE, payload: {
|
|
379
370
|
presence: {
|
|
380
371
|
status: 'online'
|
|
381
372
|
}
|
|
382
|
-
}
|
|
383
|
-
})
|
|
373
|
+
} }))
|
|
384
374
|
.expectJson() // receives a presence message, this can not be matched because the payload is dynamic
|
|
385
|
-
.sendJson({
|
|
386
|
-
...message, action: enums_1.ClientActions.SEND_MESSAGE_TO_USER, addresses: [], payload: {}
|
|
387
|
-
})
|
|
375
|
+
.sendJson(Object.assign(Object.assign({}, message), { action: enums_1.ClientActions.SEND_MESSAGE_TO_USER, addresses: [], payload: {} }))
|
|
388
376
|
.expectJson({
|
|
389
377
|
action: enums_1.ServerActions.ERROR,
|
|
390
378
|
event: "error",
|
|
@@ -393,9 +381,7 @@ describe('endpoint', () => {
|
|
|
393
381
|
message: "Error while executing event 'TEST' on channel '/test/socket': No addresses provided"
|
|
394
382
|
}
|
|
395
383
|
})
|
|
396
|
-
.sendJson({
|
|
397
|
-
...message, action: enums_1.ClientActions.SEND_MESSAGE_TO_USER, addresses: ['hello'], payload: {}
|
|
398
|
-
})
|
|
384
|
+
.sendJson(Object.assign(Object.assign({}, message), { action: enums_1.ClientActions.SEND_MESSAGE_TO_USER, addresses: ['hello'], payload: {} }))
|
|
399
385
|
.expectJson({
|
|
400
386
|
action: enums_1.ServerActions.ERROR,
|
|
401
387
|
event: "error",
|
|
@@ -404,32 +390,25 @@ describe('endpoint', () => {
|
|
|
404
390
|
message: "Error while executing event 'TEST' on channel '/test/socket': Client(s) with clientId(s) hello were not found in channel /test/socket"
|
|
405
391
|
}
|
|
406
392
|
})
|
|
407
|
-
.sendJson({
|
|
408
|
-
...message, action: enums_1.ClientActions.UPDATE_PRESENCE, payload: {
|
|
393
|
+
.sendJson(Object.assign(Object.assign({}, message), { action: enums_1.ClientActions.UPDATE_PRESENCE, payload: {
|
|
409
394
|
assigns: {
|
|
410
395
|
status: 'online'
|
|
411
396
|
}
|
|
412
|
-
}
|
|
413
|
-
})
|
|
397
|
+
} }))
|
|
414
398
|
.close()
|
|
415
399
|
.expectClosed();
|
|
416
400
|
expect(endpoint.listChannels()).toHaveLength(1); // the channel has not been removed yet
|
|
417
|
-
|
|
401
|
+
yield (0, superwstest_1.default)(server)
|
|
418
402
|
.ws('/api/newSocket')
|
|
419
403
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
420
|
-
.sendJson({
|
|
421
|
-
...message, channelName: '/test/socket2',
|
|
422
|
-
})
|
|
404
|
+
.sendJson(Object.assign(Object.assign({}, message), { channelName: '/test/socket2' }))
|
|
423
405
|
.expectJson() // receives a presence message, this can not be matched because the payload is dynamic
|
|
424
|
-
.sendJson({
|
|
425
|
-
...message, action: enums_1.ClientActions.LEAVE_CHANNEL,
|
|
426
|
-
channelName: '/test/socket2',
|
|
427
|
-
})
|
|
406
|
+
.sendJson(Object.assign(Object.assign({}, message), { action: enums_1.ClientActions.LEAVE_CHANNEL, channelName: '/test/socket2' }))
|
|
428
407
|
.expectJson();
|
|
429
408
|
expect(endpoint.listChannels()).toHaveLength(0); // by now the first channel should have been removed; and since we gracefully closed the connection, the second channel should have been removed as well
|
|
430
409
|
server.close();
|
|
431
|
-
});
|
|
432
|
-
it('should ba able to send messages to a specific user',
|
|
410
|
+
}));
|
|
411
|
+
it('should ba able to send messages to a specific user', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
433
412
|
const { socket, server } = createPondSocket();
|
|
434
413
|
expect(server).toBeDefined();
|
|
435
414
|
const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
|
|
@@ -448,18 +427,16 @@ describe('endpoint', () => {
|
|
|
448
427
|
const message = {
|
|
449
428
|
action: enums_1.ClientActions.JOIN_CHANNEL, channelName: '/test/socket', event: 'TEST', payload: {}
|
|
450
429
|
};
|
|
451
|
-
|
|
430
|
+
yield (0, superwstest_1.default)(server)
|
|
452
431
|
.ws('/api/socket')
|
|
453
432
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
454
433
|
.sendJson(message)
|
|
455
434
|
.expectJson() // receives a presence message, this can not be matched because the payload is dynamic
|
|
456
|
-
.sendJson({
|
|
457
|
-
...message, action: enums_1.ClientActions.BROADCAST_FROM, payload: {
|
|
435
|
+
.sendJson(Object.assign(Object.assign({}, message), { action: enums_1.ClientActions.BROADCAST_FROM, payload: {
|
|
458
436
|
message: {
|
|
459
437
|
action: enums_1.ServerActions.MESSAGE, payload: {}, event: "TEST", channelName: "/test/socket"
|
|
460
438
|
}
|
|
461
|
-
}
|
|
462
|
-
}).expectJson({
|
|
439
|
+
} })).expectJson({
|
|
463
440
|
action: enums_1.ServerActions.MESSAGE,
|
|
464
441
|
event: 'Test', channelName: enums_1.PondSenders.ENDPOINT,
|
|
465
442
|
payload: {
|
|
@@ -468,8 +445,8 @@ describe('endpoint', () => {
|
|
|
468
445
|
});
|
|
469
446
|
expect(endpoint.listChannels()).toHaveLength(1);
|
|
470
447
|
server.close();
|
|
471
|
-
});
|
|
472
|
-
it('should be able ot manage error from the client side',
|
|
448
|
+
}));
|
|
449
|
+
it('should be able ot manage error from the client side', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
473
450
|
const { socket, server } = createPondSocket();
|
|
474
451
|
expect(server).toBeDefined();
|
|
475
452
|
const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
|
|
@@ -496,7 +473,7 @@ describe('endpoint', () => {
|
|
|
496
473
|
}
|
|
497
474
|
};
|
|
498
475
|
try {
|
|
499
|
-
|
|
476
|
+
yield (0, superwstest_1.default)(server)
|
|
500
477
|
.ws('/api/socket')
|
|
501
478
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
502
479
|
.sendJson(message)
|
|
@@ -509,5 +486,5 @@ describe('endpoint', () => {
|
|
|
509
486
|
expect(endpoint.listChannels()).toHaveLength(0); // the socket should have been removed
|
|
510
487
|
expect(endpoint['_findChannel']('/test/socket')).toBeUndefined();
|
|
511
488
|
server.close();
|
|
512
|
-
});
|
|
489
|
+
}));
|
|
513
490
|
});
|
|
@@ -68,11 +68,7 @@ class PondChannel extends pondBase_1.BaseClass {
|
|
|
68
68
|
document.removeDoc();
|
|
69
69
|
return response.reject(`Invalid channel name: ${channelName}`);
|
|
70
70
|
}
|
|
71
|
-
const request = {
|
|
72
|
-
joinParams, ...resolved,
|
|
73
|
-
clientId: user.clientId, channelName,
|
|
74
|
-
clientAssigns: user.assigns
|
|
75
|
-
};
|
|
71
|
+
const request = Object.assign(Object.assign({ joinParams }, resolved), { clientId: user.clientId, channelName, clientAssigns: user.assigns });
|
|
76
72
|
this._handler(request, response, channel);
|
|
77
73
|
if (channel.presence.length === 0)
|
|
78
74
|
document.removeDoc();
|
|
@@ -207,11 +203,7 @@ class PondChannel extends pondBase_1.BaseClass {
|
|
|
207
203
|
const info = this.generateEventRequest(event, data.event);
|
|
208
204
|
if (!info)
|
|
209
205
|
return;
|
|
210
|
-
const req = {
|
|
211
|
-
...data,
|
|
212
|
-
params: info.params,
|
|
213
|
-
query: info.query,
|
|
214
|
-
};
|
|
206
|
+
const req = Object.assign(Object.assign({}, data), { params: info.params, query: info.query });
|
|
215
207
|
callback(req, res, channel);
|
|
216
208
|
});
|
|
217
209
|
}
|
|
@@ -1,4 +1,13 @@
|
|
|
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
|
+
};
|
|
2
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
13
|
};
|
|
@@ -75,7 +84,7 @@ describe('server', () => {
|
|
|
75
84
|
expect(socketClient.write).toHaveBeenCalled();
|
|
76
85
|
expect(socketClient.destroy).toHaveBeenCalled();
|
|
77
86
|
});
|
|
78
|
-
it('should be able to accept a socket if a handler is provided',
|
|
87
|
+
it('should be able to accept a socket if a handler is provided', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
79
88
|
const socket = new pondSocket_1.PondSocket();
|
|
80
89
|
const server = socket.listen(3001, () => {
|
|
81
90
|
console.log('server listening');
|
|
@@ -88,14 +97,14 @@ describe('server', () => {
|
|
|
88
97
|
expect(req.params.path).toBe('socket');
|
|
89
98
|
res.accept();
|
|
90
99
|
});
|
|
91
|
-
|
|
100
|
+
yield (0, superwstest_1.default)(server)
|
|
92
101
|
.ws('/api/socket')
|
|
93
102
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
94
103
|
.close()
|
|
95
104
|
.expectClosed();
|
|
96
105
|
server.close();
|
|
97
|
-
});
|
|
98
|
-
it('should be able to reject a socket if the handler rejects',
|
|
106
|
+
}));
|
|
107
|
+
it('should be able to reject a socket if the handler rejects', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
99
108
|
const socket = new pondSocket_1.PondSocket();
|
|
100
109
|
const server = socket.listen(3001, () => {
|
|
101
110
|
console.log('server listening');
|
|
@@ -105,12 +114,12 @@ describe('server', () => {
|
|
|
105
114
|
expect(req.params.path).toBe('socket');
|
|
106
115
|
res.reject();
|
|
107
116
|
});
|
|
108
|
-
|
|
117
|
+
yield (0, superwstest_1.default)(server)
|
|
109
118
|
.ws('/api/socket')
|
|
110
119
|
.expectConnectionError();
|
|
111
120
|
server.close();
|
|
112
|
-
});
|
|
113
|
-
it('should be able to send a message after connection',
|
|
121
|
+
}));
|
|
122
|
+
it('should be able to send a message after connection', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
114
123
|
const socket = new pondSocket_1.PondSocket();
|
|
115
124
|
const server = socket.listen(3001, () => {
|
|
116
125
|
console.log('server listening');
|
|
@@ -120,7 +129,7 @@ describe('server', () => {
|
|
|
120
129
|
expect(req.params.path).toBe('socket');
|
|
121
130
|
res.send('testEvent', { test: 'test' });
|
|
122
131
|
});
|
|
123
|
-
|
|
132
|
+
yield (0, superwstest_1.default)(server)
|
|
124
133
|
.ws('/api/socket')
|
|
125
134
|
.expectUpgrade(res => expect(res.statusCode).toBe(101))
|
|
126
135
|
.expectJson({
|
|
@@ -132,5 +141,5 @@ describe('server', () => {
|
|
|
132
141
|
.close()
|
|
133
142
|
.expectClosed();
|
|
134
143
|
server.close();
|
|
135
|
-
});
|
|
144
|
+
}));
|
|
136
145
|
});
|