@eleven-am/pondsocket 0.1.0
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/.eslintrc.js +28 -0
- package/.idea/modules.xml +8 -0
- package/.idea/pondsocket.iml +12 -0
- package/LICENSE +674 -0
- package/base.d.ts +1 -0
- package/base.js +17 -0
- package/client.d.ts +1 -0
- package/client.js +17 -0
- package/index.d.ts +1 -0
- package/index.js +17 -0
- package/jest.config.js +11 -0
- package/package.json +48 -0
- package/pondBase/baseClass.d.ts +37 -0
- package/pondBase/baseClass.js +111 -0
- package/pondBase/baseClass.test.js +73 -0
- package/pondBase/enums.d.ts +9 -0
- package/pondBase/enums.js +14 -0
- package/pondBase/index.d.ts +6 -0
- package/pondBase/index.js +22 -0
- package/pondBase/pondBase.d.ts +41 -0
- package/pondBase/pondBase.js +60 -0
- package/pondBase/pondBase.test.js +101 -0
- package/pondBase/pubSub.d.ts +73 -0
- package/pondBase/pubSub.js +138 -0
- package/pondBase/pubSub.test.js +309 -0
- package/pondBase/simpleBase.d.ts +131 -0
- package/pondBase/simpleBase.js +211 -0
- package/pondBase/simpleBase.test.js +153 -0
- package/pondBase/types.d.ts +2 -0
- package/pondBase/types.js +2 -0
- package/pondClient/channel.d.ts +66 -0
- package/pondClient/channel.js +152 -0
- package/pondClient/index.d.ts +2 -0
- package/pondClient/index.js +18 -0
- package/pondClient/socket.d.ts +42 -0
- package/pondClient/socket.js +116 -0
- package/pondSocket/channel.d.ts +134 -0
- package/pondSocket/channel.js +287 -0
- package/pondSocket/channel.test.js +377 -0
- package/pondSocket/channelMiddleWare.d.ts +26 -0
- package/pondSocket/channelMiddleWare.js +36 -0
- package/pondSocket/endpoint.d.ts +90 -0
- package/pondSocket/endpoint.js +323 -0
- package/pondSocket/endpoint.test.js +513 -0
- package/pondSocket/enums.d.ts +19 -0
- package/pondSocket/enums.js +25 -0
- package/pondSocket/index.d.ts +7 -0
- package/pondSocket/index.js +23 -0
- package/pondSocket/pondChannel.d.ts +79 -0
- package/pondSocket/pondChannel.js +219 -0
- package/pondSocket/pondChannel.test.js +430 -0
- package/pondSocket/pondResponse.d.ts +25 -0
- package/pondSocket/pondResponse.js +120 -0
- package/pondSocket/pondSocket.d.ts +47 -0
- package/pondSocket/pondSocket.js +94 -0
- package/pondSocket/server.test.js +136 -0
- package/pondSocket/socketMiddleWare.d.ts +6 -0
- package/pondSocket/socketMiddleWare.js +32 -0
- package/pondSocket/types.d.ts +74 -0
- package/pondSocket/types.js +2 -0
- package/socket.d.ts +1 -0
- package/socket.js +17 -0
- package/tsconfig.eslint.json +5 -0
- package/tsconfig.json +90 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PondClient = void 0;
|
|
4
|
+
const webSocket_1 = require("rxjs/webSocket");
|
|
5
|
+
const rxjs_1 = require("rxjs");
|
|
6
|
+
const channel_1 = require("./channel");
|
|
7
|
+
const operators_1 = require("rxjs/operators");
|
|
8
|
+
const pondBase_1 = require("../pondBase");
|
|
9
|
+
class PondClient {
|
|
10
|
+
constructor(endpoint, params) {
|
|
11
|
+
this.socketState = "CLOSED";
|
|
12
|
+
/**
|
|
13
|
+
* @desc A retry strategy for the socket.
|
|
14
|
+
* @param maxTries - The maximum number of retries.
|
|
15
|
+
* @param ms - The number of milliseconds to wait before retrying.
|
|
16
|
+
*/
|
|
17
|
+
this._retryStrategy = (maxTries, ms) => {
|
|
18
|
+
return (0, rxjs_1.pipe)((0, operators_1.retryWhen)(attempts => {
|
|
19
|
+
const observableForRetries = (0, rxjs_1.zip)((0, rxjs_1.range)(1, maxTries), attempts)
|
|
20
|
+
.pipe((0, operators_1.map)(([elemFromRange]) => elemFromRange), (0, operators_1.map)(i => i * i), (0, rxjs_1.switchMap)(i => (0, rxjs_1.timer)(i * ms)));
|
|
21
|
+
const observableForFailure = (0, rxjs_1.throwError)(new Error("Could not connect to server"))
|
|
22
|
+
.pipe((0, rxjs_1.materialize)(), (0, rxjs_1.delay)(1000), (0, rxjs_1.dematerialize)());
|
|
23
|
+
return (0, rxjs_1.concat)(observableForRetries, observableForFailure);
|
|
24
|
+
}));
|
|
25
|
+
};
|
|
26
|
+
let address;
|
|
27
|
+
try {
|
|
28
|
+
address = new URL(endpoint);
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
address = new URL(window.location.toString());
|
|
32
|
+
address.pathname = endpoint;
|
|
33
|
+
}
|
|
34
|
+
const query = new URLSearchParams(params);
|
|
35
|
+
address.search = query.toString();
|
|
36
|
+
const protocol = address.protocol === "https:" ? "wss:" : "ws:";
|
|
37
|
+
if (address.protocol !== "wss:" && address.protocol !== "ws:")
|
|
38
|
+
address.protocol = protocol;
|
|
39
|
+
this.address = address;
|
|
40
|
+
this.channels = new pondBase_1.PondBase();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* @desc Connects to the server and returns the socket.
|
|
44
|
+
*/
|
|
45
|
+
connect() {
|
|
46
|
+
if (this.socketState !== "CLOSED")
|
|
47
|
+
return;
|
|
48
|
+
this.socketState = "CONNECTING";
|
|
49
|
+
const socket = (0, webSocket_1.webSocket)({
|
|
50
|
+
url: this.address.toString(),
|
|
51
|
+
openObserver: {
|
|
52
|
+
next: () => {
|
|
53
|
+
this.socketState = "OPEN";
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
closeObserver: {
|
|
57
|
+
next: () => {
|
|
58
|
+
this.socketState = "CLOSED";
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
closingObserver: {
|
|
62
|
+
next: () => {
|
|
63
|
+
this.socketState = "CLOSING";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
this.socket = socket;
|
|
68
|
+
this.subscription = socket.pipe(this._retryStrategy(100, 1000)).subscribe();
|
|
69
|
+
return this;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* @desc Returns the current state of the socket.
|
|
73
|
+
*/
|
|
74
|
+
getState() {
|
|
75
|
+
return this.socketState;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* @desc Creates a channel with the given name and params.
|
|
79
|
+
* @param channel - The name of the channel.
|
|
80
|
+
* @param params - The params to send to the server.
|
|
81
|
+
*/
|
|
82
|
+
createChannel(channel, params) {
|
|
83
|
+
const channelDoc = this.channels.get(channel);
|
|
84
|
+
if (channelDoc)
|
|
85
|
+
return channelDoc.doc;
|
|
86
|
+
if (this.socket) {
|
|
87
|
+
const newChannel = new channel_1.Channel(channel, params || {}, this.socket);
|
|
88
|
+
this.channels.set(channel, newChannel);
|
|
89
|
+
return newChannel;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* @desc An event that is triggered when the socket receives a message.
|
|
95
|
+
* @param callback - The callback to be called when the event is triggered.
|
|
96
|
+
*/
|
|
97
|
+
onMessage(callback) {
|
|
98
|
+
var _a;
|
|
99
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.subscribe(data => {
|
|
100
|
+
if (data.event)
|
|
101
|
+
callback(data.event, data.payload);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* @desc Disconnects the socket from the server.
|
|
106
|
+
*/
|
|
107
|
+
disconnect() {
|
|
108
|
+
var _a, _b, _c;
|
|
109
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.complete();
|
|
110
|
+
(_b = this.socket) === null || _b === void 0 ? void 0 : _b.unsubscribe();
|
|
111
|
+
(_c = this.subscription) === null || _c === void 0 ? void 0 : _c.unsubscribe();
|
|
112
|
+
this.socket = undefined;
|
|
113
|
+
this.channels = new pondBase_1.PondBase();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.PondClient = PondClient;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import {BaseClass, default_t, PondDocument, Subscription} from "../pondBase";
|
|
2
|
+
import {NewUser, PondAssigns, PondChannelData, PondMessage, PondPresence, ServerMessage} from "./types";
|
|
3
|
+
import {PondSenders, ServerActions} from "./enums";
|
|
4
|
+
import {ChannelHandler} from "./channelMiddleWare";
|
|
5
|
+
|
|
6
|
+
export interface ChannelInfo {
|
|
7
|
+
name: string;
|
|
8
|
+
channelData: PondChannelData;
|
|
9
|
+
presence: PondPresence[];
|
|
10
|
+
assigns: PondPresence[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface PondUser {
|
|
14
|
+
presence: PondDocument<PondPresence>;
|
|
15
|
+
assigns: PondDocument<PondAssigns>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export declare class Channel extends BaseClass {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @desc Returns the channel info
|
|
23
|
+
*/
|
|
24
|
+
get info(): Readonly<ChannelInfo>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @desc Gets the channel's data
|
|
28
|
+
*/
|
|
29
|
+
get data(): Readonly<PondChannelData>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @desc Sets the channel's data
|
|
33
|
+
* @param data
|
|
34
|
+
*/
|
|
35
|
+
set data(data: PondChannelData);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @desc Gets the channel's presence
|
|
39
|
+
*/
|
|
40
|
+
get presence(): PondPresence[];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @desc Gets the channel's assigns
|
|
44
|
+
*/
|
|
45
|
+
get assigns(): PondAssigns[];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @desc Gets a user's information
|
|
49
|
+
* @param clientId - The clientId of the user
|
|
50
|
+
*/
|
|
51
|
+
getUserInfo(clientId: string): {
|
|
52
|
+
presence: PondPresence;
|
|
53
|
+
assigns: PondAssigns;
|
|
54
|
+
} | null;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @desc Checks if a user exists in the channel
|
|
58
|
+
* @param clientId - The clientId of the user
|
|
59
|
+
*/
|
|
60
|
+
hasUser(clientId: string): boolean;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @desc Adds a new user to the channel
|
|
64
|
+
* @param user - The user to add to the channel
|
|
65
|
+
*/
|
|
66
|
+
addUser(user: NewUser): void;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @desc Removes a user or group of users from the channel
|
|
70
|
+
* @param clientIds - The clientIds of the users to remove
|
|
71
|
+
*/
|
|
72
|
+
removeUser(clientIds: string | string[]): void;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @desc Subscribes to the presence changes occuring in the channel
|
|
76
|
+
* @param callback - The callback to call when a presence change occurs
|
|
77
|
+
*/
|
|
78
|
+
onPresenceChange(callback: (message: ServerMessage) => void): Subscription;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @desc Subscribes to the message events occuring in the channel
|
|
82
|
+
* @param callback - The callback to call when a message event occurs
|
|
83
|
+
*/
|
|
84
|
+
onMessage(callback: ChannelHandler): void;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @desc Updates the state of a user in the channel
|
|
88
|
+
* @param clientId - The clientId of the user to update
|
|
89
|
+
* @param presence - The new presence of the user
|
|
90
|
+
* @param assigns - The new assigns of the user
|
|
91
|
+
*/
|
|
92
|
+
updateUser(clientId: string, presence: PondPresence, assigns: PondAssigns): void;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @desc Broadcasts a message to all users in the channel
|
|
96
|
+
* @param event - The event name
|
|
97
|
+
* @param message - The message to send
|
|
98
|
+
* @param sender - The sender of the message
|
|
99
|
+
*/
|
|
100
|
+
broadcast(event: string, message: PondMessage, sender?: PondSenders | string): void;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @desc Broadcasts a message to all users in the channel except the sender
|
|
104
|
+
* @param event - The event name
|
|
105
|
+
* @param message - The message to send
|
|
106
|
+
* @param clientId - The client id of the sender
|
|
107
|
+
*/
|
|
108
|
+
broadcastFrom(event: string, message: PondMessage, clientId: string): void;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @desc Sends a message to a specific user or group of users
|
|
112
|
+
* @param event - The event name
|
|
113
|
+
* @param clientId - The client id of the user to send the message to
|
|
114
|
+
* @param message - The message to send
|
|
115
|
+
* @param sender - The client id of the sender
|
|
116
|
+
*/
|
|
117
|
+
sendTo(event: string, message: PondMessage, sender: string, clientId: string | string[]): void;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @desc Subscribes to a channel event, used only by the sockets to subscribe to all events
|
|
121
|
+
* @param clientId - The client id of the user to send the message to
|
|
122
|
+
* @param callback - The callback to call when a message is received
|
|
123
|
+
*/
|
|
124
|
+
subscribeToMessages(clientId: string, callback: (message: ServerMessage) => void): Subscription;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @desc Sends a message to a specific user without running the middleware
|
|
128
|
+
* @param event - The event name
|
|
129
|
+
* @param message - The message to send
|
|
130
|
+
* @param client - The client id of the user to send the message to
|
|
131
|
+
* @param action - The action to send
|
|
132
|
+
*/
|
|
133
|
+
respondToClient(event: string, message: default_t, client: string, action?: ServerActions): void;
|
|
134
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Channel = void 0;
|
|
4
|
+
const pondBase_1 = require("../pondBase");
|
|
5
|
+
const enums_1 = require("./enums");
|
|
6
|
+
const channelMiddleWare_1 = require("./channelMiddleWare");
|
|
7
|
+
class Channel extends pondBase_1.BaseClass {
|
|
8
|
+
constructor(name, middleWare, removeChannel) {
|
|
9
|
+
super();
|
|
10
|
+
this.name = name;
|
|
11
|
+
this._channelPresence = new pondBase_1.PondBase();
|
|
12
|
+
this._channelAssigns = new pondBase_1.SimpleBase();
|
|
13
|
+
this._channelData = {};
|
|
14
|
+
this._middleWare = new channelMiddleWare_1.ChannelMiddleware();
|
|
15
|
+
this.removeChannel = removeChannel;
|
|
16
|
+
this._messages = new pondBase_1.Broadcast();
|
|
17
|
+
this._middleWare.merge(middleWare);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* @desc Returns the channel info
|
|
21
|
+
*/
|
|
22
|
+
get info() {
|
|
23
|
+
const data = {
|
|
24
|
+
name: this.name, channelData: this.data, presence: this.presence, assigns: this.assigns
|
|
25
|
+
};
|
|
26
|
+
return Object.freeze(data);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @desc Gets the channel's data
|
|
30
|
+
*/
|
|
31
|
+
get data() {
|
|
32
|
+
const result = { ...this._channelData };
|
|
33
|
+
return Object.freeze(result);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* @desc Sets the channel's data
|
|
37
|
+
* @param data
|
|
38
|
+
*/
|
|
39
|
+
set data(data) {
|
|
40
|
+
this._channelData = { ...this._channelData, ...data };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* @desc Gets the channel's presence
|
|
44
|
+
*/
|
|
45
|
+
get presence() {
|
|
46
|
+
return this._channelPresence.map(presence => presence);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* @desc Gets the channel's assigns
|
|
50
|
+
*/
|
|
51
|
+
get assigns() {
|
|
52
|
+
return this._channelAssigns.map(assigns => assigns);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* @desc Gets a user's information
|
|
56
|
+
* @param clientId - The clientId of the user
|
|
57
|
+
*/
|
|
58
|
+
getUserInfo(clientId) {
|
|
59
|
+
const client = this._retrieveUser(clientId);
|
|
60
|
+
if (!client)
|
|
61
|
+
return null;
|
|
62
|
+
return {
|
|
63
|
+
presence: client.presence.doc, assigns: client.assigns.doc
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* @desc Checks if a user exists in the channel
|
|
68
|
+
* @param clientId - The clientId of the user
|
|
69
|
+
*/
|
|
70
|
+
hasUser(clientId) {
|
|
71
|
+
return this._channelPresence.has(clientId);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* @desc Adds a new user to the channel
|
|
75
|
+
* @param user - The user to add to the channel
|
|
76
|
+
*/
|
|
77
|
+
addUser(user) {
|
|
78
|
+
const clientId = user.client.clientId;
|
|
79
|
+
if (this.hasUser(clientId))
|
|
80
|
+
throw new Error(`User with clientId ${clientId} already exists in channel ${this.name}`);
|
|
81
|
+
this._channelPresence.set(clientId, { ...user.presence, id: clientId });
|
|
82
|
+
this._channelAssigns.set(clientId, user.assigns);
|
|
83
|
+
this._channelData = Object.assign({ ...this._channelData, ...user.channelData });
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* @desc Removes a user or group of users from the channel
|
|
87
|
+
* @param clientIds - The clientIds of the users to remove
|
|
88
|
+
*/
|
|
89
|
+
removeUser(clientIds) {
|
|
90
|
+
const clients = Array.isArray(clientIds) ? clientIds : [clientIds];
|
|
91
|
+
clients.forEach(clientId => {
|
|
92
|
+
const client = this._retrieveUser(clientId);
|
|
93
|
+
if (client) {
|
|
94
|
+
client.presence.removeDoc();
|
|
95
|
+
client.assigns.removeDoc();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
if (this._channelPresence.size === 0)
|
|
99
|
+
this.removeChannel();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* @desc Subscribes to the presence changes occuring in the channel
|
|
103
|
+
* @param callback - The callback to call when a presence change occurs
|
|
104
|
+
*/
|
|
105
|
+
onPresenceChange(callback) {
|
|
106
|
+
return this._channelPresence.subscribe((docs, change, action) => {
|
|
107
|
+
const message = {
|
|
108
|
+
action: enums_1.ServerActions.PRESENCE,
|
|
109
|
+
payload: { presence: docs, change },
|
|
110
|
+
event: action,
|
|
111
|
+
channelName: this.name,
|
|
112
|
+
};
|
|
113
|
+
callback(message);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* @desc Subscribes to the message events occuring in the channel
|
|
118
|
+
* @param callback - The callback to call when a message event occurs
|
|
119
|
+
*/
|
|
120
|
+
onMessage(callback) {
|
|
121
|
+
this._middleWare.use(callback);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* @desc Updates the state of a user in the channel
|
|
125
|
+
* @param clientId - The clientId of the user to update
|
|
126
|
+
* @param presence - The new presence of the user
|
|
127
|
+
* @param assigns - The new assigns of the user
|
|
128
|
+
*/
|
|
129
|
+
updateUser(clientId, presence, assigns) {
|
|
130
|
+
const client = this._retrieveUser(clientId);
|
|
131
|
+
if (client) {
|
|
132
|
+
client.assigns.updateDoc(Object.assign({ ...client.assigns.doc }, assigns));
|
|
133
|
+
const presenceDoc = Object.assign({ ...client.presence.doc }, presence);
|
|
134
|
+
if (!this.areEqual(presenceDoc, client.presence.doc))
|
|
135
|
+
client.presence.updateDoc(presenceDoc);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* @desc Broadcasts a message to all users in the channel
|
|
140
|
+
* @param event - The event name
|
|
141
|
+
* @param message - The message to send
|
|
142
|
+
* @param sender - The sender of the message
|
|
143
|
+
*/
|
|
144
|
+
broadcast(event, message, sender = enums_1.PondSenders.POND_CHANNEL) {
|
|
145
|
+
const client = this._retrieveUser(sender);
|
|
146
|
+
if (!client && !Object.values(enums_1.PondSenders).includes(sender))
|
|
147
|
+
throw new Error(`Client with clientId ${sender} does not exist in channel ${this.name}`);
|
|
148
|
+
const channelEvent = {
|
|
149
|
+
client: {
|
|
150
|
+
clientId: sender,
|
|
151
|
+
clientAssigns: client ? client.assigns.doc : {},
|
|
152
|
+
clientPresence: client ? client.presence.doc : {}
|
|
153
|
+
},
|
|
154
|
+
event: event,
|
|
155
|
+
payload: message,
|
|
156
|
+
channel: this,
|
|
157
|
+
};
|
|
158
|
+
const newMessage = {
|
|
159
|
+
action: enums_1.ServerActions.MESSAGE, payload: message, event: event, channelName: this.name,
|
|
160
|
+
};
|
|
161
|
+
void this._middleWare.run(channelEvent, hasErrored => {
|
|
162
|
+
if (!hasErrored)
|
|
163
|
+
this._sendToClients(this._channelAssigns.keys, newMessage);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* @desc Broadcasts a message to all users in the channel except the sender
|
|
168
|
+
* @param event - The event name
|
|
169
|
+
* @param message - The message to send
|
|
170
|
+
* @param clientId - The client id of the sender
|
|
171
|
+
*/
|
|
172
|
+
broadcastFrom(event, message, clientId) {
|
|
173
|
+
const client = this._retrieveUser(clientId);
|
|
174
|
+
if (!client)
|
|
175
|
+
throw new Error(`Client with clientId ${clientId} does not exist in channel ${this.name}`);
|
|
176
|
+
const newMessage = {
|
|
177
|
+
action: enums_1.ServerActions.MESSAGE, payload: message, event: event, channelName: this.name,
|
|
178
|
+
};
|
|
179
|
+
const channelEvent = {
|
|
180
|
+
client: {
|
|
181
|
+
clientId: clientId,
|
|
182
|
+
clientAssigns: client.assigns.doc,
|
|
183
|
+
clientPresence: client.presence.doc
|
|
184
|
+
},
|
|
185
|
+
event: event,
|
|
186
|
+
payload: message,
|
|
187
|
+
channel: this,
|
|
188
|
+
};
|
|
189
|
+
void this._middleWare.run(channelEvent, hasErrored => {
|
|
190
|
+
if (!hasErrored) {
|
|
191
|
+
const clientIds = this._channelAssigns.keys.filter(id => id !== clientId);
|
|
192
|
+
this._sendToClients(clientIds, newMessage);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* @desc Sends a message to a specific user or group of users
|
|
198
|
+
* @param event - The event name
|
|
199
|
+
* @param clientId - The client id of the user to send the message to
|
|
200
|
+
* @param message - The message to send
|
|
201
|
+
* @param sender - The client id of the sender
|
|
202
|
+
*/
|
|
203
|
+
sendTo(event, message, sender, clientId) {
|
|
204
|
+
const client = this._retrieveUser(sender);
|
|
205
|
+
if (!client && !Object.values(enums_1.PondSenders).includes(sender))
|
|
206
|
+
throw new Error('Client not found');
|
|
207
|
+
const clientIds = Array.isArray(clientId) ? clientId : [clientId];
|
|
208
|
+
const notFound = clientIds.filter(id => !this._channelAssigns.has(id));
|
|
209
|
+
if (notFound.length > 0)
|
|
210
|
+
throw new Error(`Client(s) with clientId(s) ${notFound.join(', ')} were not found in channel ${this.name}`);
|
|
211
|
+
const newMessage = {
|
|
212
|
+
action: enums_1.ServerActions.MESSAGE, payload: message, event: event, channelName: this.name,
|
|
213
|
+
};
|
|
214
|
+
const channelEvent = {
|
|
215
|
+
client: {
|
|
216
|
+
clientId: sender,
|
|
217
|
+
clientAssigns: client ? client.assigns.doc : {},
|
|
218
|
+
clientPresence: client ? client.presence.doc : {}
|
|
219
|
+
},
|
|
220
|
+
channel: this,
|
|
221
|
+
event: event,
|
|
222
|
+
payload: message,
|
|
223
|
+
};
|
|
224
|
+
void this._middleWare.run(channelEvent, hasErrored => {
|
|
225
|
+
if (!hasErrored)
|
|
226
|
+
this._sendToClients(clientIds, newMessage);
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* @desc Subscribes to a channel event, used only by the sockets to subscribe to all events
|
|
231
|
+
* @param clientId - The client id of the user to send the message to
|
|
232
|
+
* @param callback - The callback to call when a message is received
|
|
233
|
+
*/
|
|
234
|
+
subscribeToMessages(clientId, callback) {
|
|
235
|
+
const sub1 = this._messages.subscribe(({ clients, message }) => {
|
|
236
|
+
if (clients.includes(clientId))
|
|
237
|
+
callback(message);
|
|
238
|
+
});
|
|
239
|
+
const sub2 = this.onPresenceChange(callback);
|
|
240
|
+
return {
|
|
241
|
+
unsubscribe: () => {
|
|
242
|
+
sub1.unsubscribe();
|
|
243
|
+
sub2.unsubscribe();
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* @desc Sends a message to a specific user without running the middleware
|
|
249
|
+
* @param event - The event name
|
|
250
|
+
* @param message - The message to send
|
|
251
|
+
* @param client - The client id of the user to send the message to
|
|
252
|
+
* @param action - The action to send
|
|
253
|
+
*/
|
|
254
|
+
respondToClient(event, message, client, action = enums_1.ServerActions.MESSAGE) {
|
|
255
|
+
const newMessage = {
|
|
256
|
+
action: action,
|
|
257
|
+
payload: message, event: event,
|
|
258
|
+
channelName: this.name,
|
|
259
|
+
};
|
|
260
|
+
this._sendToClients([client], newMessage);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* @desc Sends a message to a specific user or group of users except the sender
|
|
264
|
+
* @param clients - The client id of the user to send the message to
|
|
265
|
+
* @param message - The message to send
|
|
266
|
+
* @private
|
|
267
|
+
*/
|
|
268
|
+
_sendToClients(clients, message) {
|
|
269
|
+
void this._messages.publish({ clients, message });
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* @desc Retrieves a user from the channel
|
|
273
|
+
* @param clientId - The client id of the user to retrieve
|
|
274
|
+
* @private
|
|
275
|
+
*/
|
|
276
|
+
_retrieveUser(clientId) {
|
|
277
|
+
const assigns = this._channelAssigns.get(clientId);
|
|
278
|
+
const presence = this._channelPresence.get(clientId);
|
|
279
|
+
if (assigns && presence !== null) {
|
|
280
|
+
return {
|
|
281
|
+
assigns: assigns, presence: presence,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
exports.Channel = Channel;
|