You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.3 KiB
JavaScript
103 lines
2.3 KiB
JavaScript
'use strict';
|
|
|
|
const createEventEmitter = require("create-event-emitter");
|
|
const defaultValue = require("default-value");
|
|
|
|
function removeFromArray(array, item) {
|
|
let index = array.indexOf(item);
|
|
|
|
if (index !== -1) {
|
|
array.splice(index, 1);
|
|
}
|
|
}
|
|
|
|
module.exports = function createClientStore(options = {}) {
|
|
let clients = [];
|
|
let subscribedClients = [];
|
|
|
|
let store = createEventEmitter({
|
|
add: function addClient(client) {
|
|
let clientObject = createEventEmitter({
|
|
socket: client,
|
|
subscribed: false,
|
|
disconnected: false,
|
|
kill: function killClient() {
|
|
store.kill(client);
|
|
},
|
|
send: function sendMessage(message) {
|
|
let data = JSON.stringify(message);
|
|
this.socket.send(data, (error) => {
|
|
if (error != null) {
|
|
store.emit("error", error);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
client.on("message", (data) => {
|
|
let message;
|
|
|
|
try {
|
|
message = JSON.parse(data);
|
|
} catch (err) {
|
|
/* User sent invalid data; disconnect them. */
|
|
return this.killClient(client);
|
|
}
|
|
|
|
if (message == null || typeof message !== "object") {
|
|
/* User sent invalid data; disconnect them. */
|
|
return this.killClient(client);
|
|
}
|
|
|
|
if (message.type === "subscribe") {
|
|
if (clientObject.subscribed === false) {
|
|
subscribedClients.push(clientObject);
|
|
clientObject.subscribed = true;
|
|
clientObject.emit("subscribed");
|
|
}
|
|
} else {
|
|
clientObject.emit("message", message);
|
|
}
|
|
});
|
|
|
|
client.on("close", (code, reason) => {
|
|
client.disconnected = true;
|
|
this.remove(clientObject);
|
|
});
|
|
|
|
clients.push(clientObject);
|
|
|
|
return clientObject;
|
|
},
|
|
kill: function killClient(client) {
|
|
client.close();
|
|
},
|
|
remove: function removeClient(client) {
|
|
removeFromArray(clients, client);
|
|
removeFromArray(subscribedClients, client);
|
|
},
|
|
broadcast: function broadcastMessage(message, clients) {
|
|
defaultValue(clients, subscribedClients).forEach((client) => {
|
|
client.send(message);
|
|
});
|
|
},
|
|
broadcastAll: function broadcastMessageToAll(message) {
|
|
this.broadcast(message, clients);
|
|
}
|
|
});
|
|
|
|
let pingInterval = defaultValue(options.pingInterval, 5000);
|
|
|
|
function pingClients() {
|
|
store.broadcastAll({
|
|
type: "ping"
|
|
});
|
|
|
|
setTimeout(pingClients, pingInterval);
|
|
}
|
|
|
|
pingClients();
|
|
|
|
return store;
|
|
};
|