diff --git a/README.md b/README.md
index bf19fb3..bc1ef16 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,8 @@
-# X-Chat
-X:/Chat is a web application that uses HTML, CSS, and JavaScript on the front-end, and NodeJS on the back-end. It allows users to communicate with one another in a secure manner (although I'm new to NodeJS, and cannot guarantee said security).
+# X:/Chat
+
+## Cryptographic algorithms and functions used in this project haven't been fully reviewed, so don't use this for any seriously sensitive data. This was also my first Node.js project, so at the time I was winging it. As a result, the application might have bugs or security issues.
+
+X:/Chat is a web application that uses HTML, CSS, and JavaScript on the front-end, and Node.js on the back-end. It allows users to communicate with one another in a secure manner (although I'm new to Node.js, and cannot guarantee said security).
JavaScript and local storage are absolutely **mandatory** for the web app to function. Local storage is used to store public keys, private keys, settings, and a whole lot more.
@@ -7,14 +10,6 @@ If you use the "Anonymous Chat" feature, absolutely nothing is stored by the ser
The normal chat is more like your generic chat application. Messages are still encrypted on the client side with RSA-2048, and users' private keys are encrypted with AES-256-CTR, which uses the SHA512 hash of the user's password as the decryption key. The user's password is stored using BCrypt with 10 salt rounds. In short, unless the server code is modified or something to capture the user's private key, there's absolutely no way to get the content of a conversation. The user's settings, contacts, and other data are stored in JSON format in text files for easy access. These are stored in plaintext, but it'd be easy to encrypt them with the user's password and AES. If you wish to make that a reality, remember, there are already functions written to make it easier. You can use the "aes_encrypt(plaintext, password)" and "aes_decrypt(encrypted, password)" functions that I wrote to easily encrypt/decrypt whatever you want.
-There might be some bugs or some unexpected behavior, but this is to be expected, this is, after all, my first NodeJS project. If you try to break the app, you'll very likely succeed. There aren't as many validation checks and such as I'd like, but there are enough to protect user's accounts and conversations. I apologize in advance if anything does go wrong though.
-
-![X:/Chat](https://www.xtrendence.com/portfolio/projects/x-chat/thumbnail.jpg)
-
-### To Do
-
-- [ ] Add comments to the code.
-
-- [ ] Add the option to store anonymous chat messages in local storage.
+There might be some bugs or some unexpected behavior, but this is to be expected, this is, after all, my first Node.js project. If you try to break the app, you'll very likely succeed. There aren't as many validation checks and such as I'd like, but there are enough to protect user's accounts and conversations. I apologize in advance if anything does go wrong though.
-- [ ] Create an ElectronJS version of X:/Chat.
+![X:/Chat](https://i.imgur.com/9U9nknc.jpg)
diff --git a/assets/css/anonymous-dark.css b/assets/css/anonymous-dark.css
index 42aa06e..87e3f22 100755
--- a/assets/css/anonymous-dark.css
+++ b/assets/css/anonymous-dark.css
@@ -137,6 +137,9 @@ button, input {
scroll-behavior:smooth;
-webkit-overflow-scrolling:touch;
}
+.messages-list::-webkit-scrollbar {
+ display:none;
+}
.chat-bubble-wrapper {
font-size:0;
display:block;
diff --git a/assets/css/anonymous-light.css b/assets/css/anonymous-light.css
index cb7edd6..bbbe368 100755
--- a/assets/css/anonymous-light.css
+++ b/assets/css/anonymous-light.css
@@ -139,6 +139,9 @@ button, input {
scroll-behavior:smooth;
-webkit-overflow-scrolling:touch;
}
+.messages-list::-webkit-scrollbar {
+ display:none;
+}
.chat-bubble-wrapper {
font-size:0;
display:block;
diff --git a/assets/js/anonymous.js b/assets/js/anonymous.js
index dc46f2a..95d0bd4 100755
--- a/assets/js/anonymous.js
+++ b/assets/js/anonymous.js
@@ -1,4 +1,5 @@
document.addEventListener("DOMContentLoaded", function(e) {
+ // Connect to Socket.IO.
var socket = io.connect(window.location.href.replace("/anonymous", ""), { reconnection:true, reconnectionDelay:1000, reconnectionDelayMax:5000, reconnectionAttempts:99999 });
initialize();
// Socket.io functionality.
@@ -6,6 +7,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
socket.emit("fetch-chat-members");
socket.connect();
});
+ // Generate an anonymous chat session. Saves the user's anonymous ID, public key, and private key in the browser's local storage, and then redirects them to their newly generated chat session.
socket.on("generate-anonymous-session", function(data) {
if(!empty(data)) {
window.localStorage.setItem(data["conversation_id"] + "-anonymous-id", data["anonymous_id"]);
@@ -17,6 +19,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
socket.emit("generate-anonymous-session");
}
});
+ // Generates credentials (anonymous ID, public key, and private key). This is used when a user joins an existing chat.
socket.on("generate-credentials", function(data) {
if(!empty(data)) {
window.localStorage.setItem(data["conversation_id"] + "-anonymous-id", data["anonymous_id"]);
@@ -28,6 +31,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
socket.emit("generate-anonymous-session");
}
});
+ // Fetch and store chat members in local storage.
socket.on("fetch-chat-members", function(data) {
if(Object.keys(data.members).length >= 2) {
document.getElementsByClassName("loading-overlay")[0].style.display = "none";
@@ -37,6 +41,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
}
update_credentials();
});
+ // Every time a user joins a chat, their details are added
socket.on("new-anonymous-user", function(data) {
if(!empty(data)) {
if(!empty(get_chat_members())) {
@@ -54,6 +59,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
}
socket.emit("fetch-chat-members", { conversation_id:get_conversation_id() });
});
+ // Adding new message bubbles.
socket.on("new-anonymous-message", function(data) {
var list = document.getElementsByClassName("messages-list")[0];
var time = hour(data.id.substring(0, 10));
@@ -70,9 +76,11 @@ document.addEventListener("DOMContentLoaded", function(e) {
}
list.scrollTop = list.scrollHeight;
});
+ // Logging out.
socket.on("logout", function() {
logout();
});
+ // Allowing the server to send notifications to the user.
socket.on("notify", function(data) {
notify(data.title, data.text, data.color, data.duration, data.args);
});
@@ -191,7 +199,8 @@ document.addEventListener("DOMContentLoaded", function(e) {
}
// Encrypt text using AES-256.
function aes_encrypt(plaintext, password) {
- return CryptoJS.AES.encrypt(plaintext, password);
+ let encrypted = CryptoJS.AES.encrypt(plaintext, password).toString();
+ return encrypted;
}
// Decrypt text using AES-256.
function aes_decrypt(encrypted, password) {
diff --git a/assets/js/login.js b/assets/js/login.js
index 69fb95c..62c312a 100755
--- a/assets/js/login.js
+++ b/assets/js/login.js
@@ -1,5 +1,7 @@
document.addEventListener("DOMContentLoaded", function(e) {
initialize();
+
+ // Declaring variables and defining elements.
var login_text = document.getElementsByClassName("login-text")[0];
var login_border = document.getElementsByClassName("login-border")[0];
var login_wrapper = document.getElementsByClassName("login-wrapper")[0];
@@ -11,10 +13,11 @@ document.addEventListener("DOMContentLoaded", function(e) {
var register_button = document.getElementsByClassName("register-button")[0];
var anonymous_button = document.getElementsByClassName("login-anonymous")[0];
+ // When the login button is clicked, the username and password are checked. If one's empty, then the user is told to fill out both fields.
login_button.addEventListener("click", function() {
var username = document.getElementsByClassName("login-input username")[0].value;
var password = document.getElementsByClassName("login-input password")[0].value;
- if(!empty(username) && !empty(password)) {
+ if(!empty(username) || !empty(password)) {
login(username, password);
}
else {
@@ -40,6 +43,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
register_border.style.display = "block";
register_wrapper.style.display = "block";
});
+ // When the register button is clicked on, the username and password are checked to not be empty. The password is also checked against the repeated one to make sure they're the same.
register_button.addEventListener("click", function() {
var username = document.getElementsByClassName("register-input username")[0].value;
var password = document.getElementsByClassName("register-input password")[0].value;
@@ -64,9 +68,11 @@ document.addEventListener("DOMContentLoaded", function(e) {
login_text.textContent = "No username entered.";
}
});
+ // Clicking on the anonymous chat button redirects the user to "/anonymous".
anonymous_button.addEventListener("click", function() {
window.location.href = "./anonymous";
});
+ // Clicking on the info icon shows the info page.
document.getElementsByClassName("info-icon")[0].addEventListener("click", function() {
if(document.getElementsByClassName("info-wrapper")[0].style.display == "block") {
document.getElementsByClassName("info-wrapper")[0].style.display = "none";
@@ -75,9 +81,11 @@ document.addEventListener("DOMContentLoaded", function(e) {
document.getElementsByClassName("info-wrapper")[0].style.display = "block";
}
});
+ // Clicking on the close icon closes the info page.
document.getElementsByClassName("close-icon")[0].addEventListener("click", function() {
document.getElementsByClassName("info-wrapper")[0].style.display = "none";
});
+ // When the user presses the enter key, either the login or register button is clicked depending on which is visible.
document.addEventListener("keydown", function(e) {
if(e.which == 13) {
if(login_wrapper.style.display == "block") {
@@ -88,6 +96,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
}
}
});
+ // The login function sends the user's username and password to the server. If the user is successfully logged in, their password hash, private key, and public key are stored in their browser's local storage.
function login(username, password) {
login_text.style.display = "block";
login_text.textContent = "Loading...";
@@ -115,6 +124,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
username: username, password: password
}));
}
+ // The register function sends the user's username and password to the server. If the registration is successful, the login form is automatically filled out, and the user is logged in.
function register(username, password) {
login_text.style.display = "block";
login_text.textContent = "Loading...";
@@ -139,14 +149,17 @@ document.addEventListener("DOMContentLoaded", function(e) {
username: username, password: password
}));
}
+ // Check if string is empty.
function empty(text) {
if(text != null && text != "" && typeof text != "undefined" ) {
return false;
}
return true;
}
+ // Initialization function.
function initialize() {
if(local_storage_available()) {
+ // Setting clear_storage to true will clear the browser's local storage for this website.
var clear_storage = false;
if(clear_storage) {
window.localStorage.clear();
@@ -172,6 +185,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
document.body.innerHTML = '
Error - Local Storage Required
Your browser needs to support Local Storage.
';
}
}
+ // Check if the user's browser supports local storage.
function local_storage_available() {
try {
window.localStorage.setItem("test", "test");
@@ -182,6 +196,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
return false;
}
}
+ // Check if the user's on a mobile device.
function detect_mobile() {
var check = false;
(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
diff --git a/assets/js/main.js b/assets/js/main.js
index 4e29176..5702899 100755
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -1,4 +1,5 @@
document.addEventListener("DOMContentLoaded", function(e) {
+ // Connect to Socket.IO.
var socket = io.connect(window.location.href, { reconnection:true, reconnectionDelay:1000, reconnectionDelayMax:5000, reconnectionAttempts:99999 });
var global_settings;
initialize();
@@ -6,11 +7,14 @@ document.addEventListener("DOMContentLoaded", function(e) {
socket.on("disconnect", function() {
socket.connect();
});
+ // Populates the conversation list.
socket.on("list-conversations", function(data) {
+ // If there are no conversations, the start page is shown.
if(empty(data["content"])) {
show_start();
}
else {
+ // Checks to see if a conversation is already open.
if(document.getElementsByClassName("conversation-wrapper active").length > 0) {
var active_id = document.getElementsByClassName("conversation-wrapper active")[0].id;
var active_exists = true;
@@ -20,6 +24,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
}
var conversations = data.content;
var keys = Object.keys(conversations);
+ // Empties the conversation list.
document.getElementsByClassName("conversation-list")[0].innerHTML = "";
for(i = 0; i < keys.length; i++) {
var id = keys[i];
@@ -34,6 +39,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
else {
var unread = "";
}
+ // Every conversation file has a last modified time.
if(empty(time_modified)) {
socket.emit("list-conversations");
}
@@ -44,6 +50,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
if(active_exists) {
document.getElementById(active_id).classList.add("active");
}
+ // If the user has a conversation open, then it's reopened once the conversation list is fetched.
if(!empty(window.localStorage.getItem("active-conversation"))) {
var active_id = window.localStorage.getItem("active-conversation");
if(document.getElementById(active_id)) {
@@ -56,24 +63,31 @@ document.addEventListener("DOMContentLoaded", function(e) {
document.getElementsByClassName("navbar-item title")[0].style.display = "inline-block";
document.getElementsByClassName("navbar-item compose")[0].style.display = "inline-block";
sort_conversation_list();
+ // Allows the server to pass a conversation ID to the client side script so that it'll be opened.
if(!empty(data.id) && !empty(document.getElementById(data.id))) {
document.getElementById(data.id).click();
}
}
});
+ // Handles the addition of new chat bubbles and messages.
socket.on("new-message", function(data) {
var list = document.getElementsByClassName("messages-list")[0];
var username = document.getElementsByClassName("account-username")[0].textContent;
+ // Every message has an ID. The ID is made up of the UNIX timestamp at the time the message was sent, and a random number. The first ten characters would always be said timestamp.
var time = hour(data.id.substring(0, 10));
var recipient_public_key = get_recipient_public_key();
var public_key = get_public_key();
var private_key = get_private_key();
+ // Checks to make sure a conversation is actually open before adding bubbles.
if(!empty(document.getElementsByClassName("conversation-wrapper active")) && document.getElementsByClassName("conversation-wrapper active")[0].id == data.conversation_id) {
+ // The server can relay the message. The client side script checks to make sure it doesn't add duplicate bubbles.
if(data.relay != "true") {
+ // If the message was sent from the current user.
if(data.from.toLowerCase() == username.toLowerCase()) {
var from = "me";
list.innerHTML += '
' + decrypt_text(data.sender, private_key) + '
';
}
+ // If the message was sent by the other party.
else {
var from = "others";
list.innerHTML += '
' + decrypt_text(data.recipient, private_key) + '
';
@@ -86,6 +100,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
}
}
else {
+ // If the message wasn't sent from the current user, and the message is a relay, then the current user is notified of the other person having messaged them.
if(data.from.toLowerCase() != username.toLowerCase() && data.relay == "true") {
if(!empty(global_settings)) {
if(JSON.parse(global_settings)["message-notification"] == "enabled") {
@@ -94,27 +109,32 @@ document.addEventListener("DOMContentLoaded", function(e) {
}
}
}
+ // Updates the conversation's last modified time.
if(!empty(data.conversation_id) && document.getElementById(data.conversation_id)) {
document.getElementById(data.conversation_id).setAttribute("data-modified", data.conversation_modified);
if(!document.getElementById(data.conversation_id).classList.contains("active")) {
socket.emit("unread-message", { id:data.conversation_id });
}
}
+ // If no last modified timestamp is found, then the conversations are refetched.
else {
socket.emit("list-conversations");
}
sort_conversation_list();
});
+ // The server can tell the client side script to remove a chat bubble element in case it has been deleted on the server-side.
socket.on("delete-message", function(data) {
document.getElementById(data.id).parentNode.remove();
document.getElementById(data.conversation_id).setAttribute("data-modified", data.conversation_modified);
sort_conversation_list();
});
+ // Mark a conversation as having an unread message.
socket.on("unread-message", function(data) {
if(!empty(data.conversation_id) && document.getElementById(data.conversation_id) && !document.getElementById(data.conversation_id).classList.contains("active")) {
document.getElementById(data.conversation_id).classList.add("unread");
}
});
+ // Fetch the content of a conversation.
socket.on("fetch-conversation", function(data) {
var list = document.getElementsByClassName("messages-list")[0];
var username = document.getElementsByClassName("account-username")[0].textContent;
@@ -125,6 +145,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
document.getElementsByClassName("loading-overlay")[0].style.display = "none";
document.getElementsByClassName("navbar-item recipient")[0].style.display = "block";
document.getElementsByClassName("navbar-item recipient")[0].textContent = recipient;
+ // Mark the conversation as read.
if(document.getElementById(data.conversation_id)) {
document.getElementById(data.conversation_id).classList.remove("unread");
}
@@ -148,17 +169,21 @@ document.addEventListener("DOMContentLoaded", function(e) {
}
list.scrollTop = list.scrollHeight;
}
+ // Save the recipient's public key in the browser's local storage.
window.localStorage.setItem("recipient-public-key", data.recipient_public_key);
}
adjust_to_screen();
close_messages_search();
});
+ // Fetch details about a specific conversation.
socket.on("fetch-conversation-info", function(data) {
open_popup(350, 400, "Information", 'Username' + data.username + 'Recipient' + data.recipient_username + 'Conversation ID' + data.id + 'Date Created' + data.created + 'Date Modified' + data.modified + 'File Size' + bytes_to_size(data.size) + '');
});
+ // Fetch details about a specific message.
socket.on("fetch-message-info", function(data) {
open_popup(350, 340, "Information", 'Conversation ID' + data.conversation + 'Message ID' + data.message + 'Date' + data.date + 'Sender' + data.sender + '');
});
+ // Refetch contacts.
socket.on("refetch-contacts", function() {
socket.emit("manage-contacts", { action:"fetch-contacts" });
for(i = 0; i < document.getElementsByClassName("contact-card contact").length; i++) {
@@ -168,6 +193,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
document.getElementsByClassName("contact-card edit")[0].remove();
}
});
+ // Populates the contact list with contact cards.
socket.on("populate-contacts", function(data) {
document.getElementsByClassName("contacts-wrapper")[0].innerHTML = "";
var add_card = document.createElement("div");
@@ -268,21 +294,27 @@ document.addEventListener("DOMContentLoaded", function(e) {
}
}
});
+ // Save and apply settings.
socket.on("save-settings", function(data) {
apply_settings(data["settings"]);
});
+ // Refetch conversation list.
socket.on("refetch", function() {
socket.emit("list-conversations");
});
+ // Logout.
socket.on("logout", function() {
logout();
});
+ // Fetch settings after they've been reset.
socket.on("reset-settings", function() {
fetch_settings();
});
+ // Refresh the page.
socket.on("refresh", function() {
location.reload();
});
+ // The server can send notifications to the client.
socket.on("notify", function(data) {
var enabled = true;
if(!empty(data.args)) {
@@ -405,6 +437,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
document.getElementById(id).click();
}
});
+ // Clicking a chat bubble opens a menu allowing the user to perform a number of actions on that specific message.
document.getElementsByClassName("messages-list")[0].addEventListener("click", function(e) {
if(e.target && e.target.classList.contains("chat-bubble")) {
var bubbles = document.getElementsByClassName("chat-bubble");
@@ -979,7 +1012,8 @@ document.addEventListener("DOMContentLoaded", function(e) {
}
// Encrypt text using AES-256.
function aes_encrypt(plaintext, password) {
- return CryptoJS.AES.encrypt(plaintext, password);
+ let encrypted = CryptoJS.AES.encrypt(plaintext, password).toString();
+ return encrypted;
}
// Decrypt text using AES-256.
function aes_decrypt(encrypted, password) {
diff --git a/node_modules/.bin/atob b/node_modules/.bin/atob
new file mode 120000
index 0000000..a68344a
--- /dev/null
+++ b/node_modules/.bin/atob
@@ -0,0 +1 @@
+../atob/bin/atob.js
\ No newline at end of file
diff --git a/node_modules/.bin/is-ci b/node_modules/.bin/is-ci
new file mode 120000
index 0000000..fe6aca6
--- /dev/null
+++ b/node_modules/.bin/is-ci
@@ -0,0 +1 @@
+../is-ci/bin.js
\ No newline at end of file
diff --git a/node_modules/.bin/mime b/node_modules/.bin/mime
new file mode 120000
index 0000000..fbb7ee0
--- /dev/null
+++ b/node_modules/.bin/mime
@@ -0,0 +1 @@
+../mime/cli.js
\ No newline at end of file
diff --git a/node_modules/.bin/nodemon b/node_modules/.bin/nodemon
new file mode 120000
index 0000000..1056ddc
--- /dev/null
+++ b/node_modules/.bin/nodemon
@@ -0,0 +1 @@
+../nodemon/bin/nodemon.js
\ No newline at end of file
diff --git a/node_modules/.bin/nodetouch b/node_modules/.bin/nodetouch
new file mode 120000
index 0000000..3409fdb
--- /dev/null
+++ b/node_modules/.bin/nodetouch
@@ -0,0 +1 @@
+../touch/bin/nodetouch.js
\ No newline at end of file
diff --git a/node_modules/.bin/nopt b/node_modules/.bin/nopt
new file mode 120000
index 0000000..6b6566e
--- /dev/null
+++ b/node_modules/.bin/nopt
@@ -0,0 +1 @@
+../nopt/bin/nopt.js
\ No newline at end of file
diff --git a/node_modules/.bin/rc b/node_modules/.bin/rc
new file mode 120000
index 0000000..48b3cda
--- /dev/null
+++ b/node_modules/.bin/rc
@@ -0,0 +1 @@
+../rc/cli.js
\ No newline at end of file
diff --git a/node_modules/.bin/semver b/node_modules/.bin/semver
new file mode 120000
index 0000000..317eb29
--- /dev/null
+++ b/node_modules/.bin/semver
@@ -0,0 +1 @@
+../semver/bin/semver
\ No newline at end of file
diff --git a/node_modules/.bin/which b/node_modules/.bin/which
new file mode 120000
index 0000000..f62471c
--- /dev/null
+++ b/node_modules/.bin/which
@@ -0,0 +1 @@
+../which/bin/which
\ No newline at end of file
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
new file mode 100644
index 0000000..fe056bc
--- /dev/null
+++ b/node_modules/.package-lock.json
@@ -0,0 +1,3265 @@
+{
+ "name": "x-chat",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "node_modules/accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "dependencies": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/after": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
+ "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
+ },
+ "node_modules/ansi-align": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
+ "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
+ "dependencies": {
+ "string-width": "^2.0.0"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dependencies": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ }
+ },
+ "node_modules/anymatch/node_modules/normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dependencies": {
+ "remove-trailing-separator": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "node_modules/array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/arraybuffer.slice": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
+ "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog=="
+ },
+ "node_modules/assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/async-each": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ=="
+ },
+ "node_modules/atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+ "bin": {
+ "atob": "bin/atob.js"
+ },
+ "engines": {
+ "node": ">= 4.5.0"
+ }
+ },
+ "node_modules/backo2": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
+ "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "node_modules/base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "dependencies": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/base/node_modules/define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dependencies": {
+ "is-descriptor": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/base/node_modules/is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/base/node_modules/is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/base/node_modules/is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dependencies": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/base64-arraybuffer": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
+ "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/base64id": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
+ "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
+ "engines": {
+ "node": "^4.5.0 || >= 5.9"
+ }
+ },
+ "node_modules/bcryptjs": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+ "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
+ },
+ "node_modules/binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/blob": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
+ "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
+ },
+ "node_modules/body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "dependencies": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/boxen": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
+ "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==",
+ "dependencies": {
+ "ansi-align": "^2.0.0",
+ "camelcase": "^4.0.0",
+ "chalk": "^2.0.1",
+ "cli-boxes": "^1.0.0",
+ "string-width": "^2.0.0",
+ "term-size": "^1.2.0",
+ "widest-line": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dependencies": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/braces/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "dependencies": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/capture-stack-trace": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
+ "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies",
+ "dependencies": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ },
+ "optionalDependencies": {
+ "fsevents": "^1.2.7"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
+ "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A=="
+ },
+ "node_modules/class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "dependencies": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/class-utils/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/cli-boxes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
+ "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/cluster-key-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz",
+ "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==",
+ "optional": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dependencies": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+ },
+ "node_modules/component-bind": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
+ "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E="
+ },
+ "node_modules/component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
+ },
+ "node_modules/component-inherit": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
+ "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM="
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "node_modules/configstore": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
+ "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==",
+ "dependencies": {
+ "dot-prop": "^4.1.0",
+ "graceful-fs": "^4.1.2",
+ "make-dir": "^1.0.0",
+ "unique-string": "^1.0.0",
+ "write-file-atomic": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/connect-redis": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-4.0.1.tgz",
+ "integrity": "sha512-Aq1le+P3vkGKMw8v/XBWZDsy7M1+SNFhLX5MECXcphi4yFnXrAhRvWo8WXdXstCPvX/85Jthup1Q9JmfE3i4pQ==",
+ "engines": {
+ "node": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "ioredis": "^4.10.0",
+ "redis": "^2.8.0",
+ "redis-mock": "^0.46.0"
+ }
+ },
+ "node_modules/connect-redis/node_modules/redis": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz",
+ "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==",
+ "dependencies": {
+ "double-ended-queue": "^2.1.0-0",
+ "redis-commands": "^1.2.0",
+ "redis-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/connect-redis/node_modules/redis-parser": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz",
+ "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+ "dependencies": {
+ "safe-buffer": "5.1.2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "node_modules/copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "node_modules/create-error-class": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
+ "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
+ "dependencies": {
+ "capture-stack-trace": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dependencies": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "node_modules/crypto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
+ "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==",
+ "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in."
+ },
+ "node_modules/crypto-js": {
+ "version": "3.1.9-1",
+ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz",
+ "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg="
+ },
+ "node_modules/crypto-random-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
+ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "dependencies": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-property/node_modules/is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-property/node_modules/is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-property/node_modules/is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dependencies": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/denque": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
+ "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==",
+ "optional": true,
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "node_modules/dot-prop": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
+ "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
+ "dependencies": {
+ "is-obj": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/double-ended-queue": {
+ "version": "2.1.0-0",
+ "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz",
+ "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw="
+ },
+ "node_modules/duplexer3": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "node_modules/ejs": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.2.tgz",
+ "integrity": "sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/engine.io": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.5.0.tgz",
+ "integrity": "sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA==",
+ "dependencies": {
+ "accepts": "~1.3.4",
+ "base64id": "2.0.0",
+ "cookie": "~0.4.1",
+ "debug": "~4.1.0",
+ "engine.io-parser": "~2.2.0",
+ "ws": "~7.4.2"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/engine.io-client": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.0.tgz",
+ "integrity": "sha512-12wPRfMrugVw/DNyJk34GQ5vIVArEcVMXWugQGGuw2XxUSztFNmJggZmv8IZlLyEdnpO1QB9LkcjeWewO2vxtA==",
+ "dependencies": {
+ "component-emitter": "~1.3.0",
+ "component-inherit": "0.0.3",
+ "debug": "~3.1.0",
+ "engine.io-parser": "~2.2.0",
+ "has-cors": "1.1.0",
+ "indexof": "0.0.1",
+ "parseqs": "0.0.6",
+ "parseuri": "0.0.6",
+ "ws": "~7.4.2",
+ "xmlhttprequest-ssl": "~1.5.4",
+ "yeast": "0.1.2"
+ }
+ },
+ "node_modules/engine.io-client/node_modules/component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
+ },
+ "node_modules/engine.io-client/node_modules/debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/engine.io-parser": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz",
+ "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==",
+ "dependencies": {
+ "after": "0.8.2",
+ "arraybuffer.slice": "~0.0.7",
+ "base64-arraybuffer": "0.1.4",
+ "blob": "0.0.5",
+ "has-binary2": "~1.0.2"
+ }
+ },
+ "node_modules/engine.io/node_modules/cookie": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
+ "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/engine.io/node_modules/debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/engine.io/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/execa": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "dependencies": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dependencies": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+ "dependencies": {
+ "accepts": "~1.3.7",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.19.0",
+ "content-disposition": "0.5.3",
+ "content-type": "~1.0.4",
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.1.2",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.5",
+ "qs": "6.7.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.1.2",
+ "send": "0.17.1",
+ "serve-static": "1.14.1",
+ "setprototypeof": "1.1.1",
+ "statuses": "~1.5.0",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/express-session": {
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.16.2.tgz",
+ "integrity": "sha512-oy0sRsdw6n93E9wpCNWKRnSsxYnSDX9Dnr9mhZgqUEEorzcq5nshGYSZ4ZReHFhKQ80WI5iVUUSPW7u3GaKauw==",
+ "dependencies": {
+ "cookie": "0.3.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~2.0.0",
+ "on-headers": "~1.0.2",
+ "parseurl": "~1.3.3",
+ "safe-buffer": "5.1.2",
+ "uid-safe": "~2.1.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/express-session/node_modules/cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express-session/node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dependencies": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extend-shallow/node_modules/is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dependencies": {
+ "is-plain-object": "^2.0.4"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dependencies": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dependencies": {
+ "is-descriptor": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dependencies": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dependencies": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fill-range/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dependencies": {
+ "map-cache": "^0.2.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs": {
+ "version": "0.0.1-security",
+ "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
+ "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ="
+ },
+ "node_modules/get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dependencies": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ }
+ },
+ "node_modules/glob-parent/node_modules/is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dependencies": {
+ "is-extglob": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/global-dirs": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
+ "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
+ "dependencies": {
+ "ini": "^1.3.4"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/got": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
+ "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
+ "dependencies": {
+ "create-error-class": "^3.0.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^3.0.0",
+ "is-redirect": "^1.0.0",
+ "is-retry-allowed": "^1.0.0",
+ "is-stream": "^1.0.0",
+ "lowercase-keys": "^1.0.0",
+ "safe-buffer": "^5.0.1",
+ "timed-out": "^4.0.0",
+ "unzip-response": "^2.0.1",
+ "url-parse-lax": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
+ "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q=="
+ },
+ "node_modules/has-binary2": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
+ "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
+ "dependencies": {
+ "isarray": "2.0.1"
+ }
+ },
+ "node_modules/has-cors": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
+ "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "dependencies": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "dependencies": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-values/node_modules/kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "dependencies": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ignore-by-default": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
+ },
+ "node_modules/import-lazy": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+ "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
+ },
+ "node_modules/inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "node_modules/ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "deprecated": "Please update to ini >=1.3.6 to avoid a prototype pollution issue",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ioredis": {
+ "version": "4.14.0",
+ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.14.0.tgz",
+ "integrity": "sha512-vGzyW9QTdGMjaAPUhMj48Z31mIO5qJLzkbsE5dg+orNi7L5Ph035htmkBZNDTDdDk7kp7e9UJUr+alhRuaWp8g==",
+ "optional": true,
+ "dependencies": {
+ "cluster-key-slot": "^1.1.0",
+ "debug": "^4.1.1",
+ "denque": "^1.1.0",
+ "lodash.defaults": "^4.2.0",
+ "lodash.flatten": "^4.4.0",
+ "redis-commands": "1.5.0",
+ "redis-errors": "^1.2.0",
+ "redis-parser": "^3.0.0",
+ "standard-as-callback": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ioredis/node_modules/debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "optional": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/ioredis/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "optional": true
+ },
+ "node_modules/ioredis/node_modules/redis-parser": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
+ "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
+ "optional": true,
+ "dependencies": {
+ "redis-errors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
+ "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-accessor-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "dependencies": {
+ "binary-extensions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
+ "node_modules/is-ci": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
+ "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
+ "dependencies": {
+ "ci-info": "^1.5.0"
+ },
+ "bin": {
+ "is-ci": "bin.js"
+ }
+ },
+ "node_modules/is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-data-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dependencies": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-descriptor/node_modules/kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-installed-globally": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
+ "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
+ "dependencies": {
+ "global-dirs": "^0.1.0",
+ "is-path-inside": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-npm": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
+ "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dependencies": {
+ "path-is-inside": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dependencies": {
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-redirect": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
+ "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-retry-allowed": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
+ "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+ "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+ },
+ "node_modules/isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/kind-of": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/latest-version": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
+ "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
+ "dependencies": {
+ "package-json": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/lodash.defaults": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+ "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=",
+ "optional": true
+ },
+ "node_modules/lodash.flatten": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+ "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
+ "optional": true
+ },
+ "node_modules/lowercase-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dependencies": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "dependencies": {
+ "pify": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dependencies": {
+ "object-visit": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dependencies": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "dependencies": {
+ "mime-db": "1.40.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+ },
+ "node_modules/mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "dependencies": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/mixin-deep/node_modules/is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dependencies": {
+ "is-plain-object": "^2.0.4"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "node_modules/nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "dependencies": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/nodemon": {
+ "version": "1.19.4",
+ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.4.tgz",
+ "integrity": "sha512-VGPaqQBNk193lrJFotBU8nvWZPqEZY2eIzymy2jjY0fJ9qIsxA0sxQ8ATPl0gZC645gijYEc1jtZvpS8QWzJGQ==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "chokidar": "^2.1.8",
+ "debug": "^3.2.6",
+ "ignore-by-default": "^1.0.1",
+ "minimatch": "^3.0.4",
+ "pstree.remy": "^1.1.7",
+ "semver": "^5.7.1",
+ "supports-color": "^5.5.0",
+ "touch": "^3.1.0",
+ "undefsafe": "^2.0.2",
+ "update-notifier": "^2.5.0"
+ },
+ "bin": {
+ "nodemon": "bin/nodemon.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/nodemon/node_modules/debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/nodemon/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/nopt": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
+ "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "dependencies": {
+ "path-key": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dependencies": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-copy/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-copy/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "dependencies": {
+ "isobject": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "dependencies": {
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/package-json": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
+ "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
+ "dependencies": {
+ "got": "^6.7.1",
+ "registry-auth-token": "^3.0.1",
+ "registry-url": "^3.0.3",
+ "semver": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/parseqs": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
+ "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w=="
+ },
+ "node_modules/parseuri": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
+ "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path": {
+ "version": "0.12.7",
+ "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
+ "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=",
+ "dependencies": {
+ "process": "^0.11.1",
+ "util": "^0.10.3"
+ }
+ },
+ "node_modules/path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
+ },
+ "node_modules/path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/prepend-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
+ "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
+ "dependencies": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.9.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+ },
+ "node_modules/pstree.remy": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz",
+ "integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A=="
+ },
+ "node_modules/qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/random-bytes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
+ "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "dependencies": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/readable-stream/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "node_modules/readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "dependencies": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/redis": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.1.tgz",
+ "integrity": "sha512-QhkKhOuzhogR1NDJfBD34TQJz2ZJwDhhIC6ZmvpftlmfYShHHQXjjNspAJ+Z2HH5NwSBVYBVganbiZ8bgFMHjg==",
+ "dependencies": {
+ "denque": "^1.5.0",
+ "redis-commands": "^1.7.0",
+ "redis-errors": "^1.2.0",
+ "redis-parser": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-redis"
+ }
+ },
+ "node_modules/redis-commands": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz",
+ "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg=="
+ },
+ "node_modules/redis-errors": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
+ "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/redis-mock": {
+ "version": "0.46.0",
+ "resolved": "https://registry.npmjs.org/redis-mock/-/redis-mock-0.46.0.tgz",
+ "integrity": "sha512-xQ/HGdune1tc70OXa2hpmUY5Q9OnC3+m0753ZTTesULIFnl7Gt8v4ElYjsKZCZoRf311G+yRdMz/C717mD7A6Q==",
+ "optional": true
+ },
+ "node_modules/redis-parser": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
+ "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
+ "dependencies": {
+ "redis-errors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/redis/node_modules/denque": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz",
+ "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/redis/node_modules/redis-commands": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz",
+ "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ=="
+ },
+ "node_modules/regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "dependencies": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/registry-auth-token": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
+ "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==",
+ "dependencies": {
+ "rc": "^1.1.6",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/registry-url": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
+ "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
+ "dependencies": {
+ "rc": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
+ },
+ "node_modules/repeat-element": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+ "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "deprecated": "https://github.com/lydell/resolve-url#deprecated"
+ },
+ "node_modules/ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "node_modules/safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dependencies": {
+ "ret": "~0.1.10"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/semver-diff": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
+ "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
+ "dependencies": {
+ "semver": "^5.0.3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.7.2",
+ "mime": "1.6.0",
+ "ms": "2.1.1",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.1",
+ "statuses": "~1.5.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ },
+ "node_modules/serve-static": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+ "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+ "dependencies": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.17.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "dependencies": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/set-value/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+ },
+ "node_modules/shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+ },
+ "node_modules/snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "dependencies": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "dependencies": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node/node_modules/define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dependencies": {
+ "is-descriptor": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node/node_modules/is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node/node_modules/is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dependencies": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "dependencies": {
+ "kind-of": "^3.2.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-util/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/socket.io": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.4.1.tgz",
+ "integrity": "sha512-Si18v0mMXGAqLqCVpTxBa8MGqriHGQh8ccEOhmsmNS3thNCGBwO8WGrwMibANsWtQQ5NStdZwHqZR3naJVFc3w==",
+ "dependencies": {
+ "debug": "~4.1.0",
+ "engine.io": "~3.5.0",
+ "has-binary2": "~1.0.2",
+ "socket.io-adapter": "~1.1.0",
+ "socket.io-client": "2.4.0",
+ "socket.io-parser": "~3.4.0"
+ }
+ },
+ "node_modules/socket.io-adapter": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz",
+ "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g=="
+ },
+ "node_modules/socket.io-client": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.4.0.tgz",
+ "integrity": "sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==",
+ "dependencies": {
+ "backo2": "1.0.2",
+ "component-bind": "1.0.0",
+ "component-emitter": "~1.3.0",
+ "debug": "~3.1.0",
+ "engine.io-client": "~3.5.0",
+ "has-binary2": "~1.0.2",
+ "indexof": "0.0.1",
+ "parseqs": "0.0.6",
+ "parseuri": "0.0.6",
+ "socket.io-parser": "~3.3.0",
+ "to-array": "0.1.4"
+ }
+ },
+ "node_modules/socket.io-client/node_modules/component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
+ },
+ "node_modules/socket.io-client/node_modules/debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/socket.io-client/node_modules/socket.io-parser": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz",
+ "integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==",
+ "dependencies": {
+ "component-emitter": "~1.3.0",
+ "debug": "~3.1.0",
+ "isarray": "2.0.1"
+ }
+ },
+ "node_modules/socket.io-parser": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz",
+ "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==",
+ "dependencies": {
+ "component-emitter": "1.2.1",
+ "debug": "~4.1.0",
+ "isarray": "2.0.1"
+ }
+ },
+ "node_modules/socket.io-parser/node_modules/debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/socket.io-parser/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/socket.io/node_modules/debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/socket.io/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-resolve": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
+ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
+ "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated",
+ "dependencies": {
+ "atob": "^2.1.1",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "node_modules/source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "deprecated": "See https://github.com/lydell/source-map-url#deprecated"
+ },
+ "node_modules/split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "dependencies": {
+ "extend-shallow": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/standard-as-callback": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.0.1.tgz",
+ "integrity": "sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==",
+ "optional": true
+ },
+ "node_modules/static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "dependencies": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/static-extend/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dependencies": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/term-size": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
+ "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=",
+ "dependencies": {
+ "execa": "^0.7.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/timed-out": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
+ "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/to-array": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
+ "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA="
+ },
+ "node_modules/to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/to-object-path/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "dependencies": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dependencies": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/touch": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
+ "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
+ "dependencies": {
+ "nopt": "~1.0.10"
+ },
+ "bin": {
+ "nodetouch": "bin/nodetouch.js"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/uid-safe": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
+ "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
+ "dependencies": {
+ "random-bytes": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/undefsafe": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
+ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA=="
+ },
+ "node_modules/union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "dependencies": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unique-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
+ "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
+ "dependencies": {
+ "crypto-random-string": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dependencies": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unset-value/node_modules/has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dependencies": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unset-value/node_modules/has-value/node_modules/isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dependencies": {
+ "isarray": "1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unset-value/node_modules/has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unset-value/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "node_modules/unzip-response": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
+ "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
+ "engines": {
+ "node": ">=4",
+ "yarn": "*"
+ }
+ },
+ "node_modules/update-notifier": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz",
+ "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==",
+ "dependencies": {
+ "boxen": "^1.2.1",
+ "chalk": "^2.0.1",
+ "configstore": "^3.0.0",
+ "import-lazy": "^2.1.0",
+ "is-ci": "^1.0.10",
+ "is-installed-globally": "^0.1.0",
+ "is-npm": "^1.0.0",
+ "latest-version": "^3.0.0",
+ "semver-diff": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "deprecated": "Please see https://github.com/lydell/urix#deprecated"
+ },
+ "node_modules/url-parse-lax": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
+ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
+ "dependencies": {
+ "prepend-http": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/util": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
+ "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
+ "dependencies": {
+ "inherits": "2.0.3"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/widest-line": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
+ "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
+ "dependencies": {
+ "string-width": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/write-file-atomic": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
+ "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
+ "dependencies": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "node_modules/ws": {
+ "version": "7.4.6",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
+ "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xdg-basedir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
+ "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/xmlhttprequest-ssl": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
+ "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ },
+ "node_modules/yeast": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
+ "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
+ }
+ }
+}
diff --git a/node_modules/async-limiter/.eslintignore b/node_modules/async-limiter/.eslintignore
deleted file mode 100755
index e1661e5..0000000
--- a/node_modules/async-limiter/.eslintignore
+++ /dev/null
@@ -1,2 +0,0 @@
-coverage
-.nyc_output
\ No newline at end of file
diff --git a/node_modules/async-limiter/.nycrc b/node_modules/async-limiter/.nycrc
deleted file mode 100755
index 874c1de..0000000
--- a/node_modules/async-limiter/.nycrc
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "check-coverage": false,
- "lines": 99,
- "statements": 99,
- "functions": 99,
- "branches": 99,
- "include": [
- "index.js"
- ]
-}
\ No newline at end of file
diff --git a/node_modules/async-limiter/.travis.yml b/node_modules/async-limiter/.travis.yml
deleted file mode 100755
index 37026e2..0000000
--- a/node_modules/async-limiter/.travis.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-language: node_js
-node_js:
- - "6"
- - "8"
- - "10"
- - "node"
-script: npm run travis
-cache:
- yarn: true
diff --git a/node_modules/async-limiter/LICENSE b/node_modules/async-limiter/LICENSE
deleted file mode 100755
index 9c91fb2..0000000
--- a/node_modules/async-limiter/LICENSE
+++ /dev/null
@@ -1,8 +0,0 @@
-The MIT License (MIT)
-Copyright (c) 2017 Samuel Reed
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/async-limiter/index.js b/node_modules/async-limiter/index.js
deleted file mode 100755
index c9bd2f9..0000000
--- a/node_modules/async-limiter/index.js
+++ /dev/null
@@ -1,67 +0,0 @@
-'use strict';
-
-function Queue(options) {
- if (!(this instanceof Queue)) {
- return new Queue(options);
- }
-
- options = options || {};
- this.concurrency = options.concurrency || Infinity;
- this.pending = 0;
- this.jobs = [];
- this.cbs = [];
- this._done = done.bind(this);
-}
-
-var arrayAddMethods = [
- 'push',
- 'unshift',
- 'splice'
-];
-
-arrayAddMethods.forEach(function(method) {
- Queue.prototype[method] = function() {
- var methodResult = Array.prototype[method].apply(this.jobs, arguments);
- this._run();
- return methodResult;
- };
-});
-
-Object.defineProperty(Queue.prototype, 'length', {
- get: function() {
- return this.pending + this.jobs.length;
- }
-});
-
-Queue.prototype._run = function() {
- if (this.pending === this.concurrency) {
- return;
- }
- if (this.jobs.length) {
- var job = this.jobs.shift();
- this.pending++;
- job(this._done);
- this._run();
- }
-
- if (this.pending === 0) {
- while (this.cbs.length !== 0) {
- var cb = this.cbs.pop();
- process.nextTick(cb);
- }
- }
-};
-
-Queue.prototype.onDone = function(cb) {
- if (typeof cb === 'function') {
- this.cbs.push(cb);
- this._run();
- }
-};
-
-function done() {
- this.pending--;
- this._run();
-}
-
-module.exports = Queue;
diff --git a/node_modules/async-limiter/package.json b/node_modules/async-limiter/package.json
deleted file mode 100755
index 756b6cf..0000000
--- a/node_modules/async-limiter/package.json
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "_from": "async-limiter@~1.0.0",
- "_id": "async-limiter@1.0.1",
- "_inBundle": false,
- "_integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
- "_location": "/async-limiter",
- "_phantomChildren": {},
- "_requested": {
- "type": "range",
- "registry": true,
- "raw": "async-limiter@~1.0.0",
- "name": "async-limiter",
- "escapedName": "async-limiter",
- "rawSpec": "~1.0.0",
- "saveSpec": null,
- "fetchSpec": "~1.0.0"
- },
- "_requiredBy": [
- "/ws"
- ],
- "_resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
- "_shasum": "dd379e94f0db8310b08291f9d64c3209766617fd",
- "_spec": "async-limiter@~1.0.0",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/ws",
- "author": {
- "name": "Samuel Reed"
- },
- "bugs": {
- "url": "https://github.com/strml/async-limiter/issues"
- },
- "bundleDependencies": false,
- "dependencies": {},
- "deprecated": false,
- "description": "asynchronous function queue with adjustable concurrency",
- "devDependencies": {
- "coveralls": "^3.0.3",
- "eslint": "^5.16.0",
- "eslint-plugin-mocha": "^5.3.0",
- "intelli-espower-loader": "^1.0.1",
- "mocha": "^6.1.4",
- "nyc": "^14.1.1",
- "power-assert": "^1.6.1"
- },
- "homepage": "https://github.com/strml/async-limiter#readme",
- "keywords": [
- "throttle",
- "async",
- "limiter",
- "asynchronous",
- "job",
- "task",
- "concurrency",
- "concurrent"
- ],
- "license": "MIT",
- "name": "async-limiter",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/strml/async-limiter.git"
- },
- "scripts": {
- "coverage": "nyc npm test && nyc report --reporter=text-lcov | coveralls",
- "example": "node example",
- "lint": "eslint .",
- "test": "mocha --require intelli-espower-loader test/",
- "travis": "npm run lint && npm run test"
- },
- "version": "1.0.1"
-}
diff --git a/node_modules/async-limiter/readme.md b/node_modules/async-limiter/readme.md
deleted file mode 100755
index fcaa22f..0000000
--- a/node_modules/async-limiter/readme.md
+++ /dev/null
@@ -1,132 +0,0 @@
-# Async-Limiter
-
-A module for limiting concurrent asynchronous actions in flight. Forked from [queue](https://github.com/jessetane/queue).
-
-[![npm](http://img.shields.io/npm/v/async-limiter.svg?style=flat-square)](http://www.npmjs.org/async-limiter)
-[![tests](https://img.shields.io/travis/STRML/async-limiter.svg?style=flat-square&branch=master)](https://travis-ci.org/STRML/async-limiter)
-[![coverage](https://img.shields.io/coveralls/STRML/async-limiter.svg?style=flat-square&branch=master)](https://coveralls.io/r/STRML/async-limiter)
-
-This module exports a class `Limiter` that implements some of the `Array` API.
-Pass async functions (ones that accept a callback or return a promise) to an instance's additive array methods.
-
-## Motivation
-
-Certain functions, like `zlib`, have [undesirable behavior](https://github.com/nodejs/node/issues/8871#issuecomment-250915913) when
-run at infinite concurrency.
-
-In this case, it is actually faster, and takes far less memory, to limit concurrency.
-
-This module should do the absolute minimum work necessary to queue up functions. PRs are welcome that would
-make this module faster or lighter, but new functionality is not desired.
-
-Style should confirm to nodejs/node style.
-
-## Example
-
-``` javascript
-var Limiter = require('async-limiter')
-
-var t = new Limiter({concurrency: 2});
-var results = []
-
-// add jobs using the familiar Array API
-t.push(function (cb) {
- results.push('two')
- cb()
-})
-
-t.push(
- function (cb) {
- results.push('four')
- cb()
- },
- function (cb) {
- results.push('five')
- cb()
- }
-)
-
-t.unshift(function (cb) {
- results.push('one')
- cb()
-})
-
-t.splice(2, 0, function (cb) {
- results.push('three')
- cb()
-})
-
-// Jobs run automatically. If you want a callback when all are done,
-// call 'onDone()'.
-t.onDone(function () {
- console.log('all done:', results)
-})
-```
-
-## Zlib Example
-
-```js
-const zlib = require('zlib');
-const Limiter = require('async-limiter');
-
-const message = {some: "data"};
-const payload = new Buffer(JSON.stringify(message));
-
-// Try with different concurrency values to see how this actually
-// slows significantly with higher concurrency!
-//
-// 5: 1398.607ms
-// 10: 1375.668ms
-// Infinity: 4423.300ms
-//
-const t = new Limiter({concurrency: 5});
-function deflate(payload, cb) {
- t.push(function(done) {
- zlib.deflate(payload, function(err, buffer) {
- done();
- cb(err, buffer);
- });
- });
-}
-
-console.time('deflate');
-for(let i = 0; i < 30000; ++i) {
- deflate(payload, function (err, buffer) {});
-}
-t.onDone(function() {
- console.timeEnd('deflate');
-});
-```
-
-## Install
-
-`npm install async-limiter`
-
-## Test
-
-`npm test`
-
-## API
-
-### `var t = new Limiter([opts])`
-Constructor. `opts` may contain inital values for:
-* `t.concurrency`
-
-## Instance methods
-
-### `t.onDone(fn)`
-`fn` will be called once and only once, when the queue is empty.
-
-## Instance methods mixed in from `Array`
-Mozilla has docs on how these methods work [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array).
-### `t.push(element1, ..., elementN)`
-### `t.unshift(element1, ..., elementN)`
-### `t.splice(index , howMany[, element1[, ...[, elementN]]])`
-
-## Properties
-### `t.concurrency`
-Max number of jobs the queue should process concurrently, defaults to `Infinity`.
-
-### `t.length`
-Jobs pending + jobs to process (readonly).
-
diff --git a/node_modules/atob/LICENSE b/node_modules/atob/LICENSE
old mode 100755
new mode 100644
diff --git a/node_modules/atob/LICENSE.DOCS b/node_modules/atob/LICENSE.DOCS
old mode 100755
new mode 100644
diff --git a/node_modules/atob/README.md b/node_modules/atob/README.md
old mode 100755
new mode 100644
diff --git a/node_modules/atob/bower.json b/node_modules/atob/bower.json
old mode 100755
new mode 100644
diff --git a/node_modules/atob/browser-atob.js b/node_modules/atob/browser-atob.js
old mode 100755
new mode 100644
diff --git a/node_modules/atob/node-atob.js b/node_modules/atob/node-atob.js
old mode 100755
new mode 100644
diff --git a/node_modules/atob/package.json b/node_modules/atob/package.json
old mode 100755
new mode 100644
index e67d2c4..79bfd9b
--- a/node_modules/atob/package.json
+++ b/node_modules/atob/package.json
@@ -1,53 +1,24 @@
{
- "_from": "atob@^2.1.1",
- "_id": "atob@2.1.2",
- "_inBundle": false,
- "_integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
- "_location": "/atob",
- "_phantomChildren": {},
- "_requested": {
- "type": "range",
- "registry": true,
- "raw": "atob@^2.1.1",
- "name": "atob",
- "escapedName": "atob",
- "rawSpec": "^2.1.1",
- "saveSpec": null,
- "fetchSpec": "^2.1.1"
- },
- "_requiredBy": [
- "/source-map-resolve"
- ],
- "_resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
- "_shasum": "6d9517eb9e030d2436666651e86bd9f6f13533c9",
- "_spec": "atob@^2.1.1",
- "_where": "/home/pi/Node Projects/x-chat/node_modules/source-map-resolve",
- "author": {
- "name": "AJ ONeal",
- "email": "coolaj86@gmail.com",
- "url": "https://coolaj86.com"
- },
- "bin": {
- "atob": "bin/atob.js"
- },
- "browser": "browser-atob.js",
- "bundleDependencies": false,
- "deprecated": false,
+ "name": "atob",
+ "homepage": "https://git.coolaj86.com/coolaj86/atob.js.git",
"description": "atob for Node.JS and Linux / Mac / Windows CLI (it's a one-liner)",
- "engines": {
- "node": ">= 4.5.0"
+ "repository": {
+ "type": "git",
+ "url": "git://git.coolaj86.com/coolaj86/atob.js.git"
},
- "homepage": "https://git.coolaj86.com/coolaj86/atob.js.git",
"keywords": [
"atob",
"browser"
],
- "license": "(MIT OR Apache-2.0)",
+ "author": "AJ ONeal (https://coolaj86.com)",
+ "engines": {
+ "node": ">= 4.5.0"
+ },
"main": "node-atob.js",
- "name": "atob",
- "repository": {
- "type": "git",
- "url": "git://git.coolaj86.com/coolaj86/atob.js.git"
+ "browser": "browser-atob.js",
+ "bin": {
+ "atob": "bin/atob.js"
},
+ "license": "(MIT OR Apache-2.0)",
"version": "2.1.2"
}
diff --git a/node_modules/atob/test.js b/node_modules/atob/test.js
old mode 100755
new mode 100644
diff --git a/node_modules/base64-arraybuffer/lib/base64-arraybuffer.js b/node_modules/base64-arraybuffer/lib/base64-arraybuffer.js
index e6b6306..362fbfa 100755
--- a/node_modules/base64-arraybuffer/lib/base64-arraybuffer.js
+++ b/node_modules/base64-arraybuffer/lib/base64-arraybuffer.js
@@ -5,17 +5,9 @@
* Copyright (c) 2012 Niklas von Hertzen
* Licensed under the MIT license.
*/
-(function(){
+(function(chars){
"use strict";
- var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- // Use a lookup table to find the index.
- var lookup = new Uint8Array(256);
- for (var i = 0; i < chars.length; i++) {
- lookup[chars.charCodeAt(i)] = i;
- }
-
exports.encode = function(arraybuffer) {
var bytes = new Uint8Array(arraybuffer),
i, len = bytes.length, base64 = "";
@@ -52,10 +44,10 @@
bytes = new Uint8Array(arraybuffer);
for (i = 0; i < len; i+=4) {
- encoded1 = lookup[base64.charCodeAt(i)];
- encoded2 = lookup[base64.charCodeAt(i+1)];
- encoded3 = lookup[base64.charCodeAt(i+2)];
- encoded4 = lookup[base64.charCodeAt(i+3)];
+ encoded1 = chars.indexOf(base64[i]);
+ encoded2 = chars.indexOf(base64[i+1]);
+ encoded3 = chars.indexOf(base64[i+2]);
+ encoded4 = chars.indexOf(base64[i+3]);
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
@@ -64,4 +56,4 @@
return arraybuffer;
};
-})();
+})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
diff --git a/node_modules/base64-arraybuffer/package.json b/node_modules/base64-arraybuffer/package.json
index 0df9d0b..16d65cd 100755
--- a/node_modules/base64-arraybuffer/package.json
+++ b/node_modules/base64-arraybuffer/package.json
@@ -1,28 +1,27 @@
{
- "_from": "base64-arraybuffer@0.1.5",
- "_id": "base64-arraybuffer@0.1.5",
+ "_from": "base64-arraybuffer@0.1.4",
+ "_id": "base64-arraybuffer@0.1.4",
"_inBundle": false,
- "_integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
+ "_integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=",
"_location": "/base64-arraybuffer",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
- "raw": "base64-arraybuffer@0.1.5",
+ "raw": "base64-arraybuffer@0.1.4",
"name": "base64-arraybuffer",
"escapedName": "base64-arraybuffer",
- "rawSpec": "0.1.5",
+ "rawSpec": "0.1.4",
"saveSpec": null,
- "fetchSpec": "0.1.5"
+ "fetchSpec": "0.1.4"
},
"_requiredBy": [
- "/engine.io-parser",
- "/socket.io-client"
+ "/engine.io-parser"
],
- "_resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
- "_shasum": "73926771923b5a19747ad666aa5cd4bf9c6e9ce8",
- "_spec": "base64-arraybuffer@0.1.5",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/engine.io-parser",
+ "_resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
+ "_shasum": "9818c79e059b1355f97e0428a017c838e90ba812",
+ "_spec": "base64-arraybuffer@0.1.4",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\engine.io-parser",
"author": {
"name": "Niklas von Hertzen",
"email": "niklasvh@gmail.com",
@@ -61,5 +60,5 @@
"scripts": {
"test": "grunt nodeunit"
},
- "version": "0.1.5"
+ "version": "0.1.4"
}
diff --git a/node_modules/base64id/.npmignore b/node_modules/base64id/.npmignore
deleted file mode 100755
index 39e9864..0000000
--- a/node_modules/base64id/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-support
-test
-examples
diff --git a/node_modules/base64id/CHANGELOG.md b/node_modules/base64id/CHANGELOG.md
new file mode 100644
index 0000000..b2b8332
--- /dev/null
+++ b/node_modules/base64id/CHANGELOG.md
@@ -0,0 +1,16 @@
+# [2.0.0](https://github.com/faeldt/base64id/compare/1.0.0...2.0.0) (2019-05-27)
+
+
+### Code Refactoring
+
+* **buffer:** replace deprecated Buffer constructor usage ([#11](https://github.com/faeldt/base64id/issues/11)) ([ccfba54](https://github.com/faeldt/base64id/commit/ccfba54))
+
+
+### BREAKING CHANGES
+
+* **buffer:** drop support for Node.js ≤ 4.4.x and 5.0.0 - 5.9.x
+
+See: https://nodejs.org/en/docs/guides/buffer-constructor-deprecation/
+
+
+
diff --git a/node_modules/base64id/lib/base64id.js b/node_modules/base64id/lib/base64id.js
index f688159..15afe74 100755
--- a/node_modules/base64id/lib/base64id.js
+++ b/node_modules/base64id/lib/base64id.js
@@ -78,7 +78,7 @@ Base64Id.prototype.getRandomBytes = function(bytes) {
*/
Base64Id.prototype.generateId = function () {
- var rand = new Buffer(15); // multiple of 3 for base64
+ var rand = Buffer.alloc(15); // multiple of 3 for base64
if (!rand.writeInt32BE) {
return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString()
+ Math.abs(Math.random() * Math.random() * Date.now() | 0).toString();
diff --git a/node_modules/base64id/package.json b/node_modules/base64id/package.json
index 4215c6a..66f7cab 100755
--- a/node_modules/base64id/package.json
+++ b/node_modules/base64id/package.json
@@ -1,27 +1,27 @@
{
- "_from": "base64id@1.0.0",
- "_id": "base64id@1.0.0",
+ "_from": "base64id@2.0.0",
+ "_id": "base64id@2.0.0",
"_inBundle": false,
- "_integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
+ "_integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
"_location": "/base64id",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
- "raw": "base64id@1.0.0",
+ "raw": "base64id@2.0.0",
"name": "base64id",
"escapedName": "base64id",
- "rawSpec": "1.0.0",
+ "rawSpec": "2.0.0",
"saveSpec": null,
- "fetchSpec": "1.0.0"
+ "fetchSpec": "2.0.0"
},
"_requiredBy": [
"/engine.io"
],
- "_resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
- "_shasum": "47688cb99bb6804f0e06d3e763b1c32e57d8e6b6",
- "_spec": "base64id@1.0.0",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/engine.io",
+ "_resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
+ "_shasum": "2770ac6bc47d312af97a8bf9a634342e0cd25cb6",
+ "_spec": "base64id@2.0.0",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\engine.io",
"author": {
"name": "Kristian Faeldt",
"email": "faeldt_kristian@cyberagent.co.jp"
@@ -33,7 +33,7 @@
"deprecated": false,
"description": "Generates a base64 id",
"engines": {
- "node": ">= 0.4.0"
+ "node": "^4.5.0 || >= 5.9"
},
"homepage": "https://github.com/faeldt/base64id#readme",
"license": "MIT",
@@ -43,5 +43,5 @@
"type": "git",
"url": "git+https://github.com/faeldt/base64id.git"
},
- "version": "1.0.0"
+ "version": "2.0.0"
}
diff --git a/node_modules/better-assert/.npmignore b/node_modules/better-assert/.npmignore
deleted file mode 100755
index f1250e5..0000000
--- a/node_modules/better-assert/.npmignore
+++ /dev/null
@@ -1,4 +0,0 @@
-support
-test
-examples
-*.sock
diff --git a/node_modules/better-assert/History.md b/node_modules/better-assert/History.md
deleted file mode 100755
index cbb579b..0000000
--- a/node_modules/better-assert/History.md
+++ /dev/null
@@ -1,15 +0,0 @@
-
-1.0.0 / 2013-02-03
-==================
-
- * Stop using the removed magic __stack global getter
-
-0.1.0 / 2012-10-04
-==================
-
- * add throwing of AssertionError for test frameworks etc
-
-0.0.1 / 2010-01-03
-==================
-
- * Initial release
diff --git a/node_modules/better-assert/Makefile b/node_modules/better-assert/Makefile
deleted file mode 100755
index 36a3ed7..0000000
--- a/node_modules/better-assert/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-
-test:
- @echo "populate me"
-
-.PHONY: test
\ No newline at end of file
diff --git a/node_modules/better-assert/Readme.md b/node_modules/better-assert/Readme.md
deleted file mode 100755
index d8d3a63..0000000
--- a/node_modules/better-assert/Readme.md
+++ /dev/null
@@ -1,61 +0,0 @@
-
-# better-assert
-
- Better c-style assertions using [callsite](https://github.com/visionmedia/callsite) for
- self-documenting failure messages.
-
-## Installation
-
- $ npm install better-assert
-
-## Example
-
- By default assertions are enabled, however the __NO_ASSERT__ environment variable
- will deactivate them when truthy.
-
-```js
-var assert = require('better-assert');
-
-test();
-
-function test() {
- var user = { name: 'tobi' };
- assert('tobi' == user.name);
- assert('number' == typeof user.age);
-}
-
-AssertionError: 'number' == typeof user.age
- at test (/Users/tj/projects/better-assert/example.js:9:3)
- at Object. (/Users/tj/projects/better-assert/example.js:4:1)
- at Module._compile (module.js:449:26)
- at Object.Module._extensions..js (module.js:467:10)
- at Module.load (module.js:356:32)
- at Function.Module._load (module.js:312:12)
- at Module.runMain (module.js:492:10)
- at process.startup.processNextTick.process._tickCallback (node.js:244:9)
-```
-
-## License
-
-(The MIT License)
-
-Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-'Software'), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/node_modules/better-assert/example.js b/node_modules/better-assert/example.js
deleted file mode 100755
index 688c29e..0000000
--- a/node_modules/better-assert/example.js
+++ /dev/null
@@ -1,10 +0,0 @@
-
-var assert = require('./');
-
-test();
-
-function test() {
- var user = { name: 'tobi' };
- assert('tobi' == user.name);
- assert('number' == typeof user.age);
-}
\ No newline at end of file
diff --git a/node_modules/better-assert/index.js b/node_modules/better-assert/index.js
deleted file mode 100755
index fd1c9b7..0000000
--- a/node_modules/better-assert/index.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Module dependencies.
- */
-
-var AssertionError = require('assert').AssertionError
- , callsite = require('callsite')
- , fs = require('fs')
-
-/**
- * Expose `assert`.
- */
-
-module.exports = process.env.NO_ASSERT
- ? function(){}
- : assert;
-
-/**
- * Assert the given `expr`.
- */
-
-function assert(expr) {
- if (expr) return;
-
- var stack = callsite();
- var call = stack[1];
- var file = call.getFileName();
- var lineno = call.getLineNumber();
- var src = fs.readFileSync(file, 'utf8');
- var line = src.split('\n')[lineno-1];
- var src = line.match(/assert\((.*)\)/)[1];
-
- var err = new AssertionError({
- message: src,
- stackStartFunction: stack[0].getFunction()
- });
-
- throw err;
-}
diff --git a/node_modules/better-assert/package.json b/node_modules/better-assert/package.json
deleted file mode 100755
index e17b1e0..0000000
--- a/node_modules/better-assert/package.json
+++ /dev/null
@@ -1,65 +0,0 @@
-{
- "_from": "better-assert@~1.0.0",
- "_id": "better-assert@1.0.2",
- "_inBundle": false,
- "_integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
- "_location": "/better-assert",
- "_phantomChildren": {},
- "_requested": {
- "type": "range",
- "registry": true,
- "raw": "better-assert@~1.0.0",
- "name": "better-assert",
- "escapedName": "better-assert",
- "rawSpec": "~1.0.0",
- "saveSpec": null,
- "fetchSpec": "~1.0.0"
- },
- "_requiredBy": [
- "/parseqs",
- "/parseuri"
- ],
- "_resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
- "_shasum": "40866b9e1b9e0b55b481894311e68faffaebc522",
- "_spec": "better-assert@~1.0.0",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/parseqs",
- "author": {
- "name": "TJ Holowaychuk",
- "email": "tj@vision-media.ca"
- },
- "bugs": {
- "url": "https://github.com/visionmedia/better-assert/issues"
- },
- "bundleDependencies": false,
- "contributors": [
- {
- "name": "TonyHe",
- "email": "coolhzb@163.com"
- },
- {
- "name": "ForbesLindesay"
- }
- ],
- "dependencies": {
- "callsite": "1.0.0"
- },
- "deprecated": false,
- "description": "Better assertions for node, reporting the expr, filename, lineno etc",
- "engines": {
- "node": "*"
- },
- "homepage": "https://github.com/visionmedia/better-assert#readme",
- "keywords": [
- "assert",
- "stack",
- "trace",
- "debug"
- ],
- "main": "index",
- "name": "better-assert",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/visionmedia/better-assert.git"
- },
- "version": "1.0.2"
-}
diff --git a/node_modules/callsite/.npmignore b/node_modules/callsite/.npmignore
deleted file mode 100755
index f1250e5..0000000
--- a/node_modules/callsite/.npmignore
+++ /dev/null
@@ -1,4 +0,0 @@
-support
-test
-examples
-*.sock
diff --git a/node_modules/callsite/History.md b/node_modules/callsite/History.md
deleted file mode 100755
index 4994198..0000000
--- a/node_modules/callsite/History.md
+++ /dev/null
@@ -1,10 +0,0 @@
-
-1.0.0 / 2013-01-24
-==================
-
- * remove lame magical getters
-
-0.0.1 / 2010-01-03
-==================
-
- * Initial release
diff --git a/node_modules/callsite/Makefile b/node_modules/callsite/Makefile
deleted file mode 100755
index 634e372..0000000
--- a/node_modules/callsite/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-
-test:
- @./node_modules/.bin/mocha \
- --require should
-
-.PHONY: test
\ No newline at end of file
diff --git a/node_modules/callsite/Readme.md b/node_modules/callsite/Readme.md
deleted file mode 100755
index 0dbd16a..0000000
--- a/node_modules/callsite/Readme.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# callstack
-
- Access to v8's "raw" `CallSite`s.
-
-## Installation
-
- $ npm install callsite
-
-## Example
-
-```js
-var stack = require('callsite');
-
-foo();
-
-function foo() {
- bar();
-}
-
-function bar() {
- baz();
-}
-
-function baz() {
- console.log();
- stack().forEach(function(site){
- console.log(' \033[36m%s\033[90m in %s:%d\033[0m'
- , site.getFunctionName() || 'anonymous'
- , site.getFileName()
- , site.getLineNumber());
- });
- console.log();
-}
-```
-
-## Why?
-
- Because you can do weird, stupid, clever, wacky things such as:
-
- - [better-assert](https://github.com/visionmedia/better-assert)
-
-## License
-
- MIT
diff --git a/node_modules/callsite/index.js b/node_modules/callsite/index.js
deleted file mode 100755
index d3ee6f8..0000000
--- a/node_modules/callsite/index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-
-module.exports = function(){
- var orig = Error.prepareStackTrace;
- Error.prepareStackTrace = function(_, stack){ return stack; };
- var err = new Error;
- Error.captureStackTrace(err, arguments.callee);
- var stack = err.stack;
- Error.prepareStackTrace = orig;
- return stack;
-};
diff --git a/node_modules/callsite/package.json b/node_modules/callsite/package.json
deleted file mode 100755
index 0e40063..0000000
--- a/node_modules/callsite/package.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
- "_from": "callsite@1.0.0",
- "_id": "callsite@1.0.0",
- "_inBundle": false,
- "_integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
- "_location": "/callsite",
- "_phantomChildren": {},
- "_requested": {
- "type": "version",
- "registry": true,
- "raw": "callsite@1.0.0",
- "name": "callsite",
- "escapedName": "callsite",
- "rawSpec": "1.0.0",
- "saveSpec": null,
- "fetchSpec": "1.0.0"
- },
- "_requiredBy": [
- "/better-assert"
- ],
- "_resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
- "_shasum": "280398e5d664bd74038b6f0905153e6e8af1bc20",
- "_spec": "callsite@1.0.0",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/better-assert",
- "author": {
- "name": "TJ Holowaychuk",
- "email": "tj@vision-media.ca"
- },
- "bundleDependencies": false,
- "dependencies": {},
- "deprecated": false,
- "description": "access to v8's CallSites",
- "devDependencies": {
- "mocha": "*",
- "should": "*"
- },
- "engines": {
- "node": "*"
- },
- "keywords": [
- "stack",
- "trace",
- "line"
- ],
- "main": "index",
- "name": "callsite",
- "version": "1.0.0"
-}
diff --git a/node_modules/connect-redis/node_modules/redis-parser/.npmignore b/node_modules/connect-redis/node_modules/redis-parser/.npmignore
new file mode 100644
index 0000000..af7d371
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis-parser/.npmignore
@@ -0,0 +1,15 @@
+# IntelliJ project files
+.idea
+*.iml
+out
+gen
+
+# Unrelevant files and folders
+benchmark
+coverage
+test
+.travis.yml
+.gitignore
+*.log
+.vscode
+.codeclimate.yml
\ No newline at end of file
diff --git a/node_modules/connect-redis/node_modules/redis-parser/LICENSE b/node_modules/connect-redis/node_modules/redis-parser/LICENSE
new file mode 100644
index 0000000..39d23f8
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis-parser/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 NodeRedis
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/node_modules/connect-redis/node_modules/redis-parser/README.md b/node_modules/connect-redis/node_modules/redis-parser/README.md
new file mode 100644
index 0000000..ff448f0
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis-parser/README.md
@@ -0,0 +1,163 @@
+[![Build Status](https://travis-ci.org/NodeRedis/node-redis-parser.png?branch=master)](https://travis-ci.org/NodeRedis/node-redis-parser)
+[![Test Coverage](https://codeclimate.com/github/NodeRedis/node-redis-parser/badges/coverage.svg)](https://codeclimate.com/github/NodeRedis/node-redis-parser/coverage)
+[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
+
+# redis-parser
+
+A high performance javascript redis parser built for [node_redis](https://github.com/NodeRedis/node_redis) and [ioredis](https://github.com/luin/ioredis). Parses all [RESP](http://redis.io/topics/protocol) data.
+
+## Install
+
+Install with [NPM](https://npmjs.org/):
+
+ npm install redis-parser
+
+## Usage
+
+```js
+var Parser = require('redis-parser');
+
+var myParser = new Parser(options);
+```
+
+### Options
+
+* `returnReply`: *function*; mandatory
+* `returnError`: *function*; mandatory
+* `returnFatalError`: *function*; optional, defaults to the returnError function
+* `returnBuffers`: *boolean*; optional, defaults to false
+* `stringNumbers`: *boolean*; optional, defaults to false
+
+### Functions
+
+* `reset()`: reset the parser to it's initial state
+* `setReturnBuffers(boolean)`: (JSParser only) set the returnBuffers option on/off without resetting the parser
+* `setStringNumbers(boolean)`: (JSParser only) set the stringNumbers option on/off without resetting the parser
+
+### Error classes
+
+* `RedisError` sub class of Error
+* `ReplyError` sub class of RedisError
+* `ParserError` sub class of RedisError
+
+All Redis errors will be returned as `ReplyErrors` while a parser error is returned as `ParserError`.
+All error classes are exported by the parser.
+
+### Example
+
+```js
+var Parser = require("redis-parser");
+
+function Library () {}
+
+Library.prototype.returnReply = function (reply) { ... }
+Library.prototype.returnError = function (err) { ... }
+Library.prototype.returnFatalError = function (err) { ... }
+
+var lib = new Library();
+
+var parser = new Parser({
+ returnReply: function(reply) {
+ lib.returnReply(reply);
+ },
+ returnError: function(err) {
+ lib.returnError(err);
+ },
+ returnFatalError: function (err) {
+ lib.returnFatalError(err);
+ }
+});
+
+Library.prototype.streamHandler = function () {
+ this.stream.on('data', function (buffer) {
+ // Here the data (e.g. `new Buffer('$5\r\nHello\r\n'`)) is passed to the parser and the result is passed to either function depending on the provided data.
+ parser.execute(buffer);
+ });
+};
+```
+You do not have to use the returnFatalError function. Fatal errors will be returned in the normal error function in that case.
+
+And if you want to return buffers instead of strings, you can do this by adding the `returnBuffers` option.
+
+If you handle with big numbers that are to large for JS (Number.MAX_SAFE_INTEGER === 2^53 - 16) please use the `stringNumbers` option. That way all numbers are going to be returned as String and you can handle them safely.
+
+```js
+// Same functions as in the first example
+
+var parser = new Parser({
+ returnReply: function(reply) {
+ lib.returnReply(reply);
+ },
+ returnError: function(err) {
+ lib.returnError(err);
+ },
+ returnBuffers: true, // All strings are returned as Buffer e.g.
+ stringNumbers: true // All numbers are returned as String
+});
+
+// The streamHandler as above
+```
+
+## Protocol errors
+
+To handle protocol errors (this is very unlikely to happen) gracefully you should add the returnFatalError option, reject any still running command (they might have been processed properly but the reply is just wrong), destroy the socket and reconnect. Note that while doing this no new command may be added, so all new commands have to be buffered in the meantime, otherwise a chunk might still contain partial data of a following command that was already processed properly but answered in the same chunk as the command that resulted in the protocol error.
+
+## Contribute
+
+The parser is highly optimized but there may still be further optimizations possible.
+
+ npm install
+ npm test
+ npm run benchmark
+
+Currently the benchmark compares the performance against the hiredis parser:
+
+ HIREDIS: $ multiple chunks in a bulk string x 859,880 ops/sec ±1.22% (82 runs sampled)
+ HIREDIS BUF: $ multiple chunks in a bulk string x 608,869 ops/sec ±1.72% (85 runs sampled)
+ JS PARSER: $ multiple chunks in a bulk string x 910,590 ops/sec ±0.87% (89 runs sampled)
+ JS PARSER BUF: $ multiple chunks in a bulk string x 1,299,507 ops/sec ±2.18% (84 runs sampled)
+
+ HIREDIS: + multiple chunks in a string x 1,787,203 ops/sec ±0.58% (96 runs sampled)
+ HIREDIS BUF: + multiple chunks in a string x 943,584 ops/sec ±1.62% (87 runs sampled)
+ JS PARSER: + multiple chunks in a string x 2,008,264 ops/sec ±1.01% (91 runs sampled)
+ JS PARSER BUF: + multiple chunks in a string x 2,045,546 ops/sec ±0.78% (91 runs sampled)
+
+ HIREDIS: $ 4mb bulk string x 310 ops/sec ±1.58% (75 runs sampled)
+ HIREDIS BUF: $ 4mb bulk string x 471 ops/sec ±2.28% (78 runs sampled)
+ JS PARSER: $ 4mb bulk string x 747 ops/sec ±2.43% (85 runs sampled)
+ JS PARSER BUF: $ 4mb bulk string x 846 ops/sec ±5.52% (72 runs sampled)
+
+ HIREDIS: + simple string x 2,324,866 ops/sec ±1.61% (90 runs sampled)
+ HIREDIS BUF: + simple string x 1,085,823 ops/sec ±2.47% (82 runs sampled)
+ JS PARSER: + simple string x 4,567,358 ops/sec ±1.97% (81 runs sampled)
+ JS PARSER BUF: + simple string x 5,433,901 ops/sec ±0.66% (93 runs sampled)
+
+ HIREDIS: : integer x 2,332,946 ops/sec ±0.47% (93 runs sampled)
+ JS PARSER: : integer x 17,730,449 ops/sec ±0.73% (91 runs sampled)
+ JS PARSER STR: : integer x 12,942,037 ops/sec ±0.51% (92 runs sampled)
+
+ HIREDIS: : big integer x 2,012,572 ops/sec ±0.33% (93 runs sampled)
+ JS PARSER: : big integer x 10,210,923 ops/sec ±0.94% (94 runs sampled)
+ JS PARSER STR: : big integer x 4,453,320 ops/sec ±0.52% (94 runs sampled)
+
+ HIREDIS: * array x 44,479 ops/sec ±0.55% (94 runs sampled)
+ HIREDIS BUF: * array x 14,391 ops/sec ±1.04% (86 runs sampled)
+ JS PARSER: * array x 53,796 ops/sec ±2.08% (79 runs sampled)
+ JS PARSER BUF: * array x 72,428 ops/sec ±0.72% (93 runs sampled)
+
+ HIREDIS: * big nested array x 217 ops/sec ±0.97% (83 runs sampled)
+ HIREDIS BUF: * big nested array x 255 ops/sec ±2.28% (77 runs sampled)
+ JS PARSER: * big nested array x 242 ops/sec ±1.10% (85 runs sampled)
+ JS PARSER BUF: * big nested array x 375 ops/sec ±1.21% (88 runs sampled)
+
+ HIREDIS: - error x 78,821 ops/sec ±0.80% (93 runs sampled)
+ JS PARSER: - error x 143,382 ops/sec ±0.75% (92 runs sampled)
+
+ Platform info:
+ Ubuntu 16.10
+ Node.js 7.4.0
+ Intel(R) Core(TM) i7-5600U CPU
+
+## License
+
+[MIT](./LICENSE)
diff --git a/node_modules/connect-redis/node_modules/redis-parser/changelog.md b/node_modules/connect-redis/node_modules/redis-parser/changelog.md
new file mode 100644
index 0000000..5cd9470
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis-parser/changelog.md
@@ -0,0 +1,138 @@
+## v.2.6.0 - 03 Apr, 2017
+
+Internals
+
+- Use Buffer.allocUnsafe instead of new Buffer() with modern Node.js versions
+
+## v.2.5.0 - 11 Mar, 2017
+
+Features
+
+- Added a `ParserError` class to differentiate them to ReplyErrors. The class is also exported
+
+Bugfixes
+
+- All errors now show their error message again next to the error name in the stack trace
+- ParserErrors now show the offset and buffer attributes while being logged
+
+## v.2.4.1 - 05 Feb, 2017
+
+Bugfixes
+
+- Fixed minimal memory consumption overhead for chunked buffers
+
+## v.2.4.0 - 25 Jan, 2017
+
+Features
+
+- Added `reset` function to reset the parser to it's initial values
+- Added `setReturnBuffers` function to reset the returnBuffers option (Only for the JSParser)
+- Added `setStringNumbers` function to reset the stringNumbers option (Only for the JSParser)
+- All Errors are now of sub classes of the new `RedisError` class. It is also exported.
+- Improved bulk string chunked data handling performance
+
+Bugfixes
+
+- Parsing time for big nested arrays is now linear
+
+## v.2.3.0 - 25 Nov, 2016
+
+Features
+
+- Parsing time for big arrays (e.g. 4mb+) is now linear and works well for arbitrary array sizes
+
+This case is a magnitude faster than before
+
+ OLD STR: * big array x 1.09 ops/sec ±2.15% (7 runs sampled)
+ OLD BUF: * big array x 1.23 ops/sec ±2.67% (8 runs sampled)
+
+ NEW STR: * big array x 273 ops/sec ±2.09% (85 runs sampled)
+ NEW BUF: * big array x 259 ops/sec ±1.32% (85 runs sampled)
+ (~10mb array with 1000 entries)
+
+## v.2.2.0 - 18 Nov, 2016
+
+Features
+
+- Improve `stringNumbers` parsing performance by up to 100%
+
+Bugfixes
+
+- Do not unref the interval anymore due to issues with NodeJS
+
+## v.2.1.1 - 31 Oct, 2016
+
+Bugfixes
+
+- Remove erroneously added const to support Node.js 0.10
+
+## v.2.1.0 - 30 Oct, 2016
+
+Features
+
+- Improve parser errors by adding more detailed information to them
+- Accept manipulated Object.prototypes
+- Unref the interval if used
+
+## v.2.0.4 - 21 Jul, 2016
+
+Bugfixes
+
+- Fixed multi byte characters getting corrupted
+
+## v.2.0.3 - 17 Jun, 2016
+
+Bugfixes
+
+- Fixed parser not working with huge buffers (e.g. 300 MB)
+
+## v.2.0.2 - 08 Jun, 2016
+
+Bugfixes
+
+- Fixed parser with returnBuffers option returning corrupted data
+
+## v.2.0.1 - 04 Jun, 2016
+
+Bugfixes
+
+- Fixed multiple parsers working concurrently resulting in faulty data in some cases
+
+## v.2.0.0 - 29 May, 2016
+
+The javascript parser got completely rewritten by [Michael Diarmid](https://github.com/Salakar) and [Ruben Bridgewater](https://github.com/BridgeAR) and is now a lot faster than the hiredis parser.
+Therefore the hiredis parser was deprecated and should only be used for testing purposes and benchmarking comparison.
+
+All Errors returned by the parser are from now on of class ReplyError
+
+Features
+
+- Improved performance by up to 15x as fast as before
+- Improved options validation
+- Added ReplyError Class
+- Added parser benchmark
+- Switched default parser from hiredis to JS, no matter if hiredis is installed or not
+
+Removed
+
+- Deprecated hiredis support
+
+## v.1.3.0 - 27 Mar, 2016
+
+Features
+
+- Added `auto` as parser name option to check what parser is available
+- Non existing requested parsers falls back into auto mode instead of always choosing the JS parser
+
+## v.1.2.0 - 27 Mar, 2016
+
+Features
+
+- Added `stringNumbers` option to make sure all numbers are returned as string instead of a js number for precision
+- The parser is from now on going to print warnings if a parser is explicitly requested that does not exist and gracefully chooses the JS parser
+
+## v.1.1.0 - 26 Jan, 2016
+
+Features
+
+- The parser is from now on going to reset itself on protocol errors
diff --git a/node_modules/connect-redis/node_modules/redis-parser/index.js b/node_modules/connect-redis/node_modules/redis-parser/index.js
new file mode 100644
index 0000000..a0c777d
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis-parser/index.js
@@ -0,0 +1,6 @@
+'use strict'
+
+module.exports = require('./lib/parser')
+module.exports.ReplyError = require('./lib/replyError')
+module.exports.RedisError = require('./lib/redisError')
+module.exports.ParserError = require('./lib/redisError')
diff --git a/node_modules/redis-parser/lib/hiredis.js b/node_modules/connect-redis/node_modules/redis-parser/lib/hiredis.js
old mode 100755
new mode 100644
similarity index 100%
rename from node_modules/redis-parser/lib/hiredis.js
rename to node_modules/connect-redis/node_modules/redis-parser/lib/hiredis.js
diff --git a/node_modules/connect-redis/node_modules/redis-parser/lib/parser.js b/node_modules/connect-redis/node_modules/redis-parser/lib/parser.js
new file mode 100644
index 0000000..4ba6a18
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis-parser/lib/parser.js
@@ -0,0 +1,581 @@
+'use strict'
+
+var StringDecoder = require('string_decoder').StringDecoder
+var decoder = new StringDecoder()
+var ReplyError = require('./replyError')
+var ParserError = require('./parserError')
+var bufferPool = bufferAlloc(32 * 1024)
+var bufferOffset = 0
+var interval = null
+var counter = 0
+var notDecreased = 0
+var isModern = typeof Buffer.allocUnsafe === 'function'
+
+/**
+ * For backwards compatibility
+ * @param len
+ * @returns {Buffer}
+ */
+
+function bufferAlloc (len) {
+ return isModern ? Buffer.allocUnsafe(len) : new Buffer(len)
+}
+
+/**
+ * Used for lengths and numbers only, faster perf on arrays / bulks
+ * @param parser
+ * @returns {*}
+ */
+function parseSimpleNumbers (parser) {
+ var offset = parser.offset
+ var length = parser.buffer.length - 1
+ var number = 0
+ var sign = 1
+
+ if (parser.buffer[offset] === 45) {
+ sign = -1
+ offset++
+ }
+
+ while (offset < length) {
+ var c1 = parser.buffer[offset++]
+ if (c1 === 13) { // \r\n
+ parser.offset = offset + 1
+ return sign * number
+ }
+ number = (number * 10) + (c1 - 48)
+ }
+}
+
+/**
+ * Used for integer numbers in case of the returnNumbers option
+ *
+ * The maximimum possible integer to use is: Math.floor(Number.MAX_SAFE_INTEGER / 10)
+ * Staying in a SMI Math.floor((Math.pow(2, 32) / 10) - 1) is even more efficient though
+ *
+ * @param parser
+ * @returns {*}
+ */
+function parseStringNumbers (parser) {
+ var offset = parser.offset
+ var length = parser.buffer.length - 1
+ var number = 0
+ var res = ''
+
+ if (parser.buffer[offset] === 45) {
+ res += '-'
+ offset++
+ }
+
+ while (offset < length) {
+ var c1 = parser.buffer[offset++]
+ if (c1 === 13) { // \r\n
+ parser.offset = offset + 1
+ if (number !== 0) {
+ res += number
+ }
+ return res
+ } else if (number > 429496728) {
+ res += (number * 10) + (c1 - 48)
+ number = 0
+ } else if (c1 === 48 && number === 0) {
+ res += 0
+ } else {
+ number = (number * 10) + (c1 - 48)
+ }
+ }
+}
+
+/**
+ * Returns a string or buffer of the provided offset start and
+ * end ranges. Checks `optionReturnBuffers`.
+ *
+ * If returnBuffers is active, all return values are returned as buffers besides numbers and errors
+ *
+ * @param parser
+ * @param start
+ * @param end
+ * @returns {*}
+ */
+function convertBufferRange (parser, start, end) {
+ parser.offset = end + 2
+ if (parser.optionReturnBuffers === true) {
+ return parser.buffer.slice(start, end)
+ }
+
+ return parser.buffer.toString('utf-8', start, end)
+}
+
+/**
+ * Parse a '+' redis simple string response but forward the offsets
+ * onto convertBufferRange to generate a string.
+ * @param parser
+ * @returns {*}
+ */
+function parseSimpleString (parser) {
+ var start = parser.offset
+ var offset = start
+ var buffer = parser.buffer
+ var length = buffer.length - 1
+
+ while (offset < length) {
+ if (buffer[offset++] === 13) { // \r\n
+ return convertBufferRange(parser, start, offset - 1)
+ }
+ }
+}
+
+/**
+ * Returns the string length via parseSimpleNumbers
+ * @param parser
+ * @returns {*}
+ */
+function parseLength (parser) {
+ var string = parseSimpleNumbers(parser)
+ if (string !== undefined) {
+ return string
+ }
+}
+
+/**
+ * Parse a ':' redis integer response
+ *
+ * If stringNumbers is activated the parser always returns numbers as string
+ * This is important for big numbers (number > Math.pow(2, 53)) as js numbers
+ * are 64bit floating point numbers with reduced precision
+ *
+ * @param parser
+ * @returns {*}
+ */
+function parseInteger (parser) {
+ if (parser.optionStringNumbers) {
+ return parseStringNumbers(parser)
+ }
+ return parseSimpleNumbers(parser)
+}
+
+/**
+ * Parse a '$' redis bulk string response
+ * @param parser
+ * @returns {*}
+ */
+function parseBulkString (parser) {
+ var length = parseLength(parser)
+ if (length === undefined) {
+ return
+ }
+ if (length === -1) {
+ return null
+ }
+ var offsetEnd = parser.offset + length
+ if (offsetEnd + 2 > parser.buffer.length) {
+ parser.bigStrSize = offsetEnd + 2
+ parser.bigOffset = parser.offset
+ parser.totalChunkSize = parser.buffer.length
+ parser.bufferCache.push(parser.buffer)
+ return
+ }
+
+ return convertBufferRange(parser, parser.offset, offsetEnd)
+}
+
+/**
+ * Parse a '-' redis error response
+ * @param parser
+ * @returns {Error}
+ */
+function parseError (parser) {
+ var string = parseSimpleString(parser)
+ if (string !== undefined) {
+ if (parser.optionReturnBuffers === true) {
+ string = string.toString()
+ }
+ return new ReplyError(string)
+ }
+}
+
+/**
+ * Parsing error handler, resets parser buffer
+ * @param parser
+ * @param error
+ */
+function handleError (parser, error) {
+ parser.buffer = null
+ parser.returnFatalError(error)
+}
+
+/**
+ * Parse a '*' redis array response
+ * @param parser
+ * @returns {*}
+ */
+function parseArray (parser) {
+ var length = parseLength(parser)
+ if (length === undefined) {
+ return
+ }
+ if (length === -1) {
+ return null
+ }
+ var responses = new Array(length)
+ return parseArrayElements(parser, responses, 0)
+}
+
+/**
+ * Push a partly parsed array to the stack
+ *
+ * @param parser
+ * @param elem
+ * @param i
+ * @returns {undefined}
+ */
+function pushArrayCache (parser, elem, pos) {
+ parser.arrayCache.push(elem)
+ parser.arrayPos.push(pos)
+}
+
+/**
+ * Parse chunked redis array response
+ * @param parser
+ * @returns {*}
+ */
+function parseArrayChunks (parser) {
+ var tmp = parser.arrayCache.pop()
+ var pos = parser.arrayPos.pop()
+ if (parser.arrayCache.length) {
+ var res = parseArrayChunks(parser)
+ if (!res) {
+ pushArrayCache(parser, tmp, pos)
+ return
+ }
+ tmp[pos++] = res
+ }
+ return parseArrayElements(parser, tmp, pos)
+}
+
+/**
+ * Parse redis array response elements
+ * @param parser
+ * @param responses
+ * @param i
+ * @returns {*}
+ */
+function parseArrayElements (parser, responses, i) {
+ var bufferLength = parser.buffer.length
+ while (i < responses.length) {
+ var offset = parser.offset
+ if (parser.offset >= bufferLength) {
+ pushArrayCache(parser, responses, i)
+ return
+ }
+ var response = parseType(parser, parser.buffer[parser.offset++])
+ if (response === undefined) {
+ if (!parser.arrayCache.length) {
+ parser.offset = offset
+ }
+ pushArrayCache(parser, responses, i)
+ return
+ }
+ responses[i] = response
+ i++
+ }
+
+ return responses
+}
+
+/**
+ * Called the appropriate parser for the specified type.
+ * @param parser
+ * @param type
+ * @returns {*}
+ */
+function parseType (parser, type) {
+ switch (type) {
+ case 36: // $
+ return parseBulkString(parser)
+ case 58: // :
+ return parseInteger(parser)
+ case 43: // +
+ return parseSimpleString(parser)
+ case 42: // *
+ return parseArray(parser)
+ case 45: // -
+ return parseError(parser)
+ default:
+ return handleError(parser, new ParserError(
+ 'Protocol error, got ' + JSON.stringify(String.fromCharCode(type)) + ' as reply type byte',
+ JSON.stringify(parser.buffer),
+ parser.offset
+ ))
+ }
+}
+
+// All allowed options including their typeof value
+var optionTypes = {
+ returnError: 'function',
+ returnFatalError: 'function',
+ returnReply: 'function',
+ returnBuffers: 'boolean',
+ stringNumbers: 'boolean',
+ name: 'string'
+}
+
+/**
+ * Javascript Redis Parser
+ * @param options
+ * @constructor
+ */
+function JavascriptRedisParser (options) {
+ if (!(this instanceof JavascriptRedisParser)) {
+ return new JavascriptRedisParser(options)
+ }
+ if (!options || !options.returnError || !options.returnReply) {
+ throw new TypeError('Please provide all return functions while initiating the parser')
+ }
+ for (var key in options) {
+ // eslint-disable-next-line valid-typeof
+ if (optionTypes.hasOwnProperty(key) && typeof options[key] !== optionTypes[key]) {
+ throw new TypeError('The options argument contains the property "' + key + '" that is either unknown or of a wrong type')
+ }
+ }
+ if (options.name === 'hiredis') {
+ /* istanbul ignore next: hiredis is only supported for legacy usage */
+ try {
+ var Hiredis = require('./hiredis')
+ console.error(new TypeError('Using hiredis is discouraged. Please use the faster JS parser by removing the name option.').stack.replace('Error', 'Warning'))
+ return new Hiredis(options)
+ } catch (e) {
+ console.error(new TypeError('Hiredis is not installed. Please remove the `name` option. The (faster) JS parser is used instead.').stack.replace('Error', 'Warning'))
+ }
+ }
+ this.optionReturnBuffers = !!options.returnBuffers
+ this.optionStringNumbers = !!options.stringNumbers
+ this.returnError = options.returnError
+ this.returnFatalError = options.returnFatalError || options.returnError
+ this.returnReply = options.returnReply
+ this.name = 'javascript'
+ this.reset()
+}
+
+/**
+ * Reset the parser values to the initial state
+ *
+ * @returns {undefined}
+ */
+JavascriptRedisParser.prototype.reset = function () {
+ this.offset = 0
+ this.buffer = null
+ this.bigStrSize = 0
+ this.bigOffset = 0
+ this.totalChunkSize = 0
+ this.bufferCache = []
+ this.arrayCache = []
+ this.arrayPos = []
+}
+
+/**
+ * Set the returnBuffers option
+ *
+ * @param returnBuffers
+ * @returns {undefined}
+ */
+JavascriptRedisParser.prototype.setReturnBuffers = function (returnBuffers) {
+ if (typeof returnBuffers !== 'boolean') {
+ throw new TypeError('The returnBuffers argument has to be a boolean')
+ }
+ this.optionReturnBuffers = returnBuffers
+}
+
+/**
+ * Set the stringNumbers option
+ *
+ * @param stringNumbers
+ * @returns {undefined}
+ */
+JavascriptRedisParser.prototype.setStringNumbers = function (stringNumbers) {
+ if (typeof stringNumbers !== 'boolean') {
+ throw new TypeError('The stringNumbers argument has to be a boolean')
+ }
+ this.optionStringNumbers = stringNumbers
+}
+
+/**
+ * Decrease the bufferPool size over time
+ * @returns {undefined}
+ */
+function decreaseBufferPool () {
+ if (bufferPool.length > 50 * 1024) {
+ // Balance between increasing and decreasing the bufferPool
+ if (counter === 1 || notDecreased > counter * 2) {
+ // Decrease the bufferPool by 10% by removing the first 10% of the current pool
+ var sliceLength = Math.floor(bufferPool.length / 10)
+ if (bufferOffset <= sliceLength) {
+ bufferOffset = 0
+ } else {
+ bufferOffset -= sliceLength
+ }
+ bufferPool = bufferPool.slice(sliceLength, bufferPool.length)
+ } else {
+ notDecreased++
+ counter--
+ }
+ } else {
+ clearInterval(interval)
+ counter = 0
+ notDecreased = 0
+ interval = null
+ }
+}
+
+/**
+ * Check if the requested size fits in the current bufferPool.
+ * If it does not, reset and increase the bufferPool accordingly.
+ *
+ * @param length
+ * @returns {undefined}
+ */
+function resizeBuffer (length) {
+ if (bufferPool.length < length + bufferOffset) {
+ var multiplier = length > 1024 * 1024 * 75 ? 2 : 3
+ if (bufferOffset > 1024 * 1024 * 111) {
+ bufferOffset = 1024 * 1024 * 50
+ }
+ bufferPool = bufferAlloc(length * multiplier + bufferOffset)
+ bufferOffset = 0
+ counter++
+ if (interval === null) {
+ interval = setInterval(decreaseBufferPool, 50)
+ }
+ }
+}
+
+/**
+ * Concat a bulk string containing multiple chunks
+ *
+ * Notes:
+ * 1) The first chunk might contain the whole bulk string including the \r
+ * 2) We are only safe to fully add up elements that are neither the first nor any of the last two elements
+ *
+ * @param parser
+ * @returns {String}
+ */
+function concatBulkString (parser) {
+ var list = parser.bufferCache
+ var chunks = list.length
+ var offset = parser.bigStrSize - parser.totalChunkSize
+ parser.offset = offset
+ if (offset <= 2) {
+ if (chunks === 2) {
+ return list[0].toString('utf8', parser.bigOffset, list[0].length + offset - 2)
+ }
+ chunks--
+ offset = list[list.length - 2].length + offset
+ }
+ var res = decoder.write(list[0].slice(parser.bigOffset))
+ for (var i = 1; i < chunks - 1; i++) {
+ res += decoder.write(list[i])
+ }
+ res += decoder.end(list[i].slice(0, offset - 2))
+ return res
+}
+
+/**
+ * Concat the collected chunks from parser.bufferCache.
+ *
+ * Increases the bufferPool size beforehand if necessary.
+ *
+ * @param parser
+ * @returns {Buffer}
+ */
+function concatBulkBuffer (parser) {
+ var list = parser.bufferCache
+ var chunks = list.length
+ var length = parser.bigStrSize - parser.bigOffset - 2
+ var offset = parser.bigStrSize - parser.totalChunkSize
+ parser.offset = offset
+ if (offset <= 2) {
+ if (chunks === 2) {
+ return list[0].slice(parser.bigOffset, list[0].length + offset - 2)
+ }
+ chunks--
+ offset = list[list.length - 2].length + offset
+ }
+ resizeBuffer(length)
+ var start = bufferOffset
+ list[0].copy(bufferPool, start, parser.bigOffset, list[0].length)
+ bufferOffset += list[0].length - parser.bigOffset
+ for (var i = 1; i < chunks - 1; i++) {
+ list[i].copy(bufferPool, bufferOffset)
+ bufferOffset += list[i].length
+ }
+ list[i].copy(bufferPool, bufferOffset, 0, offset - 2)
+ bufferOffset += offset - 2
+ return bufferPool.slice(start, bufferOffset)
+}
+
+/**
+ * Parse the redis buffer
+ * @param buffer
+ * @returns {undefined}
+ */
+JavascriptRedisParser.prototype.execute = function execute (buffer) {
+ if (this.buffer === null) {
+ this.buffer = buffer
+ this.offset = 0
+ } else if (this.bigStrSize === 0) {
+ var oldLength = this.buffer.length
+ var remainingLength = oldLength - this.offset
+ var newBuffer = bufferAlloc(remainingLength + buffer.length)
+ this.buffer.copy(newBuffer, 0, this.offset, oldLength)
+ buffer.copy(newBuffer, remainingLength, 0, buffer.length)
+ this.buffer = newBuffer
+ this.offset = 0
+ if (this.arrayCache.length) {
+ var arr = parseArrayChunks(this)
+ if (!arr) {
+ return
+ }
+ this.returnReply(arr)
+ }
+ } else if (this.totalChunkSize + buffer.length >= this.bigStrSize) {
+ this.bufferCache.push(buffer)
+ var tmp = this.optionReturnBuffers ? concatBulkBuffer(this) : concatBulkString(this)
+ this.bigStrSize = 0
+ this.bufferCache = []
+ this.buffer = buffer
+ if (this.arrayCache.length) {
+ this.arrayCache[0][this.arrayPos[0]++] = tmp
+ tmp = parseArrayChunks(this)
+ if (!tmp) {
+ return
+ }
+ }
+ this.returnReply(tmp)
+ } else {
+ this.bufferCache.push(buffer)
+ this.totalChunkSize += buffer.length
+ return
+ }
+
+ while (this.offset < this.buffer.length) {
+ var offset = this.offset
+ var type = this.buffer[this.offset++]
+ var response = parseType(this, type)
+ if (response === undefined) {
+ if (!this.arrayCache.length) {
+ this.offset = offset
+ }
+ return
+ }
+
+ if (type === 45) {
+ this.returnError(response)
+ } else {
+ this.returnReply(response)
+ }
+ }
+
+ this.buffer = null
+}
+
+module.exports = JavascriptRedisParser
diff --git a/node_modules/redis-parser/lib/parserError.js b/node_modules/connect-redis/node_modules/redis-parser/lib/parserError.js
old mode 100755
new mode 100644
similarity index 100%
rename from node_modules/redis-parser/lib/parserError.js
rename to node_modules/connect-redis/node_modules/redis-parser/lib/parserError.js
diff --git a/node_modules/redis-parser/lib/redisError.js b/node_modules/connect-redis/node_modules/redis-parser/lib/redisError.js
old mode 100755
new mode 100644
similarity index 100%
rename from node_modules/redis-parser/lib/redisError.js
rename to node_modules/connect-redis/node_modules/redis-parser/lib/redisError.js
diff --git a/node_modules/redis-parser/lib/replyError.js b/node_modules/connect-redis/node_modules/redis-parser/lib/replyError.js
old mode 100755
new mode 100644
similarity index 100%
rename from node_modules/redis-parser/lib/replyError.js
rename to node_modules/connect-redis/node_modules/redis-parser/lib/replyError.js
diff --git a/node_modules/connect-redis/node_modules/redis-parser/package.json b/node_modules/connect-redis/node_modules/redis-parser/package.json
new file mode 100644
index 0000000..0412019
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis-parser/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "redis-parser",
+ "version": "2.6.0",
+ "description": "Javascript Redis protocol (RESP) parser",
+ "main": "index.js",
+ "scripts": {
+ "test": "npm run coverage",
+ "benchmark": "node ./benchmark",
+ "lint": "standard --fix",
+ "posttest": "npm run lint && npm run coverage:check",
+ "coverage": "node ./node_modules/istanbul/lib/cli.js cover --preserve-comments ./node_modules/mocha/bin/_mocha -- -R spec",
+ "coverage:check": "node ./node_modules/istanbul/lib/cli.js check-coverage --branch 100 --statement 100"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/NodeRedis/node-redis-parser.git"
+ },
+ "keywords": [
+ "redis",
+ "protocol",
+ "parser",
+ "database",
+ "javascript",
+ "node",
+ "nodejs",
+ "resp",
+ "hiredis"
+ ],
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "devDependencies": {
+ "benchmark": "^2.1.0",
+ "codeclimate-test-reporter": "^0.4.0",
+ "intercept-stdout": "^0.1.2",
+ "istanbul": "^0.4.0",
+ "standard": "^9.0.0",
+ "mocha": "^3.1.2",
+ "hiredis": "^0.5.0"
+ },
+ "author": "Ruben Bridgewater",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/NodeRedis/node-redis-parser/issues"
+ },
+ "homepage": "https://github.com/NodeRedis/node-redis-parser#readme",
+ "directories": {
+ "test": "test",
+ "lib": "lib"
+ }
+}
diff --git a/node_modules/redis/.eslintignore b/node_modules/connect-redis/node_modules/redis/.eslintignore
old mode 100755
new mode 100644
similarity index 100%
rename from node_modules/redis/.eslintignore
rename to node_modules/connect-redis/node_modules/redis/.eslintignore
diff --git a/node_modules/redis/.eslintrc b/node_modules/connect-redis/node_modules/redis/.eslintrc
old mode 100755
new mode 100644
similarity index 100%
rename from node_modules/redis/.eslintrc
rename to node_modules/connect-redis/node_modules/redis/.eslintrc
diff --git a/node_modules/redis/.github/ISSUE_TEMPLATE.md b/node_modules/connect-redis/node_modules/redis/.github/ISSUE_TEMPLATE.md
old mode 100755
new mode 100644
similarity index 100%
rename from node_modules/redis/.github/ISSUE_TEMPLATE.md
rename to node_modules/connect-redis/node_modules/redis/.github/ISSUE_TEMPLATE.md
diff --git a/node_modules/redis/.github/PULL_REQUEST_TEMPLATE.md b/node_modules/connect-redis/node_modules/redis/.github/PULL_REQUEST_TEMPLATE.md
old mode 100755
new mode 100644
similarity index 100%
rename from node_modules/redis/.github/PULL_REQUEST_TEMPLATE.md
rename to node_modules/connect-redis/node_modules/redis/.github/PULL_REQUEST_TEMPLATE.md
diff --git a/node_modules/redis/.npmignore b/node_modules/connect-redis/node_modules/redis/.npmignore
old mode 100755
new mode 100644
similarity index 100%
rename from node_modules/redis/.npmignore
rename to node_modules/connect-redis/node_modules/redis/.npmignore
diff --git a/node_modules/connect-redis/node_modules/redis/LICENSE b/node_modules/connect-redis/node_modules/redis/LICENSE
new file mode 100644
index 0000000..710407f
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/LICENSE
@@ -0,0 +1,24 @@
+LICENSE - "MIT License"
+
+Copyright (c) 2016 by NodeRedis
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/node_modules/connect-redis/node_modules/redis/README.md b/node_modules/connect-redis/node_modules/redis/README.md
new file mode 100644
index 0000000..205503b
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/README.md
@@ -0,0 +1,965 @@
+redis - a node.js redis client
+===========================
+
+[![Build Status](https://travis-ci.org/NodeRedis/node_redis.svg?branch=master)](https://travis-ci.org/NodeRedis/node_redis)
+[![Coverage Status](https://coveralls.io/repos/NodeRedis/node_redis/badge.svg?branch=)](https://coveralls.io/r/NodeRedis/node_redis?branch=)
+[![Windows Tests](https://img.shields.io/appveyor/ci/BridgeAR/node-redis/master.svg?label=Windows%20Tests)](https://ci.appveyor.com/project/BridgeAR/node-redis/branch/master)
+[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/NodeRedis/node_redis?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+
+This is a complete and feature rich Redis client for node.js. __It supports all
+Redis commands__ and focuses on high performance.
+
+Install with:
+
+ npm install redis
+
+## Usage Example
+
+```js
+var redis = require("redis"),
+ client = redis.createClient();
+
+// if you'd like to select database 3, instead of 0 (default), call
+// client.select(3, function() { /* ... */ });
+
+client.on("error", function (err) {
+ console.log("Error " + err);
+});
+
+client.set("string key", "string val", redis.print);
+client.hset("hash key", "hashtest 1", "some value", redis.print);
+client.hset(["hash key", "hashtest 2", "some other value"], redis.print);
+client.hkeys("hash key", function (err, replies) {
+ console.log(replies.length + " replies:");
+ replies.forEach(function (reply, i) {
+ console.log(" " + i + ": " + reply);
+ });
+ client.quit();
+});
+```
+
+This will display:
+
+ mjr:~/work/node_redis (master)$ node example.js
+ Reply: OK
+ Reply: 0
+ Reply: 0
+ 2 replies:
+ 0: hashtest 1
+ 1: hashtest 2
+ mjr:~/work/node_redis (master)$
+
+Note that the API is entirely asynchronous. To get data back from the server,
+you'll need to use a callback. From v.2.6 on the API supports camelCase and
+snake_case and all options / variables / events etc. can be used either way. It
+is recommended to use camelCase as this is the default for the Node.js
+landscape.
+
+### Promises
+
+You can also use node_redis with promises by promisifying node_redis with
+[bluebird](https://github.com/petkaantonov/bluebird) as in:
+
+```js
+var redis = require('redis');
+bluebird.promisifyAll(redis.RedisClient.prototype);
+bluebird.promisifyAll(redis.Multi.prototype);
+```
+
+It'll add a *Async* to all node_redis functions (e.g. return client.getAsync().then())
+
+```js
+// We expect a value 'foo': 'bar' to be present
+// So instead of writing client.get('foo', cb); you have to write:
+return client.getAsync('foo').then(function(res) {
+ console.log(res); // => 'bar'
+});
+
+// Using multi with promises looks like:
+
+return client.multi().get('foo').execAsync().then(function(res) {
+ console.log(res); // => 'bar'
+});
+```
+
+### Sending Commands
+
+Each Redis command is exposed as a function on the `client` object.
+All functions take either an `args` Array plus optional `callback` Function or
+a variable number of individual arguments followed by an optional callback.
+Examples:
+
+```js
+client.hmset(["key", "test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {});
+// Works the same as
+client.hmset("key", ["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {});
+// Or
+client.hmset("key", "test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {});
+```
+
+Note that in either form the `callback` is optional:
+
+```js
+client.set("some key", "some val");
+client.set(["some other key", "some val"]);
+```
+
+If the key is missing, reply will be null. Only if the [Redis Command
+Reference](http://redis.io/commands) states something else it will not be null.
+
+```js
+client.get("missingkey", function(err, reply) {
+ // reply is null when the key is missing
+ console.log(reply);
+});
+```
+
+For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands)
+
+Minimal parsing is done on the replies. Commands that return a integer return
+JavaScript Numbers, arrays return JavaScript Array. `HGETALL` returns an Object
+keyed by the hash keys. All strings will either be returned as string or as
+buffer depending on your setting. Please be aware that sending null, undefined
+and Boolean values will result in the value coerced to a string!
+
+# Redis Commands
+
+This library is a 1 to 1 mapping to [Redis commands](https://redis.io/commands).
+It is not a cache library so please refer to Redis commands page for full usage
+details.
+
+Example setting key to auto expire using [SET command](https://redis.io/commands/set)
+
+```js
+// this key will expire after 10 seconds
+client.set('key', 'value!', 'EX', 10);
+```
+
+# API
+
+## Connection and other Events
+
+`client` will emit some events about the state of the connection to the Redis server.
+
+### "ready"
+
+`client` will emit `ready` once a connection is established. Commands issued
+before the `ready` event are queued, then replayed just before this event is
+emitted.
+
+### "connect"
+
+`client` will emit `connect` as soon as the stream is connected to the server.
+
+### "reconnecting"
+
+`client` will emit `reconnecting` when trying to reconnect to the Redis server
+after losing the connection. Listeners are passed an object containing `delay`
+(in ms) and `attempt` (the attempt #) attributes.
+
+### "error"
+
+`client` will emit `error` when encountering an error connecting to the Redis
+server or when any other in node_redis occurs. If you use a command without
+callback and encounter a ReplyError it is going to be emitted to the error
+listener.
+
+So please attach the error listener to node_redis.
+
+### "end"
+
+`client` will emit `end` when an established Redis server connection has closed.
+
+### "drain" (deprecated)
+
+`client` will emit `drain` when the TCP connection to the Redis server has been
+buffering, but is now writable. This event can be used to stream commands in to
+Redis and adapt to backpressure.
+
+If the stream is buffering `client.should_buffer` is set to true. Otherwise the
+variable is always set to false. That way you can decide when to reduce your
+send rate and resume sending commands when you get `drain`.
+
+You can also check the return value of each command as it will also return the
+backpressure indicator (deprecated). If false is returned the stream had to
+buffer.
+
+### "warning"
+
+`client` will emit `warning` when password was set but none is needed and if a
+deprecated option / function / similar is used.
+
+### "idle" (deprecated)
+
+`client` will emit `idle` when there are no outstanding commands that are
+awaiting a response.
+
+## redis.createClient()
+If you have `redis-server` running on the same machine as node, then the
+defaults for port and host are probably fine and you don't need to supply any
+arguments. `createClient()` returns a `RedisClient` object. Otherwise,
+`createClient()` accepts these arguments:
+
+* `redis.createClient([options])`
+* `redis.createClient(unix_socket[, options])`
+* `redis.createClient(redis_url[, options])`
+* `redis.createClient(port[, host][, options])`
+
+__Tip:__ If the Redis server runs on the same machine as the client consider
+using unix sockets if possible to increase throughput.
+
+#### `options` object properties
+| Property | Default | Description |
+|-----------|-----------|-------------|
+| host | 127.0.0.1 | IP address of the Redis server |
+| port | 6379 | Port of the Redis server |
+| path | null | The UNIX socket string of the Redis server |
+| url | null | The URL of the Redis server. Format: `[redis:]//[[user][:password@]][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]` (More info avaliable at [IANA](http://www.iana.org/assignments/uri-schemes/prov/redis)). |
+| parser | javascript | __Deprecated__ Use either the built-in JS parser [`javascript`]() or the native [`hiredis`]() parser. __Note__ `node_redis` < 2.6 uses hiredis as default if installed. This changed in v.2.6.0. |
+| string_numbers | null | Set to `true`, `node_redis` will return Redis number values as Strings instead of javascript Numbers. Useful if you need to handle big numbers (above `Number.MAX_SAFE_INTEGER === 2^53`). Hiredis is incapable of this behavior, so setting this option to `true` will result in the built-in javascript parser being used no matter the value of the `parser` option. |
+| return_buffers | false | If set to `true`, then all replies will be sent to callbacks as Buffers instead of Strings. |
+| detect_buffers | false | If set to `true`, then replies will be sent to callbacks as Buffers. This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to every command on a client. __Note__: This doesn't work properly with the pubsub mode. A subscriber has to either always return Strings or Buffers. |
+| socket_keepalive | true | If set to `true`, the keep-alive functionality is enabled on the underlying socket. |
+| no_ready_check | false | When a connection is established to the Redis server, the server might still be loading the database from disk. While loading, the server will not respond to any commands. To work around this, `node_redis` has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. Setting `no_ready_check` to `true` will inhibit this check. |
+| enable_offline_queue | true | By default, if there is no active connection to the Redis server, commands are added to a queue and are executed once the connection has been established. Setting `enable_offline_queue` to `false` will disable this feature and the callback will be executed immediately with an error, or an error will be emitted if no callback is specified. |
+| retry_max_delay | null | __Deprecated__ _Please use `retry_strategy` instead._ By default, every time the client tries to connect and fails, the reconnection delay almost doubles. This delay normally grows infinitely, but setting `retry_max_delay` limits it to the maximum value provided in milliseconds. |
+| connect_timeout | 3600000 | __Deprecated__ _Please use `retry_strategy` instead._ Setting `connect_timeout` limits the total time for the client to connect and reconnect. The value is provided in milliseconds and is counted from the moment a new client is created or from the time the connection is lost. The last retry is going to happen exactly at the timeout time. Default is to try connecting until the default system socket timeout has been exceeded and to try reconnecting until 1h has elapsed. |
+| max_attempts | 0 | __Deprecated__ _Please use `retry_strategy` instead._ By default, a client will try reconnecting until connected. Setting `max_attempts` limits total amount of connection attempts. Setting this to 1 will prevent any reconnect attempt. |
+| retry_unfulfilled_commands | false | If set to `true`, all commands that were unfulfilled while the connection is lost will be retried after the connection has been reestablished. Use this with caution if you use state altering commands (e.g. `incr`). This is especially useful if you use blocking commands. |
+| password | null | If set, client will run Redis auth command on connect. Alias `auth_pass` __Note__ `node_redis` < 2.5 must use `auth_pass` |
+| db | null | If set, client will run Redis `select` command on connect. |
+| family | IPv4 | You can force using IPv6 if you set the family to 'IPv6'. See Node.js [net](https://nodejs.org/api/net.html) or [dns](https://nodejs.org/api/dns.html) modules on how to use the family type. |
+| disable_resubscribing | false | If set to `true`, a client won't resubscribe after disconnecting. |
+| rename_commands | null | Passing an object with renamed commands to use instead of the original functions. For example, if you renamed the command KEYS to "DO-NOT-USE" then the rename_commands object would be: `{ KEYS : "DO-NOT-USE" }` . See the [Redis security topics](http://redis.io/topics/security) for more info. |
+| tls | null | An object containing options to pass to [tls.connect](http://nodejs.org/api/tls.html#tls_tls_connect_port_host_options_callback) to set up a TLS connection to Redis (if, for example, it is set up to be accessible via a tunnel). |
+| prefix | null | A string used to prefix all used keys (e.g. `namespace:test`). Please be aware that the `keys` command will not be prefixed. The `keys` command has a "pattern" as argument and no key and it would be impossible to determine the existing keys in Redis if this would be prefixed. |
+| retry_strategy | function | A function that receives an options object as parameter including the retry `attempt`, the `total_retry_time` indicating how much time passed since the last time connected, the `error` why the connection was lost and the number of `times_connected` in total. If you return a number from this function, the retry will happen exactly after that time in milliseconds. If you return a non-number, no further retry will happen and all offline commands are flushed with errors. Return an error to return that specific error to all offline commands. Example below. |
+
+```js
+var redis = require("redis");
+var client = redis.createClient({detect_buffers: true});
+
+client.set("foo_rand000000000000", "OK");
+
+// This will return a JavaScript String
+client.get("foo_rand000000000000", function (err, reply) {
+ console.log(reply.toString()); // Will print `OK`
+});
+
+// This will return a Buffer since original key is specified as a Buffer
+client.get(new Buffer("foo_rand000000000000"), function (err, reply) {
+ console.log(reply.toString()); // Will print ``
+});
+client.quit();
+```
+
+retry_strategy example
+
+```js
+var client = redis.createClient({
+ retry_strategy: function (options) {
+ if (options.error && options.error.code === 'ECONNREFUSED') {
+ // End reconnecting on a specific error and flush all commands with
+ // a individual error
+ return new Error('The server refused the connection');
+ }
+ if (options.total_retry_time > 1000 * 60 * 60) {
+ // End reconnecting after a specific timeout and flush all commands
+ // with a individual error
+ return new Error('Retry time exhausted');
+ }
+ if (options.attempt > 10) {
+ // End reconnecting with built in error
+ return undefined;
+ }
+ // reconnect after
+ return Math.min(options.attempt * 100, 3000);
+ }
+});
+```
+
+## client.auth(password[, callback])
+
+When connecting to a Redis server that requires authentication, the `AUTH`
+command must be sent as the first command after connecting. This can be tricky
+to coordinate with reconnections, the ready check, etc. To make this easier,
+`client.auth()` stashes `password` and will send it after each connection,
+including reconnections. `callback` is invoked only once, after the response to
+the very first `AUTH` command sent.
+NOTE: Your call to `client.auth()` should not be inside the ready handler. If
+you are doing this wrong, `client` will emit an error that looks
+something like this `Error: Ready check failed: ERR operation not permitted`.
+
+## backpressure
+
+### stream
+
+The client exposed the used [stream](https://nodejs.org/api/stream.html) in
+`client.stream` and if the stream or client had to
+[buffer](https://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback)
+the command in `client.should_buffer`. In combination this can be used to
+implement backpressure by checking the buffer state before sending a command and
+listening to the stream
+[drain](https://nodejs.org/api/stream.html#stream_event_drain) event.
+
+## client.quit()
+
+This sends the quit command to the redis server and ends cleanly right after all
+running commands were properly handled. If this is called while reconnecting
+(and therefore no connection to the redis server exists) it is going to end the
+connection right away instead of resulting in further reconnections! All offline
+commands are going to be flushed with an error in that case.
+
+## client.end(flush)
+
+Forcibly close the connection to the Redis server. Note that this does not wait
+until all replies have been parsed. If you want to exit cleanly, call
+`client.quit()` as mentioned above.
+
+You should set flush to true, if you are not absolutely sure you do not care
+about any other commands. If you set flush to false all still running commands
+will silently fail.
+
+This example closes the connection to the Redis server before the replies have
+been read. You probably don't want to do this:
+
+```js
+var redis = require("redis"),
+ client = redis.createClient();
+
+client.set("foo_rand000000000000", "some fantastic value", function (err, reply) {
+ // This will either result in an error (flush parameter is set to true)
+ // or will silently fail and this callback will not be called at all (flush set to false)
+ console.log(err);
+});
+client.end(true); // No further commands will be processed
+client.get("foo_rand000000000000", function (err, reply) {
+ console.log(err); // => 'The connection has already been closed.'
+});
+```
+
+`client.end()` without the flush parameter set to true should NOT be used in production!
+
+## Error handling (>= v.2.6)
+
+Currently the following error subclasses exist:
+
+* `RedisError`: _All errors_ returned by the client
+* `ReplyError` subclass of `RedisError`: All errors returned by __Redis__ itself
+* `AbortError` subclass of `RedisError`: All commands that could not finish due
+ to what ever reason
+* `ParserError` subclass of `RedisError`: Returned in case of a parser error
+ (this should not happen)
+* `AggregateError` subclass of `AbortError`: Emitted in case multiple unresolved
+ commands without callback got rejected in debug_mode instead of lots of
+ `AbortError`s.
+
+All error classes are exported by the module.
+
+Example:
+```js
+var redis = require('./');
+var assert = require('assert');
+var client = redis.createClient();
+
+client.on('error', function (err) {
+ assert(err instanceof Error);
+ assert(err instanceof redis.AbortError);
+ assert(err instanceof redis.AggregateError);
+ // The set and get get aggregated in here
+ assert.strictEqual(err.errors.length, 2);
+ assert.strictEqual(err.code, 'NR_CLOSED');
+});
+client.set('foo', 123, 'bar', function (err, res) { // Too many arguments
+ assert(err instanceof redis.ReplyError); // => true
+ assert.strictEqual(err.command, 'SET');
+ assert.deepStrictEqual(err.args, ['foo', 123, 'bar']);
+
+ redis.debug_mode = true;
+ client.set('foo', 'bar');
+ client.get('foo');
+ process.nextTick(function () {
+ // Force closing the connection while the command did not yet return
+ client.end(true);
+ redis.debug_mode = false;
+ });
+});
+
+```
+
+Every `ReplyError` contains the `command` name in all-caps and the arguments (`args`).
+
+If node_redis emits a library error because of another error, the triggering
+error is added to the returned error as `origin` attribute.
+
+___Error codes___
+
+node_redis returns a `NR_CLOSED` error code if the clients connection dropped.
+If a command unresolved command got rejected a `UNCERTAIN_STATE` code is
+returned. A `CONNECTION_BROKEN` error code is used in case node_redis gives up
+to reconnect.
+
+## client.unref()
+
+Call `unref()` on the underlying socket connection to the Redis server, allowing
+the program to exit once no more commands are pending.
+
+This is an **experimental** feature, and only supports a subset of the Redis
+protocol. Any commands where client state is saved on the Redis server, e.g.
+`*SUBSCRIBE` or the blocking `BL*` commands will *NOT* work with `.unref()`.
+
+```js
+var redis = require("redis")
+var client = redis.createClient()
+
+/*
+ Calling unref() will allow this program to exit immediately after the get
+ command finishes. Otherwise the client would hang as long as the
+ client-server connection is alive.
+*/
+client.unref()
+client.get("foo", function (err, value){
+ if (err) throw(err)
+ console.log(value)
+})
+```
+
+## Friendlier hash commands
+
+Most Redis commands take a single String or an Array of Strings as arguments,
+and replies are sent back as a single String or an Array of Strings. When
+dealing with hash values, there are a couple of useful exceptions to this.
+
+### client.hgetall(hash, callback)
+
+The reply from an HGETALL command will be converted into a JavaScript Object by
+`node_redis`. That way you can interact with the responses using JavaScript
+syntax.
+
+Example:
+
+```js
+client.hmset("hosts", "mjr", "1", "another", "23", "home", "1234");
+client.hgetall("hosts", function (err, obj) {
+ console.dir(obj);
+});
+```
+
+Output:
+
+```js
+{ mjr: '1', another: '23', home: '1234' }
+```
+
+### client.hmset(hash, obj[, callback])
+
+Multiple values in a hash can be set by supplying an object:
+
+```js
+client.HMSET(key2, {
+ "0123456789": "abcdefghij", // NOTE: key and value will be coerced to strings
+ "some manner of key": "a type of value"
+});
+```
+
+The properties and values of this Object will be set as keys and values in the
+Redis hash.
+
+### client.hmset(hash, key1, val1, ... keyn, valn, [callback])
+
+Multiple values may also be set by supplying a list:
+
+```js
+client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value");
+```
+
+## Publish / Subscribe
+
+Example of the publish / subscribe API. This program opens two
+client connections, subscribes to a channel on one of them, and publishes to that
+channel on the other:
+
+```js
+var redis = require("redis");
+var sub = redis.createClient(), pub = redis.createClient();
+var msg_count = 0;
+
+sub.on("subscribe", function (channel, count) {
+ pub.publish("a nice channel", "I am sending a message.");
+ pub.publish("a nice channel", "I am sending a second message.");
+ pub.publish("a nice channel", "I am sending my last message.");
+});
+
+sub.on("message", function (channel, message) {
+ console.log("sub channel " + channel + ": " + message);
+ msg_count += 1;
+ if (msg_count === 3) {
+ sub.unsubscribe();
+ sub.quit();
+ pub.quit();
+ }
+});
+
+sub.subscribe("a nice channel");
+```
+
+When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into
+a "subscriber" mode. At that point, only commands that modify the subscription
+set are valid and quit (and depending on the redis version ping as well). When
+the subscription set is empty, the connection is put back into regular mode.
+
+If you need to send regular commands to Redis while in subscriber mode, just
+open another connection with a new client (hint: use `client.duplicate()`).
+
+## Subscriber Events
+
+If a client has subscriptions active, it may emit these events:
+
+### "message" (channel, message)
+
+Client will emit `message` for every message received that matches an active subscription.
+Listeners are passed the channel name as `channel` and the message as `message`.
+
+### "pmessage" (pattern, channel, message)
+
+Client will emit `pmessage` for every message received that matches an active
+subscription pattern. Listeners are passed the original pattern used with
+`PSUBSCRIBE` as `pattern`, the sending channel name as `channel`, and the
+message as `message`.
+
+### "message_buffer" (channel, message)
+
+This is the same as the `message` event with the exception, that it is always
+going to emit a buffer. If you listen to the `message` event at the same time as
+the `message_buffer`, it is always going to emit a string.
+
+### "pmessage_buffer" (pattern, channel, message)
+
+This is the same as the `pmessage` event with the exception, that it is always
+going to emit a buffer. If you listen to the `pmessage` event at the same time
+as the `pmessage_buffer`, it is always going to emit a string.
+
+### "subscribe" (channel, count)
+
+Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are
+passed the channel name as `channel` and the new count of subscriptions for this
+client as `count`.
+
+### "psubscribe" (pattern, count)
+
+Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners
+are passed the original pattern as `pattern`, and the new count of subscriptions
+for this client as `count`.
+
+### "unsubscribe" (channel, count)
+
+Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners
+are passed the channel name as `channel` and the new count of subscriptions for
+this client as `count`. When `count` is 0, this client has left subscriber mode
+and no more subscriber events will be emitted.
+
+### "punsubscribe" (pattern, count)
+
+Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command.
+Listeners are passed the channel name as `channel` and the new count of
+subscriptions for this client as `count`. When `count` is 0, this client has
+left subscriber mode and no more subscriber events will be emitted.
+
+## client.multi([commands])
+
+`MULTI` commands are queued up until an `EXEC` is issued, and then all commands
+are run atomically by Redis. The interface in `node_redis` is to return an
+individual `Multi` object by calling `client.multi()`. If any command fails to
+queue, all commands are rolled back and none is going to be executed (For
+further information look at
+[transactions](http://redis.io/topics/transactions)).
+
+```js
+var redis = require("./index"),
+ client = redis.createClient(), set_size = 20;
+
+client.sadd("bigset", "a member");
+client.sadd("bigset", "another member");
+
+while (set_size > 0) {
+ client.sadd("bigset", "member " + set_size);
+ set_size -= 1;
+}
+
+// multi chain with an individual callback
+client.multi()
+ .scard("bigset")
+ .smembers("bigset")
+ .keys("*", function (err, replies) {
+ // NOTE: code in this callback is NOT atomic
+ // this only happens after the the .exec call finishes.
+ client.mget(replies, redis.print);
+ })
+ .dbsize()
+ .exec(function (err, replies) {
+ console.log("MULTI got " + replies.length + " replies");
+ replies.forEach(function (reply, index) {
+ console.log("Reply " + index + ": " + reply.toString());
+ });
+ });
+```
+
+### Multi.exec([callback])
+
+`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects
+share all of the same command methods as `client` objects do. Commands are
+queued up inside the `Multi` object until `Multi.exec()` is invoked.
+
+If your code contains an syntax error an EXECABORT error is going to be thrown
+and all commands are going to be aborted. That error contains a `.errors`
+property that contains the concrete errors.
+If all commands were queued successfully and an error is thrown by redis while
+processing the commands that error is going to be returned in the result array!
+No other command is going to be aborted though than the onces failing.
+
+You can either chain together `MULTI` commands as in the above example, or you
+can queue individual commands while still sending regular client command as in
+this example:
+
+```js
+var redis = require("redis"),
+ client = redis.createClient(), multi;
+
+// start a separate multi command queue
+multi = client.multi();
+multi.incr("incr thing", redis.print);
+multi.incr("incr other thing", redis.print);
+
+// runs immediately
+client.mset("incr thing", 100, "incr other thing", 1, redis.print);
+
+// drains multi queue and runs atomically
+multi.exec(function (err, replies) {
+ console.log(replies); // 101, 2
+});
+```
+
+In addition to adding commands to the `MULTI` queue individually, you can also
+pass an array of commands and arguments to the constructor:
+
+```js
+var redis = require("redis"),
+ client = redis.createClient(), multi;
+
+client.multi([
+ ["mget", "multifoo", "multibar", redis.print],
+ ["incr", "multifoo"],
+ ["incr", "multibar"]
+]).exec(function (err, replies) {
+ console.log(replies);
+});
+```
+
+### Multi.exec_atomic([callback])
+
+Identical to Multi.exec but with the difference that executing a single command
+will not use transactions.
+
+## client.batch([commands])
+
+Identical to .multi without transactions. This is recommended if you want to
+execute many commands at once but don't have to rely on transactions.
+
+`BATCH` commands are queued up until an `EXEC` is issued, and then all commands
+are run atomically by Redis. The interface in `node_redis` is to return an
+individual `Batch` object by calling `client.batch()`. The only difference
+between .batch and .multi is that no transaction is going to be used.
+Be aware that the errors are - just like in multi statements - in the result.
+Otherwise both, errors and results could be returned at the same time.
+
+If you fire many commands at once this is going to boost the execution speed
+significantly compared to firing the same commands in a loop without waiting for
+the result! See the benchmarks for further comparison. Please remember that all
+commands are kept in memory until they are fired.
+
+## Monitor mode
+
+Redis supports the `MONITOR` command, which lets you see all commands received
+by the Redis server across all client connections, including from other client
+libraries and other computers.
+
+A `monitor` event is going to be emitted for every command fired from any client
+connected to the server including the monitoring client itself. The callback for
+the `monitor` event takes a timestamp from the Redis server, an array of command
+arguments and the raw monitoring string.
+
+Example:
+
+```js
+var client = require("redis").createClient();
+client.monitor(function (err, res) {
+ console.log("Entering monitoring mode.");
+});
+client.set('foo', 'bar');
+
+client.on("monitor", function (time, args, raw_reply) {
+ console.log(time + ": " + args); // 1458910076.446514:['set', 'foo', 'bar']
+});
+```
+
+# Extras
+
+Some other things you might like to know about.
+
+## client.server_info
+
+After the ready probe completes, the results from the INFO command are saved in
+the `client.server_info` object.
+
+The `versions` key contains an array of the elements of the version string for
+easy comparison.
+
+ > client.server_info.redis_version
+ '2.3.0'
+ > client.server_info.versions
+ [ 2, 3, 0 ]
+
+## redis.print()
+
+A handy callback function for displaying return values when testing. Example:
+
+```js
+var redis = require("redis"),
+ client = redis.createClient();
+
+client.on("connect", function () {
+ client.set("foo_rand000000000000", "some fantastic value", redis.print);
+ client.get("foo_rand000000000000", redis.print);
+});
+```
+
+This will print:
+
+ Reply: OK
+ Reply: some fantastic value
+
+Note that this program will not exit cleanly because the client is still connected.
+
+## Multi-word commands
+
+To execute redis multi-word commands like `SCRIPT LOAD` or `CLIENT LIST` pass
+the second word as first parameter:
+
+ client.script('load', 'return 1');
+ client.multi().script('load', 'return 1').exec(...);
+ client.multi([['script', 'load', 'return 1']]).exec(...);
+
+## client.duplicate([options][, callback])
+
+Duplicate all current options and return a new redisClient instance. All options
+passed to the duplicate function are going to replace the original option. If
+you pass a callback, duplicate is going to wait until the client is ready and
+returns it in the callback. If an error occurs in the meanwhile, that is going
+to return an error instead in the callback.
+
+One example of when to use duplicate() would be to accommodate the connection-
+blocking redis commands BRPOP, BLPOP, and BRPOPLPUSH. If these commands
+are used on the same redisClient instance as non-blocking commands, the
+non-blocking ones may be queued up until after the blocking ones finish.
+
+ var Redis=require('redis');
+ var client = Redis.createClient();
+ var clientBlocking = client.duplicate();
+
+ var get = function() {
+ console.log("get called");
+ client.get("any_key",function() { console.log("get returned"); });
+ setTimeout( get, 1000 );
+ };
+ var brpop = function() {
+ console.log("brpop called");
+ clientBlocking.brpop("nonexistent", 5, function() {
+ console.log("brpop return");
+ setTimeout( brpop, 1000 );
+ });
+ };
+ get();
+ brpop();
+
+Another reason to use duplicate() is when multiple DBs on the same server are
+accessed via the redis SELECT command. Each DB could use its own connection.
+
+## client.send_command(command_name[, [args][, callback]])
+
+All Redis commands have been added to the `client` object. However, if new
+commands are introduced before this library is updated or if you want to add
+individual commands you can use `send_command()` to send arbitrary commands to
+Redis.
+
+All commands are sent as multi-bulk commands. `args` can either be an Array of
+arguments, or omitted / set to undefined.
+
+## client.add_command(command_name)
+
+Calling add_command will add a new command to the prototype. The exact command
+name will be used when calling using this new command. Using arbitrary arguments
+is possible as with any other command.
+
+## client.connected
+
+Boolean tracking the state of the connection to the Redis server.
+
+## client.command_queue_length
+
+The number of commands that have been sent to the Redis server but not yet
+replied to. You can use this to enforce some kind of maximum queue depth for
+commands while connected.
+
+## client.offline_queue_length
+
+The number of commands that have been queued up for a future connection. You can
+use this to enforce some kind of maximum queue depth for pre-connection
+commands.
+
+### Commands with Optional and Keyword arguments
+
+This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset
+count]` in the [redis.io/commands](http://redis.io/commands) documentation.
+
+Example:
+
+```js
+var args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ];
+client.zadd(args, function (err, response) {
+ if (err) throw err;
+ console.log('added '+response+' items.');
+
+ // -Infinity and +Infinity also work
+ var args1 = [ 'myzset', '+inf', '-inf' ];
+ client.zrevrangebyscore(args1, function (err, response) {
+ if (err) throw err;
+ console.log('example1', response);
+ // write your code here
+ });
+
+ var max = 3, min = 1, offset = 1, count = 2;
+ var args2 = [ 'myzset', max, min, 'WITHSCORES', 'LIMIT', offset, count ];
+ client.zrevrangebyscore(args2, function (err, response) {
+ if (err) throw err;
+ console.log('example2', response);
+ // write your code here
+ });
+});
+```
+
+## Performance
+
+Much effort has been spent to make `node_redis` as fast as possible for common
+operations.
+
+```
+Lenovo T450s, i7-5600U and 12gb memory
+clients: 1, NodeJS: 6.2.0, Redis: 3.2.0, parser: javascript, connected by: tcp
+ PING, 1/1 avg/max: 0.02/ 5.26 2501ms total, 46916 ops/sec
+ PING, batch 50/1 avg/max: 0.06/ 4.35 2501ms total, 755178 ops/sec
+ SET 4B str, 1/1 avg/max: 0.02/ 4.75 2501ms total, 40856 ops/sec
+ SET 4B str, batch 50/1 avg/max: 0.11/ 1.51 2501ms total, 432727 ops/sec
+ SET 4B buf, 1/1 avg/max: 0.05/ 2.76 2501ms total, 20659 ops/sec
+ SET 4B buf, batch 50/1 avg/max: 0.25/ 1.76 2501ms total, 194962 ops/sec
+ GET 4B str, 1/1 avg/max: 0.02/ 1.55 2501ms total, 45156 ops/sec
+ GET 4B str, batch 50/1 avg/max: 0.09/ 3.15 2501ms total, 524110 ops/sec
+ GET 4B buf, 1/1 avg/max: 0.02/ 3.07 2501ms total, 44563 ops/sec
+ GET 4B buf, batch 50/1 avg/max: 0.10/ 3.18 2501ms total, 473171 ops/sec
+ SET 4KiB str, 1/1 avg/max: 0.03/ 1.54 2501ms total, 32627 ops/sec
+ SET 4KiB str, batch 50/1 avg/max: 0.34/ 1.89 2501ms total, 146861 ops/sec
+ SET 4KiB buf, 1/1 avg/max: 0.05/ 2.85 2501ms total, 20688 ops/sec
+ SET 4KiB buf, batch 50/1 avg/max: 0.36/ 1.83 2501ms total, 138165 ops/sec
+ GET 4KiB str, 1/1 avg/max: 0.02/ 1.37 2501ms total, 39389 ops/sec
+ GET 4KiB str, batch 50/1 avg/max: 0.24/ 1.81 2501ms total, 208157 ops/sec
+ GET 4KiB buf, 1/1 avg/max: 0.02/ 2.63 2501ms total, 39918 ops/sec
+ GET 4KiB buf, batch 50/1 avg/max: 0.31/ 8.56 2501ms total, 161575 ops/sec
+ INCR, 1/1 avg/max: 0.02/ 4.69 2501ms total, 45685 ops/sec
+ INCR, batch 50/1 avg/max: 0.09/ 3.06 2501ms total, 539964 ops/sec
+ LPUSH, 1/1 avg/max: 0.02/ 3.04 2501ms total, 41253 ops/sec
+ LPUSH, batch 50/1 avg/max: 0.12/ 1.94 2501ms total, 425090 ops/sec
+ LRANGE 10, 1/1 avg/max: 0.02/ 2.28 2501ms total, 39850 ops/sec
+ LRANGE 10, batch 50/1 avg/max: 0.25/ 1.85 2501ms total, 194302 ops/sec
+ LRANGE 100, 1/1 avg/max: 0.05/ 2.93 2501ms total, 21026 ops/sec
+ LRANGE 100, batch 50/1 avg/max: 1.52/ 2.89 2501ms total, 32767 ops/sec
+ SET 4MiB str, 1/1 avg/max: 5.16/ 15.55 2502ms total, 193 ops/sec
+ SET 4MiB str, batch 20/1 avg/max: 89.73/ 99.96 2513ms total, 223 ops/sec
+ SET 4MiB buf, 1/1 avg/max: 2.23/ 8.35 2501ms total, 446 ops/sec
+ SET 4MiB buf, batch 20/1 avg/max: 41.47/ 50.91 2530ms total, 482 ops/sec
+ GET 4MiB str, 1/1 avg/max: 2.79/ 10.91 2502ms total, 358 ops/sec
+ GET 4MiB str, batch 20/1 avg/max: 101.61/118.11 2541ms total, 197 ops/sec
+ GET 4MiB buf, 1/1 avg/max: 2.32/ 14.93 2502ms total, 430 ops/sec
+ GET 4MiB buf, batch 20/1 avg/max: 65.01/ 84.72 2536ms total, 308 ops/sec
+ ```
+
+## Debugging
+
+To get debug output run your `node_redis` application with `NODE_DEBUG=redis`.
+
+This is also going to result in good stack traces opposed to useless ones
+otherwise for any async operation.
+If you only want to have good stack traces but not the debug output run your
+application in development mode instead (`NODE_ENV=development`).
+
+Good stack traces are only activated in development and debug mode as this
+results in a significant performance penalty.
+
+___Comparison___:
+Useless stack trace:
+```
+ReplyError: ERR wrong number of arguments for 'set' command
+ at parseError (/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:158:12)
+ at parseType (/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:219:14)
+```
+Good stack trace:
+```
+ReplyError: ERR wrong number of arguments for 'set' command
+ at new Command (/home/ruben/repos/redis/lib/command.js:9:902)
+ at RedisClient.set (/home/ruben/repos/redis/lib/commands.js:9:3238)
+ at Context. (/home/ruben/repos/redis/test/good_stacks.spec.js:20:20)
+ at callFnAsync (/home/ruben/repos/redis/node_modules/mocha/lib/runnable.js:349:8)
+ at Test.Runnable.run (/home/ruben/repos/redis/node_modules/mocha/lib/runnable.js:301:7)
+ at Runner.runTest (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:422:10)
+ at /home/ruben/repos/redis/node_modules/mocha/lib/runner.js:528:12
+ at next (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:342:14)
+ at /home/ruben/repos/redis/node_modules/mocha/lib/runner.js:352:7
+ at next (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:284:14)
+ at Immediate._onImmediate (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:320:5)
+ at processImmediate [as _immediateCallback] (timers.js:383:17)
+```
+
+## How to Contribute
+- Open a pull request or an issue about what you want to implement / change. We're glad for any help!
+ - Please be aware that we'll only accept fully tested code.
+
+## Contributors
+
+The original author of node_redis is [Matthew Ranney](https://github.com/mranney)
+
+The current lead maintainer is [Ruben Bridgewater](https://github.com/BridgeAR)
+
+Many [others](https://github.com/NodeRedis/node_redis/graphs/contributors)
+contributed to `node_redis` too. Thanks to all of them!
+
+## License
+
+[MIT](LICENSE)
+
+### Consolidation: It's time for celebration
+
+Right now there are two great redis clients around and both have some advantages
+above each other. We speak about ioredis and node_redis. So after talking to
+each other about how we could improve in working together we (that is @luin and
+@BridgeAR) decided to work towards a single library on the long run. But step by
+step.
+
+First of all, we want to split small parts of our libraries into others so that
+we're both able to use the same code. Those libraries are going to be maintained
+under the NodeRedis organization. This is going to reduce the maintenance
+overhead, allows others to use the very same code, if they need it and it's way
+easyer for others to contribute to both libraries.
+
+We're very happy about this step towards working together as we both want to
+give you the best redis experience possible.
+
+If you want to join our cause by help maintaining something, please don't
+hesitate to contact either one of us.
diff --git a/node_modules/connect-redis/node_modules/redis/changelog.md b/node_modules/connect-redis/node_modules/redis/changelog.md
new file mode 100644
index 0000000..d650f9b
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/changelog.md
@@ -0,0 +1,845 @@
+# Changelog
+
+## v.2.8.0 - 31 Jul, 2017
+
+Features
+
+- Accept UPPER_CASE commands in send_command
+- Add arbitrary commands to the prototype by using `Redis.addCommand(name)`
+
+Bugfixes
+
+- Fixed not always copying subscribe unsubscribe arguments
+- Fixed emitting internal errors while reconnecting with auth
+- Fixed crashing with invalid url option
+
+## v.2.7.1 - 14 Mar, 2017
+
+Bugfixes
+
+- Fixed monitor mode not working in combination with IPv6 (2.6.0 regression)
+
+## v.2.7.0 - 11 Mar, 2017
+
+Features
+
+- All returned errors are from now a subclass of `RedisError`.
+
+Bugfixes
+
+- Fixed rename_commands not accepting `null` as value
+- Fixed `AbortError`s and `AggregateError`s not showing the error message in the stack trace
+
+## v.2.6.5 - 15 Jan, 2017
+
+Bugfixes
+
+- Fixed parser not being reset in case the redis connection closed ASAP for overcoming of output buffer limits
+- Fixed parser reset if (p)message_buffer listener is attached
+
+## v.2.6.4 - 12 Jan, 2017
+
+Bugfixes
+
+- Fixed monitor mode not working in combination with IPv6, sockets or lua scripts (2.6.0 regression)
+
+## v.2.6.3 - 31 Oct, 2016
+
+Bugfixes
+
+- Do not change the tls setting to camel_case
+- Fix domain handling in combination with the offline queue (2.5.3 regression)
+
+## v.2.6.2 - 16 Jun, 2016
+
+Bugfixes
+
+- Fixed individual callbacks of a transaction not being called (2.6.0 regression)
+
+## v.2.6.1 - 02 Jun, 2016
+
+Bugfixes
+
+- Fixed invalid function name being exported
+
+## v.2.6.0 - 01 Jun, 2016
+
+In addition to the pre-releases the following changes exist in v.2.6.0:
+
+Features
+
+- Updated [redis-parser](https://github.com/NodeRedis/node-redis-parser) dependency ([changelog](https://github.com/NodeRedis/node-redis-parser/releases/tag/v.2.0.0))
+ - The JS parser is from now on the new default as it is a lot faster than the hiredis parser
+ - This is no BC as there is no changed behavior for the user at all but just a performance improvement. Explicitly requireing the Hiredis parser is still possible.
+- Added name property to all Redis functions (Node.js >= 4.0)
+- Improved stack traces in development and debug mode
+
+Bugfixes
+
+- Reverted support for `__proto__` (v.2.6.0-2) to prevent and breaking change
+
+Deprecations
+
+- The `parser` option is deprecated and should be removed. The built-in Javascript parser is a lot faster than the hiredis parser and has more features
+
+## v.2.6.0-2 - 29 Apr, 2016
+
+Features
+
+- Added support for the new [CLIENT REPLY ON|OFF|SKIP](http://redis.io/commands/client-reply) command (Redis v.3.2)
+- Added support for camelCase
+ - The Node.js landscape default is to use camelCase. node_redis is a bit out of the box here
+ but from now on it is possible to use both, just as you prefer!
+ - If there's any documented variable missing as camelCased, please open a issue for it
+- Improve error handling significantly
+ - Only emit an error if the error has not already been handled in a callback
+ - Improved unspecific error messages e.g. "Connection gone from end / close event"
+ - Added `args` to command errors to improve identification of the error
+ - Added origin to errors if there's e.g. a connection error
+ - Added ReplyError class. All Redis errors are from now on going to be of that class
+ - Added AbortError class. A subclass of AbortError. All unresolved and by node_redis rejected commands are from now on of that class
+ - Added AggregateError class. If a unresolved and by node_redis rejected command has no callback and
+ this applies to more than a single command, the errors for the commands without callback are aggregated
+ to a single error that is emitted in debug_mode in that case.
+- Added `message_buffer` / `pmessage_buffer` events. That event is always going to emit a buffer
+ - Listening to the `message` event at the same time is always going to return the same message as string
+- Added callback option to the duplicate function
+- Added support for `__proto__` and other reserved keywords as hgetall field
+- Updated [redis-commands](https://github.com/NodeRedis/redis-commands) dependency ([changelog](https://github.com/NodeRedis/redis-commands/releases/tag/v.1.2.0))
+
+Bugfixes
+
+- Fixed v.2.5.0 auth command regression (under special circumstances a reconnect would not authenticate properly)
+- Fixed v.2.6.0-0 pub sub mode and quit command regressions:
+ - Entering pub sub mode not working if a earlier called and still running command returned an error
+ - Unsubscribe callback not called if unsubscribing from all channels and resubscribing right away
+ - Quit command resulting in an error in some cases
+- Fixed special handled functions in batch and multi context not working the same as without (e.g. select and info)
+ - Be aware that not all commands work in combination with transactions but they all work with batch
+- Fixed address always set to 127.0.0.1:6379 in case host / port is set in the `tls` options instead of the general options
+
+## v.2.6.0-1 - 01 Apr, 2016
+
+A second pre-release with further fixes. This is likely going to be released as 2.6.0 stable without further changes.
+
+Features
+
+- Added type validations for client.send_command arguments
+
+Bugfixes
+
+- Fixed client.send_command not working properly with every command and every option
+- Fixed pub sub mode unsubscribing from all channels in combination with the new `string_numbers` option crashing
+- Fixed pub sub mode unsubscribing from all channels not respected while reconnecting
+- Fixed pub sub mode events in combination with the `string_numbers` option emitting the number of channels not as number
+
+## v.2.6.0-0 - 27 Mar, 2016
+
+This is mainly a very important bug fix release with some smaller features.
+
+Features
+
+- Monitor and pub sub mode now work together with the offline queue
+ - All commands that were send after a connection loss are now going to be send after reconnecting
+- Activating monitor mode does now work together with arbitrary commands including pub sub mode
+- Pub sub mode is completely rewritten and all known issues fixed
+- Added `string_numbers` option to get back strings instead of numbers
+- Quit command is from now on always going to end the connection properly
+
+Bugfixes
+
+- Fixed calling monitor command while other commands are still running
+- Fixed monitor and pub sub mode not working together
+- Fixed monitor mode not working in combination with the offline queue
+- Fixed pub sub mode not working in combination with the offline queue
+- Fixed pub sub mode resubscribing not working with non utf8 buffer channels
+- Fixed pub sub mode crashing if calling unsubscribe / subscribe in various combinations
+- Fixed pub sub mode emitting unsubscribe even if no channels were unsubscribed
+- Fixed pub sub mode emitting a message without a message published
+- Fixed quit command not ending the connection and resulting in further reconnection if called while reconnecting
+
+The quit command did not end connections earlier if the connection was down at that time and this could have
+lead to strange situations, therefor this was fixed to end the connection right away in those cases.
+
+## v.2.5.3 - 21 Mar, 2016
+
+Bugfixes
+
+- Revert throwing on invalid data types and print a warning instead
+
+## v.2.5.2 - 16 Mar, 2016
+
+Bugfixes
+
+- Fixed breaking changes against Redis 2.4 introduced in 2.5.0 / 2.5.1
+
+## v.2.5.1 - 15 Mar, 2016
+
+Bugfixes
+
+- Fixed info command not working anymore with optional section argument
+
+## v.2.5.0 - 15 Mar, 2016
+
+Same changelog as the pre-release
+
+## v.2.5.0-1 - 07 Mar, 2016
+
+This is a big release with some substantial underlining changes. Therefor this is released as a pre-release and I encourage anyone who's able to, to test this out.
+
+It took way to long to release this one and the next release cycles will be shorter again.
+
+This release is also going to deprecate a couple things to prepare for a future v.3 (it'll still take a while to v.3).
+
+Features
+
+- The parsers moved into the [redis-parser](https://github.com/NodeRedis/node-redis-parser) module and will be maintained in there from now on
+ - Improve js parser speed significantly for big SUNION/SINTER/LRANGE/ZRANGE
+- Improve redis-url parsing to also accept the database-number and options as query parameters as suggested in [IANA](http://www.iana.org/assignments/uri-schemes/prov/redis)
+- Added a `retry_unfulfilled_commands` option
+ - Setting this to 'true' results in retrying all commands that were not fulfilled on a connection loss after the reconnect. Use with caution
+- Added a `db` option to select the database while connecting (this is [not recommended](https://groups.google.com/forum/#!topic/redis-db/vS5wX8X4Cjg))
+- Added a `password` option as alias for auth_pass
+- The client.server_info is from now on updated while using the info command
+- Gracefuly handle redis protocol errors from now on
+- Added a `warning` emitter that receives node_redis warnings like auth not required and deprecation messages
+- Added a `retry_strategy` option that replaces all reconnect options
+- The reconnecting event from now on also receives:
+ - The error message why the reconnect happened (params.error)
+ - The amount of times the client was connected (params.times_connected)
+ - The total reconnecting time since the last time connected (params.total_retry_time)
+- Always respect the command execution order no matter if the reply could be returned sync or not (former exceptions: [#937](https://github.com/NodeRedis/node_redis/issues/937#issuecomment-167525939))
+- redis.createClient is now checking input values stricter and detects more faulty input
+- Started refactoring internals into individual modules
+- Pipelining speed improvements
+
+Bugfixes
+
+- Fixed explicit undefined as a command callback in a multi context
+- Fixed hmset failing to detect the first key as buffer or date if the key is of that type
+- Fixed do not run toString on an array argument and throw a "invalid data" error instead
+ - This is not considered as breaking change, as this is likely a error in your code and if you want to have such a behavior you should handle this beforehand
+ - The same applies to Map / Set and individual Object types
+- Fixed redis url not accepting the protocol being omitted or protocols other than the redis protocol for convenience
+- Fixed parsing the db keyspace even if the first database does not begin with a zero
+- Fixed handling of errors occurring while receiving pub sub messages
+- Fixed huge string pipelines crashing NodeJS (Pipeline size above 256mb)
+- Fixed rename_commands and prefix option not working together
+- Fixed ready being emitted to early in case a slave is still syncing / master down
+
+Deprecations
+
+- Using any command with a argument being set to null or undefined is deprecated
+ - From v.3.0.0 on using a command with such an argument will return an error instead
+ - If you want to keep the old behavior please use a precheck in your code that converts the arguments to a string.
+ - Using SET or SETEX with a undefined or null value will from now on also result in converting the value to "null" / "undefined" to have a consistent behavior. This is not considered as breaking change, as it returned an error earlier.
+- Using .end(flush) without the flush parameter is deprecated and the flush parameter should explicitly be used
+ - From v.3.0.0 on using .end without flush will result in an error
+ - Using .end without flush means that any command that did not yet return is going to silently fail. Therefor this is considered harmful and you should explicitly silence such errors if you are sure you want this
+- Depending on the return value of a command to detect the backpressure is deprecated
+ - From version 3.0.0 on node_redis might not return true / false as a return value anymore. Please rely on client.should_buffer instead
+- The `socket_nodelay` option is deprecated and will be removed in v.3.0.0
+ - If you want to buffer commands you should use [.batch or .multi](./README.md) instead. This is necessary to reduce the amount of different options and this is very likely reducing your throughput if set to false.
+ - If you are sure you want to activate the NAGLE algorithm you can still activate it by using client.stream.setNoDelay(false)
+- The `max_attempts` option is deprecated and will be removed in v.3.0.0. Please use the `retry_strategy` instead
+- The `retry_max_delay` option is deprecated and will be removed in v.3.0.0. Please use the `retry_strategy` instead
+- The drain event is deprecated and will be removed in v.3.0.0. Please listen to the stream drain event instead
+- The idle event is deprecated and will likely be removed in v.3.0.0. If you rely on this feature please open a new ticket in node_redis with your use case
+- Redis < v. 2.6 is not officially supported anymore and might not work in all cases. Please update to a newer redis version as it is not possible to test for these old versions
+- Removed non documented command syntax (adding the callback to an arguments array instead of passing it as individual argument)
+
+## v.2.4.2 - 27 Nov, 2015
+
+Bugfixes
+
+- Fixed not emitting ready after reconnect with disable_resubscribing ([@maxgalbu](https://github.com/maxgalbu))
+
+## v.2.4.1 - 25 Nov, 2015
+
+Bugfixes
+
+- Fixed a js parser regression introduced in 2.4.0 ([@BridgeAR](https://github.com/BridgeAR))
+
+## v.2.4.0 - 25 Nov, 2015
+
+Features
+
+- Added `tls` option to initiate a connection to a redis server behind a TLS proxy. Thanks ([@paddybyers](https://github.com/paddybyers))
+- Added `prefix` option to auto key prefix any command with the provided prefix ([@luin](https://github.com/luin) & [@BridgeAR](https://github.com/BridgeAR))
+- Added `url` option to pass the connection url with the options object ([@BridgeAR](https://github.com/BridgeAR))
+- Added `client.duplicate([options])` to duplicate the current client and return a new one with the same options ([@BridgeAR](https://github.com/BridgeAR))
+- Improve performance by up to 20% on almost all use cases ([@BridgeAR](https://github.com/BridgeAR))
+
+Bugfixes
+
+- Fixed js parser handling big values slow ([@BridgeAR](https://github.com/BridgeAR))
+ - The speed is now on par with the hiredis parser.
+
+## v.2.3.1 - 18 Nov, 2015
+
+Bugfixes
+
+- Fixed saving buffers with charsets other than utf-8 while using multi ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed js parser handling big values very slow ([@BridgeAR](https://github.com/BridgeAR))
+ - The speed is up to ~500% faster than before but still up to ~50% slower than the hiredis parser.
+
+## v.2.3.0 - 30 Oct, 2015
+
+Features
+
+- Improve speed further for: ([@BridgeAR](https://github.com/BridgeAR))
+ - saving big strings (up to +300%)
+ - using .multi / .batch (up to +50% / on Node.js 0.10.x +300%)
+ - saving small buffers
+- Increased coverage to 99% ([@BridgeAR](https://github.com/BridgeAR))
+- Refactored manual backpressure control ([@BridgeAR](https://github.com/BridgeAR))
+ - Removed the high water mark and low water mark. Such a mechanism should be implemented by a user instead
+ - The `drain` event is from now on only emitted if the stream really had to buffer
+- Reduced the default connect_timeout to be one hour instead of 24h ([@BridgeAR](https://github.com/BridgeAR))
+- Added .path to redis.createClient(options); ([@BridgeAR](https://github.com/BridgeAR))
+- Ignore info command, if not available on server ([@ivanB1975](https://github.com/ivanB1975))
+
+Bugfixes
+
+- Fixed a js parser error that could result in a timeout ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed .multi / .batch used with Node.js 0.10.x not working properly after a reconnect ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed fired but not yet returned commands not being rejected after a connection loss ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed connect_timeout not respected if no connection has ever been established ([@gagle](https://github.com/gagle) & [@benjie](https://github.com/benjie))
+- Fixed return_buffers in pub sub mode ([@komachi](https://github.com/komachi))
+
+## v.2.2.5 - 18 Oct, 2015
+
+Bugfixes
+
+- Fixed undefined options passed to a new instance not accepted (possible with individual .createClient functions) ([@BridgeAR](https://github.com/BridgeAR))
+
+## v.2.2.4 - 17 Oct, 2015
+
+Bugfixes
+
+- Fixed unspecific error message for unresolvable commands ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed not allowed command error in pubsub mode not being returned in a provided callback ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed to many commands forbidden in pub sub mode ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed mutation of the arguments array passed to .multi / .batch constructor ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed mutation of the options object passed to createClient ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed error callback in .multi not called if connection in broken mode ([@BridgeAR](https://github.com/BridgeAR))
+
+## v.2.2.3 - 14 Oct, 2015
+
+Bugfixes
+
+- Fixed multi not being executed on Node 0.10.x if node_redis not yet ready ([@BridgeAR](https://github.com/BridgeAR))
+
+## v.2.2.2 - 14 Oct, 2015
+
+Bugfixes
+
+- Fixed regular commands not being executed after a .multi until .exec was called ([@BridgeAR](https://github.com/BridgeAR))
+
+## v.2.2.1 - 12 Oct, 2015
+
+No code change
+
+## v.2.2.0 - 12 Oct, 2015 - The peregrino falcon
+
+The peregrino falcon is the fasted bird on earth and this is what this release is all about: Increased performance for heavy usage by up to **400%** [sic!] and increased overall performance for any command as well. Please check the benchmarks in the [README.md](README.md) for further details.
+
+Features
+
+- Added rename_commands options to handle renamed commands from the redis config ([@digmxl](https://github.com/digmxl) & [@BridgeAR](https://github.com/BridgeAR))
+- Added disable_resubscribing option to prevent a client from resubscribing after reconnecting ([@BridgeAR](https://github.com/BridgeAR))
+- Increased performance ([@BridgeAR](https://github.com/BridgeAR))
+ - exchanging built in queue with [@petkaantonov](https://github.com/petkaantonov)'s [double-ended queue](https://github.com/petkaantonov/deque)
+ - prevent polymorphism
+ - optimize statements
+- Added *.batch* command, similar to .multi but without transaction ([@BridgeAR](https://github.com/BridgeAR))
+- Improved pipelining to minimize the [RTT](http://redis.io/topics/pipelining) further ([@BridgeAR](https://github.com/BridgeAR))
+
+Bugfixes
+
+- Fixed a javascript parser regression introduced in 2.0 that could result in timeouts on high load. ([@BridgeAR](https://github.com/BridgeAR))
+ - I was not able to write a regression test for this, since the error seems to only occur under heavy load with special conditions. So please have a look for timeouts with the js parser, if you use it and report all issues and switch to the hiredis parser in the meanwhile. If you're able to come up with a reproducable test case, this would be even better :)
+- Fixed should_buffer boolean for .exec, .select and .auth commands not being returned and fix a couple special conditions ([@BridgeAR](https://github.com/BridgeAR))
+
+If you do not rely on transactions but want to reduce the RTT you can use .batch from now on. It'll behave just the same as .multi but it does not have any transaction and therefor won't roll back any failed commands.
+Both .multi and .batch are from now on going to cache the commands and release them while calling .exec.
+
+Please consider using .batch instead of looping through a lot of commands one by one. This will significantly improve your performance.
+
+Here are some stats compared to ioredis 1.9.1 (Lenovo T450s i7-5600U):
+
+ simple set
+ 82,496 op/s » ioredis
+ 112,617 op/s » node_redis
+
+ simple get
+ 82,015 op/s » ioredis
+ 105,701 op/s » node_redis
+
+ simple get with pipeline
+ 10,233 op/s » ioredis
+ 26,541 op/s » node_redis (using .batch)
+
+ lrange 100
+ 7,321 op/s » ioredis
+ 26,155 op/s » node_redis
+
+ publish
+ 90,524 op/s » ioredis
+ 112,823 op/s » node_redis
+
+ subscribe
+ 43,783 op/s » ioredis
+ 61,889 op/s » node_redis
+
+To conclude: we can proudly say that node_redis is very likely outperforming any other node redis client.
+
+Known issues
+
+- The pub sub system has some flaws and those will be addressed in the next minor release
+
+## v2.1.0 - Oct 02, 2015
+
+Features:
+
+- Addded optional flush parameter to `.end`. If set to true, commands fired after using .end are going to be rejected instead of being ignored. (@crispy1989)
+- Addded: host and port can now be provided in a single options object. E.g. redis.createClient({ host: 'localhost', port: 1337, max_attempts: 5 }); (@BridgeAR)
+- Speedup common cases (@BridgeAR)
+
+Bugfixes:
+
+- Fix argument mutation while using the array notation with the multi constructor (@BridgeAR)
+- Fix multi.hmset key not being type converted if used with an object and key not being a string (@BridgeAR)
+- Fix parser errors not being catched properly (@BridgeAR)
+- Fix a crash that could occur if a redis server does not return the info command as usual #541 (@BridgeAR)
+- Explicitly passing undefined as a callback statement will work again. E.g. client.publish('channel', 'message', undefined); (@BridgeAR)
+
+## v2.0.1 - Sep 24, 2015
+
+Bugfixes:
+
+- Fix argument mutation while using the array notation in combination with keys / callbacks ([#866](.)). (@BridgeAR)
+
+## v2.0.0 - Sep 21, 2015
+
+This is the biggest release that node_redis had since it was released in 2010. A long list of outstanding bugs has been fixed, so we are very happy to present you redis 2.0 and we highly recommend updating as soon as possible.
+
+# What's new in 2.0
+
+- Implemented a "connection is broken" mode if no connection could be established
+- node_redis no longer throws under any circumstances, preventing it from terminating applications.
+- Multi error handling is now working properly
+- Consistent command behavior including multi
+- Windows support
+- Improved performance
+- A lot of code cleanup
+- Many bug fixes
+- Better user support!
+
+## Features:
+
+- Added a "redis connection is broken" mode after reaching max connection attempts / exceeding connection timeout. (@BridgeAR)
+- Added NODE_DEBUG=redis env to activate the debug_mode (@BridgeAR)
+- Added a default connection timeout of 24h instead of never timing out as a default (@BridgeAR)
+- Added: Network errors and other stream errors will from now on include the error code as `err.code` property (@BridgeAR)
+- Added: Errors thrown by redis will now include the redis error code as `err.code` property. (@skeggse & @BridgeAR)
+- Added: Errors thrown by node_redis will now include a `err.command` property for the command used (@BridgeAR)
+- Added new commands and drop support for deprecated *substr* (@BridgeAR)
+- Added new possibilities how to provide the command arguments (@BridgeAR)
+- The entries in the keyspace of the server_info is now an object instead of a string. (@SinisterLight & @BridgeAR)
+- Small speedup here and there (e.g. by not using .toLowerCase() anymore) (@BridgeAR)
+- Full windows support (@bcoe)
+- Increased coverage by 10% and add a lot of tests to make sure everything works as it should. We now reached 97% :-) (@BridgeAR)
+- Remove dead code, clean up and refactor very old chunks (@BridgeAR)
+- Don't flush the offline queue if reconnecting (@BridgeAR)
+- Emit all errors insteaf of throwing sometimes and sometimes emitting them (@BridgeAR)
+- *auth_pass* passwords are now checked to be a valid password (@jcppman & @BridgeAR)
+
+## Bug fixes:
+
+- Don't kill the app anymore by randomly throwing errors sync instead of emitting them (@BridgeAR)
+- Don't catch user errors anymore occuring in callbacks (no try callback anymore & more fixes for the parser) (@BridgeAR)
+- Early garbage collection of queued items (@dohse)
+- Fix js parser returning errors as strings (@BridgeAR)
+- Do not wrap errors into other errors (@BridgeAR)
+- Authentication failures are now returned in the callback instead of being emitted (@BridgeAR)
+- Fix a memory leak on reconnect (@rahar)
+- Using `send_command` directly may now also be called without the args as stated in the [README.md](./README.md) (@BridgeAR)
+- Fix the multi.exec error handling (@BridgeAR)
+- Fix commands being inconsistent and behaving wrong (@BridgeAR)
+- Channel names with spaces are now properly resubscribed after a reconnection (@pbihler)
+- Do not try to reconnect after the connection timeout has been exceeded (@BridgeAR)
+- Ensure the execution order is observed if using .eval (@BridgeAR)
+- Fix commands not being rejected after calling .quit (@BridgeAR)
+- Fix .auth calling the callback twice if already connected (@BridgeAR)
+- Fix detect_buffers not working in pub sub mode and while monitoring (@BridgeAR)
+- Fix channel names always being strings instead of buffers while return_buffers is true (@BridgeAR)
+- Don't print any debug statements if not asked for (@BridgeAR)
+- Fix a couple small other bugs
+
+## Breaking changes:
+
+1. redis.send_command commands have to be lower case from now on. This does only apply if you use `.send_command` directly instead of the convenient methods like `redis.command`.
+2. Error messages have changed quite a bit. If you depend on a specific wording please check your application carfully.
+3. Errors are from now on always either returned if a callback is present or emitted. They won't be thrown (neither sync, nor async).
+4. The Multi error handling has changed a lot!
+ - All errors are from now on errors instead of strings (this only applied to the js parser).
+ - If an error occurs while queueing the commands an EXECABORT error will be returned including the failed commands as `.errors` property instead of an array with errors.
+ - If an error occurs while executing the commands and that command has a callback it'll return the error as first parameter (`err, undefined` instead of `null, undefined`).
+ - All the errors occuring while executing the commands will stay in the result value as error instance (if you used the js parser before they would have been strings). Be aware that the transaction won't be aborted if those error occurr!
+ - If `multi.exec` does not have a callback and an EXECABORT error occurrs, it'll emit that error instead.
+5. If redis can't connect to your redis server it'll give up after a certain point of failures (either max connection attempts or connection timeout exceeded). If that is the case it'll emit an CONNECTION_BROKEN error. You'll have to initiate a new client to try again afterwards.
+6. The offline queue is not flushed anymore on a reconnect. It'll stay until node_redis gives up trying to reach the server or until you close the connection.
+7. Before this release node_redis catched user errors and threw them async back. This is not the case anymore! No user behavior of what so ever will be tracked or catched.
+8. The keyspace of `redis.server_info` (db0...) is from now on an object instead of an string.
+
+NodeRedis also thanks @qdb, @tobek, @cvibhagool, @frewsxcv, @davidbanham, @serv, @vitaliylag, @chrishamant, @GamingCoder and all other contributors that I may have missed for their contributions!
+
+From now on we'll push new releases more frequently out and fix further long outstanding things and implement new features.
+
+
+
+## v1.0.0 - Aug 30, 2015
+
+* Huge issue and pull-request cleanup. Thanks Blain! (@blainsmith)
+* [#658](https://github.com/NodeRedis/node_redis/pull/658) Client now parses URL-format connection strings (e.g., redis://foo:pass@127.0.0.1:8080) (@kuwabarahiroshi)
+* [#749](https://github.com/NodeRedis/node_redis/pull/749) Fix reconnection bug when client is in monitoring mode (@danielbprice)
+* [#786](https://github.com/NodeRedis/node_redis/pull/786) Refactor createClient. Fixes #651 (@BridgeAR)
+* [#793](https://github.com/NodeRedis/node_redis/pull/793) Refactor tests and improve test coverage (@erinspice, @bcoe)
+* [#733](https://github.com/NodeRedis/node_redis/pull/733) Fixes detect_buffers functionality in the context of exec. Fixes #732, #263 (@raydog)
+* [#785](https://github.com/NodeRedis/node_redis/pull/785) Tiny speedup by using 'use strict' (@BridgeAR)
+* Fix extraneous error output due to pubsub tests (Mikael Kohlmyr)
+
+## v0.12.1 - Aug 10, 2014
+* Fix IPv6/IPv4 family selection in node 0.11+ (Various)
+
+## v0.12.0 - Aug 9, 2014
+* Fix unix socket support (Jack Tang)
+* Improve createClient argument handling (Jack Tang)
+
+## v0.11.0 - Jul 10, 2014
+
+* IPv6 Support. (Yann Stephan)
+* Revert error emitting and go back to throwing errors. (Bryce Baril)
+* Set socket_keepalive to prevent long-lived client timeouts. (mohit)
+* Correctly reset retry timer. (ouotuo)
+* Domains protection from bad user exit. (Jake Verbaten)
+* Fix reconnection socket logic to prevent misqueued entries. (Iain Proctor)
+
+## v0.10.3 - May 22, 2014
+
+* Update command list to match Redis 2.8.9 (Charles Feng)
+
+## v0.10.2 - May 18, 2014
+
+* Better binary key handling for HGETALL. (Nick Apperson)
+* Fix test not resetting `error` handler. (CrypticSwarm)
+* Fix SELECT error semantics. (Bryan English)
+
+## v0.10.1 - February 17, 2014
+
+* Skip plucking redis version from the INFO stream if INFO results weren't provided. (Robert Sköld)
+
+## v0.10.0 - December 21, 2013
+
+* Instead of throwing errors asynchronously, emit errors on client. (Bryce Baril)
+
+## v0.9.2 - December 15, 2013
+
+* Regenerate commands for new 2.8.x Redis commands. (Marek Ventur)
+* Correctly time reconnect counts when using 'auth'. (William Hockey)
+
+## v0.9.1 - November 23, 2013
+
+* Allow hmset to accept numeric keys. (Alex Stokes)
+* Fix TypeError for multiple MULTI/EXEC errors. (Kwangsu Kim)
+
+## v0.9.0 - October 17, 2013
+
+* Domains support. (Forrest L Norvell)
+
+## v0.8.6 - October 2, 2013
+
+* If error is already an Error, don't wrap it in another Error. (Mathieu M-Gosselin)
+* Fix retry delay logic (Ian Babrou)
+* Return Errors instead of strings where Errors are expected (Ian Babrou)
+* Add experimental `.unref()` method to RedisClient (Bryce Baril / Olivier Lalonde)
+* Strengthen checking of reply to prevent conflating "message" or "pmessage" fields with pub_sub replies. (Bryce Baril)
+
+## v0.8.5 - September 26, 2013
+
+* Add `auth_pass` option to connect and immediately authenticate (Henrik Peinar)
+
+## v0.8.4 - June 24, 2013
+
+Many contributed features and fixes, including:
+* Ignore password set if not needed. (jbergknoff)
+* Improved compatibility with 0.10.X for tests and client.end() (Bryce Baril)
+* Protect connection retries from application exceptions. (Amos Barreto)
+* Better exception handling for Multi/Exec (Thanasis Polychronakis)
+* Renamed pubsub mode to subscriber mode (Luke Plaster)
+* Treat SREM like SADD when passed an array (Martin Ciparelli)
+* Fix empty unsub/punsub TypeError (Jeff Barczewski)
+* Only attempt to run a callback if it one was provided (jifeng)
+
+## v0.8.3 - April 09, 2013
+
+Many contributed features and fixes, including:
+* Fix some tests for Node.js version 0.9.x+ changes (Roman Ivanilov)
+* Fix error when commands submitted after idle event handler (roamm)
+* Bypass Redis for no-op SET/SETEX commands (jifeng)
+* Fix HMGET + detect_buffers (Joffrey F)
+* Fix CLIENT LOAD functionality (Jonas Dohse)
+* Add percentage outputs to diff_multi_bench_output.js (Bryce Baril)
+* Add retry_max_delay option (Tomasz Durka)
+* Fix parser off-by-one errors with nested multi-bulk replies (Bryce Baril)
+* Prevent parser from sinking application-side exceptions (Bryce Baril)
+* Fix parser incorrect buffer skip when parsing multi-bulk errors (Bryce Baril)
+* Reverted previous change with throwing on non-string values with HMSET (David Trejo)
+* Fix command queue sync issue when using pubsub (Tom Leach)
+* Fix compatibility with two-word Redis commands (Jonas Dohse)
+* Add EVAL with array syntax (dmoena)
+* Fix tests due to Redis reply order changes in 2.6.5+ (Bryce Baril)
+* Added a test for the SLOWLOG command (Nitesh Sinha)
+* Fix SMEMBERS order dependency in test broken by Redis changes (Garrett Johnson)
+* Update commands for new Redis commands (David Trejo)
+* Prevent exception from SELECT on subscriber reconnection (roamm)
+
+
+## v0.8.2 - November 11, 2012
+
+Another version bump because 0.8.1 didn't get applied properly for some mysterious reason.
+Sorry about that.
+
+Changed name of "faster" parser to "javascript".
+
+## v0.8.1 - September 11, 2012
+
+Important bug fix for null responses (Jerry Sievert)
+
+## v0.8.0 - September 10, 2012
+
+Many contributed features and fixes, including:
+
+* Pure JavaScript reply parser that is usually faster than hiredis (Jerry Sievert)
+* Remove hiredis as optionalDependency from package.json. It still works if you want it.
+* Restore client state on reconnect, including select, subscribe, and monitor. (Ignacio Burgueño)
+* Fix idle event (Trae Robrock)
+* Many documentation improvements and bug fixes (David Trejo)
+
+## v0.7.2 - April 29, 2012
+
+Many contributed fixes. Thank you, contributors.
+
+* [GH-190] - pub/sub mode fix (Brian Noguchi)
+* [GH-165] - parser selection fix (TEHEK)
+* numerous documentation and examples updates
+* auth errors emit Errors instead of Strings (David Trejo)
+
+## v0.7.1 - November 15, 2011
+
+Fix regression in reconnect logic.
+
+Very much need automated tests for reconnection and queue logic.
+
+## v0.7.0 - November 14, 2011
+
+Many contributed fixes. Thanks everybody.
+
+* [GH-127] - properly re-initialize parser on reconnect
+* [GH-136] - handle passing undefined as callback (Ian Babrou)
+* [GH-139] - properly handle exceptions thrown in pub/sub event handlers (Felix Geisendörfer)
+* [GH-141] - detect closing state on stream error (Felix Geisendörfer)
+* [GH-142] - re-select database on reconnection (Jean-Hugues Pinson)
+* [GH-146] - add sort example (Maksim Lin)
+
+Some more goodies:
+
+* Fix bugs with node 0.6
+* Performance improvements
+* New version of `multi_bench.js` that tests more realistic scenarios
+* [GH-140] - support optional callback for subscribe commands
+* Properly flush and error out command queue when connection fails
+* Initial work on reconnection thresholds
+
+## v0.6.7 - July 30, 2011
+
+(accidentally skipped v0.6.6)
+
+Fix and test for [GH-123]
+
+Passing an Array as as the last argument should expand as users
+expect. The old behavior was to coerce the arguments into Strings,
+which did surprising things with Arrays.
+
+## v0.6.5 - July 6, 2011
+
+Contributed changes:
+
+* Support SlowBuffers (Umair Siddique)
+* Add Multi to exports (Louis-Philippe Perron)
+* Fix for drain event calculation (Vladimir Dronnikov)
+
+Thanks!
+
+## v0.6.4 - June 30, 2011
+
+Fix bug with optional callbacks for hmset.
+
+## v0.6.2 - June 30, 2011
+
+Bugs fixed:
+
+* authentication retry while server is loading db (danmaz74) [GH-101]
+* command arguments processing issue with arrays
+
+New features:
+
+* Auto update of new commands from redis.io (Dave Hoover)
+* Performance improvements and backpressure controls.
+* Commands now return the true/false value from the underlying socket write(s).
+* Implement command_queue high water and low water for more better control of queueing.
+
+See `examples/backpressure_drain.js` for more information.
+
+## v0.6.1 - June 29, 2011
+
+Add support and tests for Redis scripting through EXEC command.
+
+Bug fix for monitor mode. (forddg)
+
+Auto update of new commands from redis.io (Dave Hoover)
+
+## v0.6.0 - April 21, 2011
+
+Lots of bugs fixed.
+
+* connection error did not properly trigger reconnection logic [GH-85]
+* client.hmget(key, [val1, val2]) was not expanding properly [GH-66]
+* client.quit() while in pub/sub mode would throw an error [GH-87]
+* client.multi(['hmset', 'key', {foo: 'bar'}]) fails [GH-92]
+* unsubscribe before subscribe would make things very confused [GH-88]
+* Add BRPOPLPUSH [GH-79]
+
+## v0.5.11 - April 7, 2011
+
+Added DISCARD
+
+I originally didn't think DISCARD would do anything here because of the clever MULTI interface, but somebody
+pointed out to me that DISCARD can be used to flush the WATCH set.
+
+## v0.5.10 - April 6, 2011
+
+Added HVALS
+
+## v0.5.9 - March 14, 2011
+
+Fix bug with empty Array arguments - Andy Ray
+
+## v0.5.8 - March 14, 2011
+
+Add `MONITOR` command and special monitor command reply parsing.
+
+## v0.5.7 - February 27, 2011
+
+Add magical auth command.
+
+Authentication is now remembered by the client and will be automatically sent to the server
+on every connection, including any reconnections.
+
+## v0.5.6 - February 22, 2011
+
+Fix bug in ready check with `return_buffers` set to `true`.
+
+Thanks to Dean Mao and Austin Chau.
+
+## v0.5.5 - February 16, 2011
+
+Add probe for server readiness.
+
+When a Redis server starts up, it might take a while to load the dataset into memory.
+During this time, the server will accept connections, but will return errors for all non-INFO
+commands. Now node_redis will send an INFO command whenever it connects to a server.
+If the info command indicates that the server is not ready, the client will keep trying until
+the server is ready. Once it is ready, the client will emit a "ready" event as well as the
+"connect" event. The client will queue up all commands sent before the server is ready, just
+like it did before. When the server is ready, all offline/non-ready commands will be replayed.
+This should be backward compatible with previous versions.
+
+To disable this ready check behavior, set `options.no_ready_check` when creating the client.
+
+As a side effect of this change, the key/val params from the info command are available as
+`client.server_options`. Further, the version string is decomposed into individual elements
+in `client.server_options.versions`.
+
+## v0.5.4 - February 11, 2011
+
+Fix excess memory consumption from Queue backing store.
+
+Thanks to Gustaf Sjöberg.
+
+## v0.5.3 - February 5, 2011
+
+Fix multi/exec error reply callback logic.
+
+Thanks to Stella Laurenzo.
+
+## v0.5.2 - January 18, 2011
+
+Fix bug where unhandled error replies confuse the parser.
+
+## v0.5.1 - January 18, 2011
+
+Fix bug where subscribe commands would not handle redis-server startup error properly.
+
+## v0.5.0 - December 29, 2010
+
+Some bug fixes:
+
+* An important bug fix in reconnection logic. Previously, reply callbacks would be invoked twice after
+ a reconnect.
+* Changed error callback argument to be an actual Error object.
+
+New feature:
+
+* Add friendly syntax for HMSET using an object.
+
+## v0.4.1 - December 8, 2010
+
+Remove warning about missing hiredis. You probably do want it though.
+
+## v0.4.0 - December 5, 2010
+
+Support for multiple response parsers and hiredis C library from Pieter Noordhuis.
+Return Strings instead of Buffers by default.
+Empty nested mb reply bug fix.
+
+## v0.3.9 - November 30, 2010
+
+Fix parser bug on failed EXECs.
+
+## v0.3.8 - November 10, 2010
+
+Fix for null MULTI response when WATCH condition fails.
+
+## v0.3.7 - November 9, 2010
+
+Add "drain" and "idle" events.
+
+## v0.3.6 - November 3, 2010
+
+Add all known Redis commands from Redis master, even ones that are coming in 2.2 and beyond.
+
+Send a friendlier "error" event message on stream errors like connection refused / reset.
+
+## v0.3.5 - October 21, 2010
+
+A few bug fixes.
+
+* Fixed bug with `nil` multi-bulk reply lengths that showed up with `BLPOP` timeouts.
+* Only emit `end` once when connection goes away.
+* Fixed bug in `test.js` where driver finished before all tests completed.
+
+## unversioned wasteland
+
+See the git history for what happened before.
diff --git a/node_modules/connect-redis/node_modules/redis/index.js b/node_modules/connect-redis/node_modules/redis/index.js
new file mode 100644
index 0000000..58fcf84
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/index.js
@@ -0,0 +1,1105 @@
+'use strict';
+
+var net = require('net');
+var tls = require('tls');
+var util = require('util');
+var utils = require('./lib/utils');
+var Command = require('./lib/command');
+var Queue = require('double-ended-queue');
+var errorClasses = require('./lib/customErrors');
+var EventEmitter = require('events');
+var Parser = require('redis-parser');
+var commands = require('redis-commands');
+var debug = require('./lib/debug');
+var unifyOptions = require('./lib/createClient');
+var SUBSCRIBE_COMMANDS = {
+ subscribe: true,
+ unsubscribe: true,
+ psubscribe: true,
+ punsubscribe: true
+};
+
+// Newer Node.js versions > 0.10 return the EventEmitter right away and using .EventEmitter was deprecated
+if (typeof EventEmitter !== 'function') {
+ EventEmitter = EventEmitter.EventEmitter;
+}
+
+function noop () {}
+
+function handle_detect_buffers_reply (reply, command, buffer_args) {
+ if (buffer_args === false || this.message_buffers) {
+ // If detect_buffers option was specified, then the reply from the parser will be a buffer.
+ // If this command did not use Buffer arguments, then convert the reply to Strings here.
+ reply = utils.reply_to_strings(reply);
+ }
+
+ if (command === 'hgetall') {
+ reply = utils.reply_to_object(reply);
+ }
+ return reply;
+}
+
+exports.debug_mode = /\bredis\b/i.test(process.env.NODE_DEBUG);
+
+// Attention: The second parameter might be removed at will and is not officially supported.
+// Do not rely on this
+function RedisClient (options, stream) {
+ // Copy the options so they are not mutated
+ options = utils.clone(options);
+ EventEmitter.call(this);
+ var cnx_options = {};
+ var self = this;
+ /* istanbul ignore next: travis does not work with stunnel atm. Therefore the tls tests are skipped on travis */
+ for (var tls_option in options.tls) {
+ cnx_options[tls_option] = options.tls[tls_option];
+ // Copy the tls options into the general options to make sure the address is set right
+ if (tls_option === 'port' || tls_option === 'host' || tls_option === 'path' || tls_option === 'family') {
+ options[tls_option] = options.tls[tls_option];
+ }
+ }
+ if (stream) {
+ // The stream from the outside is used so no connection from this side is triggered but from the server this client should talk to
+ // Reconnect etc won't work with this. This requires monkey patching to work, so it is not officially supported
+ options.stream = stream;
+ this.address = '"Private stream"';
+ } else if (options.path) {
+ cnx_options.path = options.path;
+ this.address = options.path;
+ } else {
+ cnx_options.port = +options.port || 6379;
+ cnx_options.host = options.host || '127.0.0.1';
+ cnx_options.family = (!options.family && net.isIP(cnx_options.host)) || (options.family === 'IPv6' ? 6 : 4);
+ this.address = cnx_options.host + ':' + cnx_options.port;
+ }
+ // Warn on misusing deprecated functions
+ if (typeof options.retry_strategy === 'function') {
+ if ('max_attempts' in options) {
+ self.warn('WARNING: You activated the retry_strategy and max_attempts at the same time. This is not possible and max_attempts will be ignored.');
+ // Do not print deprecation warnings twice
+ delete options.max_attempts;
+ }
+ if ('retry_max_delay' in options) {
+ self.warn('WARNING: You activated the retry_strategy and retry_max_delay at the same time. This is not possible and retry_max_delay will be ignored.');
+ // Do not print deprecation warnings twice
+ delete options.retry_max_delay;
+ }
+ }
+
+ this.connection_options = cnx_options;
+ this.connection_id = RedisClient.connection_id++;
+ this.connected = false;
+ this.ready = false;
+ if (options.socket_nodelay === undefined) {
+ options.socket_nodelay = true;
+ } else if (!options.socket_nodelay) { // Only warn users with this set to false
+ self.warn(
+ 'socket_nodelay is deprecated and will be removed in v.3.0.0.\n' +
+ 'Setting socket_nodelay to false likely results in a reduced throughput. Please use .batch for pipelining instead.\n' +
+ 'If you are sure you rely on the NAGLE-algorithm you can activate it by calling client.stream.setNoDelay(false) instead.'
+ );
+ }
+ if (options.socket_keepalive === undefined) {
+ options.socket_keepalive = true;
+ }
+ for (var command in options.rename_commands) {
+ options.rename_commands[command.toLowerCase()] = options.rename_commands[command];
+ }
+ options.return_buffers = !!options.return_buffers;
+ options.detect_buffers = !!options.detect_buffers;
+ // Override the detect_buffers setting if return_buffers is active and print a warning
+ if (options.return_buffers && options.detect_buffers) {
+ self.warn('WARNING: You activated return_buffers and detect_buffers at the same time. The return value is always going to be a buffer.');
+ options.detect_buffers = false;
+ }
+ if (options.detect_buffers) {
+ // We only need to look at the arguments if we do not know what we have to return
+ this.handle_reply = handle_detect_buffers_reply;
+ }
+ this.should_buffer = false;
+ this.max_attempts = options.max_attempts | 0;
+ if ('max_attempts' in options) {
+ self.warn(
+ 'max_attempts is deprecated and will be removed in v.3.0.0.\n' +
+ 'To reduce the number of options and to improve the reconnection handling please use the new `retry_strategy` option instead.\n' +
+ 'This replaces the max_attempts and retry_max_delay option.'
+ );
+ }
+ this.command_queue = new Queue(); // Holds sent commands to de-pipeline them
+ this.offline_queue = new Queue(); // Holds commands issued but not able to be sent
+ this.pipeline_queue = new Queue(); // Holds all pipelined commands
+ // ATTENTION: connect_timeout should change in v.3.0 so it does not count towards ending reconnection attempts after x seconds
+ // This should be done by the retry_strategy. Instead it should only be the timeout for connecting to redis
+ this.connect_timeout = +options.connect_timeout || 3600000; // 60 * 60 * 1000 ms
+ this.enable_offline_queue = options.enable_offline_queue === false ? false : true;
+ this.retry_max_delay = +options.retry_max_delay || null;
+ if ('retry_max_delay' in options) {
+ self.warn(
+ 'retry_max_delay is deprecated and will be removed in v.3.0.0.\n' +
+ 'To reduce the amount of options and the improve the reconnection handling please use the new `retry_strategy` option instead.\n' +
+ 'This replaces the max_attempts and retry_max_delay option.'
+ );
+ }
+ this.initialize_retry_vars();
+ this.pub_sub_mode = 0;
+ this.subscription_set = {};
+ this.monitoring = false;
+ this.message_buffers = false;
+ this.closing = false;
+ this.server_info = {};
+ this.auth_pass = options.auth_pass || options.password;
+ this.selected_db = options.db; // Save the selected db here, used when reconnecting
+ this.old_state = null;
+ this.fire_strings = true; // Determine if strings or buffers should be written to the stream
+ this.pipeline = false;
+ this.sub_commands_left = 0;
+ this.times_connected = 0;
+ this.buffers = options.return_buffers || options.detect_buffers;
+ this.options = options;
+ this.reply = 'ON'; // Returning replies is the default
+ this.create_stream();
+ // The listeners will not be attached right away, so let's print the deprecation message while the listener is attached
+ this.on('newListener', function (event) {
+ if (event === 'idle') {
+ this.warn(
+ 'The idle event listener is deprecated and will likely be removed in v.3.0.0.\n' +
+ 'If you rely on this feature please open a new ticket in node_redis with your use case'
+ );
+ } else if (event === 'drain') {
+ this.warn(
+ 'The drain event listener is deprecated and will be removed in v.3.0.0.\n' +
+ 'If you want to keep on listening to this event please listen to the stream drain event directly.'
+ );
+ } else if ((event === 'message_buffer' || event === 'pmessage_buffer' || event === 'messageBuffer' || event === 'pmessageBuffer') && !this.buffers && !this.message_buffers) {
+ if (this.reply_parser.name !== 'javascript') {
+ return this.warn(
+ 'You attached the "' + event + '" listener without the returnBuffers option set to true.\n' +
+ 'Please use the JavaScript parser or set the returnBuffers option to true to return buffers.'
+ );
+ }
+ this.reply_parser.optionReturnBuffers = true;
+ this.message_buffers = true;
+ this.handle_reply = handle_detect_buffers_reply;
+ }
+ });
+}
+util.inherits(RedisClient, EventEmitter);
+
+RedisClient.connection_id = 0;
+
+function create_parser (self) {
+ return new Parser({
+ returnReply: function (data) {
+ self.return_reply(data);
+ },
+ returnError: function (err) {
+ // Return a ReplyError to indicate Redis returned an error
+ self.return_error(err);
+ },
+ returnFatalError: function (err) {
+ // Error out all fired commands. Otherwise they might rely on faulty data. We have to reconnect to get in a working state again
+ // Note: the execution order is important. First flush and emit, then create the stream
+ err.message += '. Please report this.';
+ self.ready = false;
+ self.flush_and_error({
+ message: 'Fatal error encountert. Command aborted.',
+ code: 'NR_FATAL'
+ }, {
+ error: err,
+ queues: ['command_queue']
+ });
+ self.emit('error', err);
+ self.create_stream();
+ },
+ returnBuffers: self.buffers || self.message_buffers,
+ name: self.options.parser || 'javascript',
+ stringNumbers: self.options.string_numbers || false
+ });
+}
+
+/******************************************************************************
+
+ All functions in here are internal besides the RedisClient constructor
+ and the exported functions. Don't rely on them as they will be private
+ functions in node_redis v.3
+
+******************************************************************************/
+
+// Attention: the function name "create_stream" should not be changed, as other libraries need this to mock the stream (e.g. fakeredis)
+RedisClient.prototype.create_stream = function () {
+ var self = this;
+
+ // Init parser
+ this.reply_parser = create_parser(this);
+
+ if (this.options.stream) {
+ // Only add the listeners once in case of a reconnect try (that won't work)
+ if (this.stream) {
+ return;
+ }
+ this.stream = this.options.stream;
+ } else {
+ // On a reconnect destroy the former stream and retry
+ if (this.stream) {
+ this.stream.removeAllListeners();
+ this.stream.destroy();
+ }
+
+ /* istanbul ignore if: travis does not work with stunnel atm. Therefore the tls tests are skipped on travis */
+ if (this.options.tls) {
+ this.stream = tls.connect(this.connection_options);
+ } else {
+ this.stream = net.createConnection(this.connection_options);
+ }
+ }
+
+ if (this.options.connect_timeout) {
+ this.stream.setTimeout(this.connect_timeout, function () {
+ // Note: This is only tested if a internet connection is established
+ self.retry_totaltime = self.connect_timeout;
+ self.connection_gone('timeout');
+ });
+ }
+
+ /* istanbul ignore next: travis does not work with stunnel atm. Therefore the tls tests are skipped on travis */
+ var connect_event = this.options.tls ? 'secureConnect' : 'connect';
+ this.stream.once(connect_event, function () {
+ this.removeAllListeners('timeout');
+ self.times_connected++;
+ self.on_connect();
+ });
+
+ this.stream.on('data', function (buffer_from_socket) {
+ // The buffer_from_socket.toString() has a significant impact on big chunks and therefore this should only be used if necessary
+ debug('Net read ' + self.address + ' id ' + self.connection_id); // + ': ' + buffer_from_socket.toString());
+ self.reply_parser.execute(buffer_from_socket);
+ self.emit_idle();
+ });
+
+ this.stream.on('error', function (err) {
+ self.on_error(err);
+ });
+
+ /* istanbul ignore next: difficult to test and not important as long as we keep this listener */
+ this.stream.on('clientError', function (err) {
+ debug('clientError occured');
+ self.on_error(err);
+ });
+
+ this.stream.once('close', function (hadError) {
+ self.connection_gone('close');
+ });
+
+ this.stream.once('end', function () {
+ self.connection_gone('end');
+ });
+
+ this.stream.on('drain', function () {
+ self.drain();
+ });
+
+ if (this.options.socket_nodelay) {
+ this.stream.setNoDelay();
+ }
+
+ // Fire the command before redis is connected to be sure it's the first fired command
+ if (this.auth_pass !== undefined) {
+ this.ready = true;
+ // Fail silently as we might not be able to connect
+ this.auth(this.auth_pass, function (err) {
+ if (err && err.code !== 'UNCERTAIN_STATE') {
+ self.emit('error', err);
+ }
+ });
+ this.ready = false;
+ }
+};
+
+RedisClient.prototype.handle_reply = function (reply, command) {
+ if (command === 'hgetall') {
+ reply = utils.reply_to_object(reply);
+ }
+ return reply;
+};
+
+RedisClient.prototype.cork = noop;
+RedisClient.prototype.uncork = noop;
+
+RedisClient.prototype.initialize_retry_vars = function () {
+ this.retry_timer = null;
+ this.retry_totaltime = 0;
+ this.retry_delay = 200;
+ this.retry_backoff = 1.7;
+ this.attempts = 1;
+};
+
+RedisClient.prototype.warn = function (msg) {
+ var self = this;
+ // Warn on the next tick. Otherwise no event listener can be added
+ // for warnings that are emitted in the redis client constructor
+ process.nextTick(function () {
+ if (self.listeners('warning').length !== 0) {
+ self.emit('warning', msg);
+ } else {
+ console.warn('node_redis:', msg);
+ }
+ });
+};
+
+// Flush provided queues, erroring any items with a callback first
+RedisClient.prototype.flush_and_error = function (error_attributes, options) {
+ options = options || {};
+ var aggregated_errors = [];
+ var queue_names = options.queues || ['command_queue', 'offline_queue']; // Flush the command_queue first to keep the order intakt
+ for (var i = 0; i < queue_names.length; i++) {
+ // If the command was fired it might have been processed so far
+ if (queue_names[i] === 'command_queue') {
+ error_attributes.message += ' It might have been processed.';
+ } else { // As the command_queue is flushed first, remove this for the offline queue
+ error_attributes.message = error_attributes.message.replace(' It might have been processed.', '');
+ }
+ // Don't flush everything from the queue
+ for (var command_obj = this[queue_names[i]].shift(); command_obj; command_obj = this[queue_names[i]].shift()) {
+ var err = new errorClasses.AbortError(error_attributes);
+ if (command_obj.error) {
+ err.stack = err.stack + command_obj.error.stack.replace(/^Error.*?\n/, '\n');
+ }
+ err.command = command_obj.command.toUpperCase();
+ if (command_obj.args && command_obj.args.length) {
+ err.args = command_obj.args;
+ }
+ if (options.error) {
+ err.origin = options.error;
+ }
+ if (typeof command_obj.callback === 'function') {
+ command_obj.callback(err);
+ } else {
+ aggregated_errors.push(err);
+ }
+ }
+ }
+ // Currently this would be a breaking change, therefore it's only emitted in debug_mode
+ if (exports.debug_mode && aggregated_errors.length) {
+ var error;
+ if (aggregated_errors.length === 1) {
+ error = aggregated_errors[0];
+ } else {
+ error_attributes.message = error_attributes.message.replace('It', 'They').replace(/command/i, '$&s');
+ error = new errorClasses.AggregateError(error_attributes);
+ error.errors = aggregated_errors;
+ }
+ this.emit('error', error);
+ }
+};
+
+RedisClient.prototype.on_error = function (err) {
+ if (this.closing) {
+ return;
+ }
+
+ err.message = 'Redis connection to ' + this.address + ' failed - ' + err.message;
+ debug(err.message);
+ this.connected = false;
+ this.ready = false;
+
+ // Only emit the error if the retry_stategy option is not set
+ if (!this.options.retry_strategy) {
+ this.emit('error', err);
+ }
+ // 'error' events get turned into exceptions if they aren't listened for. If the user handled this error
+ // then we should try to reconnect.
+ this.connection_gone('error', err);
+};
+
+RedisClient.prototype.on_connect = function () {
+ debug('Stream connected ' + this.address + ' id ' + this.connection_id);
+
+ this.connected = true;
+ this.ready = false;
+ this.emitted_end = false;
+ this.stream.setKeepAlive(this.options.socket_keepalive);
+ this.stream.setTimeout(0);
+
+ this.emit('connect');
+ this.initialize_retry_vars();
+
+ if (this.options.no_ready_check) {
+ this.on_ready();
+ } else {
+ this.ready_check();
+ }
+};
+
+RedisClient.prototype.on_ready = function () {
+ var self = this;
+
+ debug('on_ready called ' + this.address + ' id ' + this.connection_id);
+ this.ready = true;
+
+ this.cork = function () {
+ self.pipeline = true;
+ if (self.stream.cork) {
+ self.stream.cork();
+ }
+ };
+ this.uncork = function () {
+ if (self.fire_strings) {
+ self.write_strings();
+ } else {
+ self.write_buffers();
+ }
+ self.pipeline = false;
+ self.fire_strings = true;
+ if (self.stream.uncork) {
+ // TODO: Consider using next tick here. See https://github.com/NodeRedis/node_redis/issues/1033
+ self.stream.uncork();
+ }
+ };
+
+ // Restore modal commands from previous connection. The order of the commands is important
+ if (this.selected_db !== undefined) {
+ this.internal_send_command(new Command('select', [this.selected_db]));
+ }
+ if (this.monitoring) { // Monitor has to be fired before pub sub commands
+ this.internal_send_command(new Command('monitor', []));
+ }
+ var callback_count = Object.keys(this.subscription_set).length;
+ if (!this.options.disable_resubscribing && callback_count) {
+ // only emit 'ready' when all subscriptions were made again
+ // TODO: Remove the countdown for ready here. This is not coherent with all other modes and should therefore not be handled special
+ // We know we are ready as soon as all commands were fired
+ var callback = function () {
+ callback_count--;
+ if (callback_count === 0) {
+ self.emit('ready');
+ }
+ };
+ debug('Sending pub/sub on_ready commands');
+ for (var key in this.subscription_set) {
+ var command = key.slice(0, key.indexOf('_'));
+ var args = this.subscription_set[key];
+ this[command]([args], callback);
+ }
+ this.send_offline_queue();
+ return;
+ }
+ this.send_offline_queue();
+ this.emit('ready');
+};
+
+RedisClient.prototype.on_info_cmd = function (err, res) {
+ if (err) {
+ if (err.message === "ERR unknown command 'info'") {
+ this.on_ready();
+ return;
+ }
+ err.message = 'Ready check failed: ' + err.message;
+ this.emit('error', err);
+ return;
+ }
+
+ /* istanbul ignore if: some servers might not respond with any info data. This is just a safety check that is difficult to test */
+ if (!res) {
+ debug('The info command returned without any data.');
+ this.on_ready();
+ return;
+ }
+
+ if (!this.server_info.loading || this.server_info.loading === '0') {
+ // If the master_link_status exists but the link is not up, try again after 50 ms
+ if (this.server_info.master_link_status && this.server_info.master_link_status !== 'up') {
+ this.server_info.loading_eta_seconds = 0.05;
+ } else {
+ // Eta loading should change
+ debug('Redis server ready.');
+ this.on_ready();
+ return;
+ }
+ }
+
+ var retry_time = +this.server_info.loading_eta_seconds * 1000;
+ if (retry_time > 1000) {
+ retry_time = 1000;
+ }
+ debug('Redis server still loading, trying again in ' + retry_time);
+ setTimeout(function (self) {
+ self.ready_check();
+ }, retry_time, this);
+};
+
+RedisClient.prototype.ready_check = function () {
+ var self = this;
+ debug('Checking server ready state...');
+ // Always fire this info command as first command even if other commands are already queued up
+ this.ready = true;
+ this.info(function (err, res) {
+ self.on_info_cmd(err, res);
+ });
+ this.ready = false;
+};
+
+RedisClient.prototype.send_offline_queue = function () {
+ for (var command_obj = this.offline_queue.shift(); command_obj; command_obj = this.offline_queue.shift()) {
+ debug('Sending offline command: ' + command_obj.command);
+ this.internal_send_command(command_obj);
+ }
+ this.drain();
+};
+
+var retry_connection = function (self, error) {
+ debug('Retrying connection...');
+
+ var reconnect_params = {
+ delay: self.retry_delay,
+ attempt: self.attempts,
+ error: error
+ };
+ if (self.options.camel_case) {
+ reconnect_params.totalRetryTime = self.retry_totaltime;
+ reconnect_params.timesConnected = self.times_connected;
+ } else {
+ reconnect_params.total_retry_time = self.retry_totaltime;
+ reconnect_params.times_connected = self.times_connected;
+ }
+ self.emit('reconnecting', reconnect_params);
+
+ self.retry_totaltime += self.retry_delay;
+ self.attempts += 1;
+ self.retry_delay = Math.round(self.retry_delay * self.retry_backoff);
+ self.create_stream();
+ self.retry_timer = null;
+};
+
+RedisClient.prototype.connection_gone = function (why, error) {
+ // If a retry is already in progress, just let that happen
+ if (this.retry_timer) {
+ return;
+ }
+ error = error || null;
+
+ debug('Redis connection is gone from ' + why + ' event.');
+ this.connected = false;
+ this.ready = false;
+ // Deactivate cork to work with the offline queue
+ this.cork = noop;
+ this.uncork = noop;
+ this.pipeline = false;
+ this.pub_sub_mode = 0;
+
+ // since we are collapsing end and close, users don't expect to be called twice
+ if (!this.emitted_end) {
+ this.emit('end');
+ this.emitted_end = true;
+ }
+
+ // If this is a requested shutdown, then don't retry
+ if (this.closing) {
+ debug('Connection ended by quit / end command, not retrying.');
+ this.flush_and_error({
+ message: 'Stream connection ended and command aborted.',
+ code: 'NR_CLOSED'
+ }, {
+ error: error
+ });
+ return;
+ }
+
+ if (typeof this.options.retry_strategy === 'function') {
+ var retry_params = {
+ attempt: this.attempts,
+ error: error
+ };
+ if (this.options.camel_case) {
+ retry_params.totalRetryTime = this.retry_totaltime;
+ retry_params.timesConnected = this.times_connected;
+ } else {
+ retry_params.total_retry_time = this.retry_totaltime;
+ retry_params.times_connected = this.times_connected;
+ }
+ this.retry_delay = this.options.retry_strategy(retry_params);
+ if (typeof this.retry_delay !== 'number') {
+ // Pass individual error through
+ if (this.retry_delay instanceof Error) {
+ error = this.retry_delay;
+ }
+ this.flush_and_error({
+ message: 'Stream connection ended and command aborted.',
+ code: 'NR_CLOSED'
+ }, {
+ error: error
+ });
+ this.end(false);
+ return;
+ }
+ }
+
+ if (this.max_attempts !== 0 && this.attempts >= this.max_attempts || this.retry_totaltime >= this.connect_timeout) {
+ var message = 'Redis connection in broken state: ';
+ if (this.retry_totaltime >= this.connect_timeout) {
+ message += 'connection timeout exceeded.';
+ } else {
+ message += 'maximum connection attempts exceeded.';
+ }
+
+ this.flush_and_error({
+ message: message,
+ code: 'CONNECTION_BROKEN',
+ }, {
+ error: error
+ });
+ var err = new Error(message);
+ err.code = 'CONNECTION_BROKEN';
+ if (error) {
+ err.origin = error;
+ }
+ this.emit('error', err);
+ this.end(false);
+ return;
+ }
+
+ // Retry commands after a reconnect instead of throwing an error. Use this with caution
+ if (this.options.retry_unfulfilled_commands) {
+ this.offline_queue.unshift.apply(this.offline_queue, this.command_queue.toArray());
+ this.command_queue.clear();
+ } else if (this.command_queue.length !== 0) {
+ this.flush_and_error({
+ message: 'Redis connection lost and command aborted.',
+ code: 'UNCERTAIN_STATE'
+ }, {
+ error: error,
+ queues: ['command_queue']
+ });
+ }
+
+ if (this.retry_max_delay !== null && this.retry_delay > this.retry_max_delay) {
+ this.retry_delay = this.retry_max_delay;
+ } else if (this.retry_totaltime + this.retry_delay > this.connect_timeout) {
+ // Do not exceed the maximum
+ this.retry_delay = this.connect_timeout - this.retry_totaltime;
+ }
+
+ debug('Retry connection in ' + this.retry_delay + ' ms');
+
+ this.retry_timer = setTimeout(retry_connection, this.retry_delay, this, error);
+};
+
+RedisClient.prototype.return_error = function (err) {
+ var command_obj = this.command_queue.shift();
+ if (command_obj.error) {
+ err.stack = command_obj.error.stack.replace(/^Error.*?\n/, 'ReplyError: ' + err.message + '\n');
+ }
+ err.command = command_obj.command.toUpperCase();
+ if (command_obj.args && command_obj.args.length) {
+ err.args = command_obj.args;
+ }
+
+ // Count down pub sub mode if in entering modus
+ if (this.pub_sub_mode > 1) {
+ this.pub_sub_mode--;
+ }
+
+ var match = err.message.match(utils.err_code);
+ // LUA script could return user errors that don't behave like all other errors!
+ if (match) {
+ err.code = match[1];
+ }
+
+ utils.callback_or_emit(this, command_obj.callback, err);
+};
+
+RedisClient.prototype.drain = function () {
+ this.emit('drain');
+ this.should_buffer = false;
+};
+
+RedisClient.prototype.emit_idle = function () {
+ if (this.command_queue.length === 0 && this.pub_sub_mode === 0) {
+ this.emit('idle');
+ }
+};
+
+function normal_reply (self, reply) {
+ var command_obj = self.command_queue.shift();
+ if (typeof command_obj.callback === 'function') {
+ if (command_obj.command !== 'exec') {
+ reply = self.handle_reply(reply, command_obj.command, command_obj.buffer_args);
+ }
+ command_obj.callback(null, reply);
+ } else {
+ debug('No callback for reply');
+ }
+}
+
+function subscribe_unsubscribe (self, reply, type) {
+ // Subscribe commands take an optional callback and also emit an event, but only the _last_ response is included in the callback
+ // The pub sub commands return each argument in a separate return value and have to be handled that way
+ var command_obj = self.command_queue.get(0);
+ var buffer = self.options.return_buffers || self.options.detect_buffers && command_obj.buffer_args;
+ var channel = (buffer || reply[1] === null) ? reply[1] : reply[1].toString();
+ var count = +reply[2]; // Return the channel counter as number no matter if `string_numbers` is activated or not
+ debug(type, channel);
+
+ // Emit first, then return the callback
+ if (channel !== null) { // Do not emit or "unsubscribe" something if there was no channel to unsubscribe from
+ self.emit(type, channel, count);
+ if (type === 'subscribe' || type === 'psubscribe') {
+ self.subscription_set[type + '_' + channel] = channel;
+ } else {
+ type = type === 'unsubscribe' ? 'subscribe' : 'psubscribe'; // Make types consistent
+ delete self.subscription_set[type + '_' + channel];
+ }
+ }
+
+ if (command_obj.args.length === 1 || self.sub_commands_left === 1 || command_obj.args.length === 0 && (count === 0 || channel === null)) {
+ if (count === 0) { // unsubscribed from all channels
+ var running_command;
+ var i = 1;
+ self.pub_sub_mode = 0; // Deactivating pub sub mode
+ // This should be a rare case and therefore handling it this way should be good performance wise for the general case
+ while (running_command = self.command_queue.get(i)) {
+ if (SUBSCRIBE_COMMANDS[running_command.command]) {
+ self.pub_sub_mode = i; // Entering pub sub mode again
+ break;
+ }
+ i++;
+ }
+ }
+ self.command_queue.shift();
+ if (typeof command_obj.callback === 'function') {
+ // TODO: The current return value is pretty useless.
+ // Evaluate to change this in v.3 to return all subscribed / unsubscribed channels in an array including the number of channels subscribed too
+ command_obj.callback(null, channel);
+ }
+ self.sub_commands_left = 0;
+ } else {
+ if (self.sub_commands_left !== 0) {
+ self.sub_commands_left--;
+ } else {
+ self.sub_commands_left = command_obj.args.length ? command_obj.args.length - 1 : count;
+ }
+ }
+}
+
+function return_pub_sub (self, reply) {
+ var type = reply[0].toString();
+ if (type === 'message') { // channel, message
+ if (!self.options.return_buffers || self.message_buffers) { // backwards compatible. Refactor this in v.3 to always return a string on the normal emitter
+ self.emit('message', reply[1].toString(), reply[2].toString());
+ self.emit('message_buffer', reply[1], reply[2]);
+ self.emit('messageBuffer', reply[1], reply[2]);
+ } else {
+ self.emit('message', reply[1], reply[2]);
+ }
+ } else if (type === 'pmessage') { // pattern, channel, message
+ if (!self.options.return_buffers || self.message_buffers) { // backwards compatible. Refactor this in v.3 to always return a string on the normal emitter
+ self.emit('pmessage', reply[1].toString(), reply[2].toString(), reply[3].toString());
+ self.emit('pmessage_buffer', reply[1], reply[2], reply[3]);
+ self.emit('pmessageBuffer', reply[1], reply[2], reply[3]);
+ } else {
+ self.emit('pmessage', reply[1], reply[2], reply[3]);
+ }
+ } else {
+ subscribe_unsubscribe(self, reply, type);
+ }
+}
+
+RedisClient.prototype.return_reply = function (reply) {
+ if (this.monitoring) {
+ var replyStr;
+ if (this.buffers && Buffer.isBuffer(reply)) {
+ replyStr = reply.toString();
+ } else {
+ replyStr = reply;
+ }
+ // If in monitor mode, all normal commands are still working and we only want to emit the streamlined commands
+ if (typeof replyStr === 'string' && utils.monitor_regex.test(replyStr)) {
+ var timestamp = replyStr.slice(0, replyStr.indexOf(' '));
+ var args = replyStr.slice(replyStr.indexOf('"') + 1, -1).split('" "').map(function (elem) {
+ return elem.replace(/\\"/g, '"');
+ });
+ this.emit('monitor', timestamp, args, replyStr);
+ return;
+ }
+ }
+ if (this.pub_sub_mode === 0) {
+ normal_reply(this, reply);
+ } else if (this.pub_sub_mode !== 1) {
+ this.pub_sub_mode--;
+ normal_reply(this, reply);
+ } else if (!(reply instanceof Array) || reply.length <= 2) {
+ // Only PING and QUIT are allowed in this context besides the pub sub commands
+ // Ping replies with ['pong', null|value] and quit with 'OK'
+ normal_reply(this, reply);
+ } else {
+ return_pub_sub(this, reply);
+ }
+};
+
+function handle_offline_command (self, command_obj) {
+ var command = command_obj.command;
+ var err, msg;
+ if (self.closing || !self.enable_offline_queue) {
+ command = command.toUpperCase();
+ if (!self.closing) {
+ if (self.stream.writable) {
+ msg = 'The connection is not yet established and the offline queue is deactivated.';
+ } else {
+ msg = 'Stream not writeable.';
+ }
+ } else {
+ msg = 'The connection is already closed.';
+ }
+ err = new errorClasses.AbortError({
+ message: command + " can't be processed. " + msg,
+ code: 'NR_CLOSED',
+ command: command
+ });
+ if (command_obj.args.length) {
+ err.args = command_obj.args;
+ }
+ utils.reply_in_order(self, command_obj.callback, err);
+ } else {
+ debug('Queueing ' + command + ' for next server connection.');
+ self.offline_queue.push(command_obj);
+ }
+ self.should_buffer = true;
+}
+
+// Do not call internal_send_command directly, if you are not absolutly certain it handles everything properly
+// e.g. monitor / info does not work with internal_send_command only
+RedisClient.prototype.internal_send_command = function (command_obj) {
+ var arg, prefix_keys;
+ var i = 0;
+ var command_str = '';
+ var args = command_obj.args;
+ var command = command_obj.command;
+ var len = args.length;
+ var big_data = false;
+ var args_copy = new Array(len);
+
+ if (process.domain && command_obj.callback) {
+ command_obj.callback = process.domain.bind(command_obj.callback);
+ }
+
+ if (this.ready === false || this.stream.writable === false) {
+ // Handle offline commands right away
+ handle_offline_command(this, command_obj);
+ return false; // Indicate buffering
+ }
+
+ for (i = 0; i < len; i += 1) {
+ if (typeof args[i] === 'string') {
+ // 30000 seemed to be a good value to switch to buffers after testing and checking the pros and cons
+ if (args[i].length > 30000) {
+ big_data = true;
+ args_copy[i] = new Buffer(args[i], 'utf8');
+ } else {
+ args_copy[i] = args[i];
+ }
+ } else if (typeof args[i] === 'object') { // Checking for object instead of Buffer.isBuffer helps us finding data types that we can't handle properly
+ if (args[i] instanceof Date) { // Accept dates as valid input
+ args_copy[i] = args[i].toString();
+ } else if (args[i] === null) {
+ this.warn(
+ 'Deprecated: The ' + command.toUpperCase() + ' command contains a "null" argument.\n' +
+ 'This is converted to a "null" string now and will return an error from v.3.0 on.\n' +
+ 'Please handle this in your code to make sure everything works as you intended it to.'
+ );
+ args_copy[i] = 'null'; // Backwards compatible :/
+ } else if (Buffer.isBuffer(args[i])) {
+ args_copy[i] = args[i];
+ command_obj.buffer_args = true;
+ big_data = true;
+ } else {
+ this.warn(
+ 'Deprecated: The ' + command.toUpperCase() + ' command contains a argument of type ' + args[i].constructor.name + '.\n' +
+ 'This is converted to "' + args[i].toString() + '" by using .toString() now and will return an error from v.3.0 on.\n' +
+ 'Please handle this in your code to make sure everything works as you intended it to.'
+ );
+ args_copy[i] = args[i].toString(); // Backwards compatible :/
+ }
+ } else if (typeof args[i] === 'undefined') {
+ this.warn(
+ 'Deprecated: The ' + command.toUpperCase() + ' command contains a "undefined" argument.\n' +
+ 'This is converted to a "undefined" string now and will return an error from v.3.0 on.\n' +
+ 'Please handle this in your code to make sure everything works as you intended it to.'
+ );
+ args_copy[i] = 'undefined'; // Backwards compatible :/
+ } else {
+ // Seems like numbers are converted fast using string concatenation
+ args_copy[i] = '' + args[i];
+ }
+ }
+
+ if (this.options.prefix) {
+ prefix_keys = commands.getKeyIndexes(command, args_copy);
+ for (i = prefix_keys.pop(); i !== undefined; i = prefix_keys.pop()) {
+ args_copy[i] = this.options.prefix + args_copy[i];
+ }
+ }
+ if (this.options.rename_commands && this.options.rename_commands[command]) {
+ command = this.options.rename_commands[command];
+ }
+ // Always use 'Multi bulk commands', but if passed any Buffer args, then do multiple writes, one for each arg.
+ // This means that using Buffers in commands is going to be slower, so use Strings if you don't already have a Buffer.
+ command_str = '*' + (len + 1) + '\r\n$' + command.length + '\r\n' + command + '\r\n';
+
+ if (big_data === false) { // Build up a string and send entire command in one write
+ for (i = 0; i < len; i += 1) {
+ arg = args_copy[i];
+ command_str += '$' + Buffer.byteLength(arg) + '\r\n' + arg + '\r\n';
+ }
+ debug('Send ' + this.address + ' id ' + this.connection_id + ': ' + command_str);
+ this.write(command_str);
+ } else {
+ debug('Send command (' + command_str + ') has Buffer arguments');
+ this.fire_strings = false;
+ this.write(command_str);
+
+ for (i = 0; i < len; i += 1) {
+ arg = args_copy[i];
+ if (typeof arg === 'string') {
+ this.write('$' + Buffer.byteLength(arg) + '\r\n' + arg + '\r\n');
+ } else { // buffer
+ this.write('$' + arg.length + '\r\n');
+ this.write(arg);
+ this.write('\r\n');
+ }
+ debug('send_command: buffer send ' + arg.length + ' bytes');
+ }
+ }
+ if (command_obj.call_on_write) {
+ command_obj.call_on_write();
+ }
+ // Handle `CLIENT REPLY ON|OFF|SKIP`
+ // This has to be checked after call_on_write
+ /* istanbul ignore else: TODO: Remove this as soon as we test Redis 3.2 on travis */
+ if (this.reply === 'ON') {
+ this.command_queue.push(command_obj);
+ } else {
+ // Do not expect a reply
+ // Does this work in combination with the pub sub mode?
+ if (command_obj.callback) {
+ utils.reply_in_order(this, command_obj.callback, null, undefined, this.command_queue);
+ }
+ if (this.reply === 'SKIP') {
+ this.reply = 'SKIP_ONE_MORE';
+ } else if (this.reply === 'SKIP_ONE_MORE') {
+ this.reply = 'ON';
+ }
+ }
+ return !this.should_buffer;
+};
+
+RedisClient.prototype.write_strings = function () {
+ var str = '';
+ for (var command = this.pipeline_queue.shift(); command; command = this.pipeline_queue.shift()) {
+ // Write to stream if the string is bigger than 4mb. The biggest string may be Math.pow(2, 28) - 15 chars long
+ if (str.length + command.length > 4 * 1024 * 1024) {
+ this.should_buffer = !this.stream.write(str);
+ str = '';
+ }
+ str += command;
+ }
+ if (str !== '') {
+ this.should_buffer = !this.stream.write(str);
+ }
+};
+
+RedisClient.prototype.write_buffers = function () {
+ for (var command = this.pipeline_queue.shift(); command; command = this.pipeline_queue.shift()) {
+ this.should_buffer = !this.stream.write(command);
+ }
+};
+
+RedisClient.prototype.write = function (data) {
+ if (this.pipeline === false) {
+ this.should_buffer = !this.stream.write(data);
+ return;
+ }
+ this.pipeline_queue.push(data);
+};
+
+Object.defineProperty(exports, 'debugMode', {
+ get: function () {
+ return this.debug_mode;
+ },
+ set: function (val) {
+ this.debug_mode = val;
+ }
+});
+
+// Don't officially expose the command_queue directly but only the length as read only variable
+Object.defineProperty(RedisClient.prototype, 'command_queue_length', {
+ get: function () {
+ return this.command_queue.length;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'offline_queue_length', {
+ get: function () {
+ return this.offline_queue.length;
+ }
+});
+
+// Add support for camelCase by adding read only properties to the client
+// All known exposed snake_case variables are added here
+Object.defineProperty(RedisClient.prototype, 'retryDelay', {
+ get: function () {
+ return this.retry_delay;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'retryBackoff', {
+ get: function () {
+ return this.retry_backoff;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'commandQueueLength', {
+ get: function () {
+ return this.command_queue.length;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'offlineQueueLength', {
+ get: function () {
+ return this.offline_queue.length;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'shouldBuffer', {
+ get: function () {
+ return this.should_buffer;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'connectionId', {
+ get: function () {
+ return this.connection_id;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'serverInfo', {
+ get: function () {
+ return this.server_info;
+ }
+});
+
+exports.createClient = function () {
+ return new RedisClient(unifyOptions.apply(null, arguments));
+};
+exports.RedisClient = RedisClient;
+exports.print = utils.print;
+exports.Multi = require('./lib/multi');
+exports.AbortError = errorClasses.AbortError;
+exports.RedisError = Parser.RedisError;
+exports.ParserError = Parser.ParserError;
+exports.ReplyError = Parser.ReplyError;
+exports.AggregateError = errorClasses.AggregateError;
+
+// Add all redis commands / node_redis api to the client
+require('./lib/individualCommands');
+require('./lib/extendedApi');
+
+//enables adding new commands (for modules and new commands)
+exports.addCommand = exports.add_command = require('./lib/commands');
\ No newline at end of file
diff --git a/node_modules/connect-redis/node_modules/redis/lib/command.js b/node_modules/connect-redis/node_modules/redis/lib/command.js
new file mode 100644
index 0000000..717115c
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/lib/command.js
@@ -0,0 +1,16 @@
+'use strict';
+
+var betterStackTraces = /development/i.test(process.env.NODE_ENV) || /\bredis\b/i.test(process.env.NODE_DEBUG);
+
+function Command (command, args, callback, call_on_write) {
+ this.command = command;
+ this.args = args;
+ this.buffer_args = false;
+ this.callback = callback;
+ this.call_on_write = call_on_write;
+ if (betterStackTraces) {
+ this.error = new Error();
+ }
+}
+
+module.exports = Command;
diff --git a/node_modules/connect-redis/node_modules/redis/lib/commands.js b/node_modules/connect-redis/node_modules/redis/lib/commands.js
new file mode 100644
index 0000000..6275ec8
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/lib/commands.js
@@ -0,0 +1,121 @@
+'use strict';
+
+var commands = require('redis-commands');
+var Multi = require('./multi');
+var RedisClient = require('../').RedisClient;
+var Command = require('./command');
+// Feature detect if a function may change it's name
+var changeFunctionName = (function () {
+ var fn = function abc () {};
+ try {
+ Object.defineProperty(fn, 'name', {
+ value: 'foobar'
+ });
+ return true;
+ } catch (e) {
+ return false;
+ }
+}());
+
+var addCommand = function (command) {
+ // Some rare Redis commands use special characters in their command name
+ // Convert those to a underscore to prevent using invalid function names
+ var commandName = command.replace(/(?:^([0-9])|[^a-zA-Z0-9_$])/g, '_$1');
+
+ // Do not override existing functions
+ if (!RedisClient.prototype[command]) {
+ RedisClient.prototype[command.toUpperCase()] = RedisClient.prototype[command] = function () {
+ var arr;
+ var len = arguments.length;
+ var callback;
+ var i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ if (len === 2) {
+ callback = arguments[1];
+ }
+ } else if (len > 1 && Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else {
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ return this.internal_send_command(new Command(command, arr, callback));
+ };
+ // Alias special function names (e.g. NR.RUN becomes NR_RUN and nr_run)
+ if (commandName !== command) {
+ RedisClient.prototype[commandName.toUpperCase()] = RedisClient.prototype[commandName] = RedisClient.prototype[command];
+ }
+ if (changeFunctionName) {
+ Object.defineProperty(RedisClient.prototype[command], 'name', {
+ value: commandName
+ });
+ }
+ }
+
+ // Do not override existing functions
+ if (!Multi.prototype[command]) {
+ Multi.prototype[command.toUpperCase()] = Multi.prototype[command] = function () {
+ var arr;
+ var len = arguments.length;
+ var callback;
+ var i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ if (len === 2) {
+ callback = arguments[1];
+ }
+ } else if (len > 1 && Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else {
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ this.queue.push(new Command(command, arr, callback));
+ return this;
+ };
+ // Alias special function names (e.g. NR.RUN becomes NR_RUN and nr_run)
+ if (commandName !== command) {
+ Multi.prototype[commandName.toUpperCase()] = Multi.prototype[commandName] = Multi.prototype[command];
+ }
+ if (changeFunctionName) {
+ Object.defineProperty(Multi.prototype[command], 'name', {
+ value: commandName
+ });
+ }
+ }
+};
+
+commands.list.forEach(addCommand);
+
+module.exports = addCommand;
diff --git a/node_modules/connect-redis/node_modules/redis/lib/createClient.js b/node_modules/connect-redis/node_modules/redis/lib/createClient.js
new file mode 100644
index 0000000..2f3b09f
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/lib/createClient.js
@@ -0,0 +1,80 @@
+'use strict';
+
+var utils = require('./utils');
+var URL = require('url');
+
+module.exports = function createClient (port_arg, host_arg, options) {
+
+ if (typeof port_arg === 'number' || typeof port_arg === 'string' && /^\d+$/.test(port_arg)) {
+
+ var host;
+ if (typeof host_arg === 'string') {
+ host = host_arg;
+ } else {
+ if (options && host_arg) {
+ throw new TypeError('Unknown type of connection in createClient()');
+ }
+ options = options || host_arg;
+ }
+ options = utils.clone(options);
+ options.host = host || options.host;
+ options.port = port_arg;
+
+ } else if (typeof port_arg === 'string' || port_arg && port_arg.url) {
+
+ options = utils.clone(port_arg.url ? port_arg : host_arg || options);
+ var url = port_arg.url || port_arg;
+ var parsed = URL.parse(url, true, true);
+
+ // [redis:]//[[user][:password]@][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]
+ if (parsed.slashes) { // We require slashes
+ if (parsed.auth) {
+ options.password = parsed.auth.split(':')[1];
+ }
+ if (parsed.protocol && parsed.protocol !== 'redis:') {
+ console.warn('node_redis: WARNING: You passed "' + parsed.protocol.substring(0, parsed.protocol.length - 1) + '" as protocol instead of the "redis" protocol!');
+ }
+ if (parsed.pathname && parsed.pathname !== '/') {
+ options.db = parsed.pathname.substr(1);
+ }
+ if (parsed.hostname) {
+ options.host = parsed.hostname;
+ }
+ if (parsed.port) {
+ options.port = parsed.port;
+ }
+ if (parsed.search !== '') {
+ var elem;
+ for (elem in parsed.query) {
+ // If options are passed twice, only the parsed options will be used
+ if (elem in options) {
+ if (options[elem] === parsed.query[elem]) {
+ console.warn('node_redis: WARNING: You passed the ' + elem + ' option twice!');
+ } else {
+ throw new RangeError('The ' + elem + ' option is added twice and does not match');
+ }
+ }
+ options[elem] = parsed.query[elem];
+ }
+ }
+ } else if (parsed.hostname) {
+ throw new RangeError('The redis url must begin with slashes "//" or contain slashes after the redis protocol');
+ } else {
+ options.path = url;
+ }
+
+ } else if (typeof port_arg === 'object' || port_arg === undefined) {
+ options = utils.clone(port_arg || options);
+ options.host = options.host || host_arg;
+
+ if (port_arg && arguments.length !== 1) {
+ throw new TypeError('To many arguments passed to createClient. Please only pass the options object');
+ }
+ }
+
+ if (!options) {
+ throw new TypeError('Unknown type of connection in createClient()');
+ }
+
+ return options;
+};
diff --git a/node_modules/connect-redis/node_modules/redis/lib/customErrors.js b/node_modules/connect-redis/node_modules/redis/lib/customErrors.js
new file mode 100644
index 0000000..d9b3442
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/lib/customErrors.js
@@ -0,0 +1,59 @@
+'use strict';
+
+var util = require('util');
+var assert = require('assert');
+var RedisError = require('redis-parser').RedisError;
+var ADD_STACKTRACE = false;
+
+function AbortError (obj, stack) {
+ assert(obj, 'The options argument is required');
+ assert.strictEqual(typeof obj, 'object', 'The options argument has to be of type object');
+
+ RedisError.call(this, obj.message, ADD_STACKTRACE);
+ Object.defineProperty(this, 'message', {
+ value: obj.message || '',
+ configurable: true,
+ writable: true
+ });
+ if (stack || stack === undefined) {
+ Error.captureStackTrace(this, AbortError);
+ }
+ for (var keys = Object.keys(obj), key = keys.pop(); key; key = keys.pop()) {
+ this[key] = obj[key];
+ }
+}
+
+function AggregateError (obj) {
+ assert(obj, 'The options argument is required');
+ assert.strictEqual(typeof obj, 'object', 'The options argument has to be of type object');
+
+ AbortError.call(this, obj, ADD_STACKTRACE);
+ Object.defineProperty(this, 'message', {
+ value: obj.message || '',
+ configurable: true,
+ writable: true
+ });
+ Error.captureStackTrace(this, AggregateError);
+ for (var keys = Object.keys(obj), key = keys.pop(); key; key = keys.pop()) {
+ this[key] = obj[key];
+ }
+}
+
+util.inherits(AbortError, RedisError);
+util.inherits(AggregateError, AbortError);
+
+Object.defineProperty(AbortError.prototype, 'name', {
+ value: 'AbortError',
+ configurable: true,
+ writable: true
+});
+Object.defineProperty(AggregateError.prototype, 'name', {
+ value: 'AggregateError',
+ configurable: true,
+ writable: true
+});
+
+module.exports = {
+ AbortError: AbortError,
+ AggregateError: AggregateError
+};
diff --git a/node_modules/connect-redis/node_modules/redis/lib/debug.js b/node_modules/connect-redis/node_modules/redis/lib/debug.js
new file mode 100644
index 0000000..0e6333f
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/lib/debug.js
@@ -0,0 +1,11 @@
+'use strict';
+
+var index = require('../');
+
+function debug () {
+ if (index.debug_mode) {
+ console.error.apply(null, arguments);
+ }
+}
+
+module.exports = debug;
diff --git a/node_modules/connect-redis/node_modules/redis/lib/extendedApi.js b/node_modules/connect-redis/node_modules/redis/lib/extendedApi.js
new file mode 100644
index 0000000..bac3691
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/lib/extendedApi.js
@@ -0,0 +1,113 @@
+'use strict';
+
+var utils = require('./utils');
+var debug = require('./debug');
+var RedisClient = require('../').RedisClient;
+var Command = require('./command');
+var noop = function () {};
+
+/**********************************************
+All documented and exposed API belongs in here
+**********************************************/
+
+// Redirect calls to the appropriate function and use to send arbitrary / not supported commands
+RedisClient.prototype.send_command = RedisClient.prototype.sendCommand = function (command, args, callback) {
+ // Throw to fail early instead of relying in order in this case
+ if (typeof command !== 'string') {
+ throw new TypeError('Wrong input type "' + (command !== null && command !== undefined ? command.constructor.name : command) + '" for command name');
+ }
+ command = command.toLowerCase();
+ if (!Array.isArray(args)) {
+ if (args === undefined || args === null) {
+ args = [];
+ } else if (typeof args === 'function' && callback === undefined) {
+ callback = args;
+ args = [];
+ } else {
+ throw new TypeError('Wrong input type "' + args.constructor.name + '" for args');
+ }
+ }
+ if (typeof callback !== 'function' && callback !== undefined) {
+ throw new TypeError('Wrong input type "' + (callback !== null ? callback.constructor.name : 'null') + '" for callback function');
+ }
+
+ // Using the raw multi command is only possible with this function
+ // If the command is not yet added to the client, the internal function should be called right away
+ // Otherwise we need to redirect the calls to make sure the internal functions don't get skipped
+ // The internal functions could actually be used for any non hooked function
+ // but this might change from time to time and at the moment there's no good way to distinguish them
+ // from each other, so let's just do it do it this way for the time being
+ if (command === 'multi' || typeof this[command] !== 'function') {
+ return this.internal_send_command(new Command(command, args, callback));
+ }
+ if (typeof callback === 'function') {
+ args = args.concat([callback]); // Prevent manipulating the input array
+ }
+ return this[command].apply(this, args);
+};
+
+RedisClient.prototype.end = function (flush) {
+ // Flush queue if wanted
+ if (flush) {
+ this.flush_and_error({
+ message: 'Connection forcefully ended and command aborted.',
+ code: 'NR_CLOSED'
+ });
+ } else if (arguments.length === 0) {
+ this.warn(
+ 'Using .end() without the flush parameter is deprecated and throws from v.3.0.0 on.\n' +
+ 'Please check the doku (https://github.com/NodeRedis/node_redis) and explictly use flush.'
+ );
+ }
+ // Clear retry_timer
+ if (this.retry_timer) {
+ clearTimeout(this.retry_timer);
+ this.retry_timer = null;
+ }
+ this.stream.removeAllListeners();
+ this.stream.on('error', noop);
+ this.connected = false;
+ this.ready = false;
+ this.closing = true;
+ return this.stream.destroySoon();
+};
+
+RedisClient.prototype.unref = function () {
+ if (this.connected) {
+ debug("Unref'ing the socket connection");
+ this.stream.unref();
+ } else {
+ debug('Not connected yet, will unref later');
+ this.once('connect', function () {
+ this.unref();
+ });
+ }
+};
+
+RedisClient.prototype.duplicate = function (options, callback) {
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+ var existing_options = utils.clone(this.options);
+ options = utils.clone(options);
+ for (var elem in options) {
+ existing_options[elem] = options[elem];
+ }
+ var client = new RedisClient(existing_options);
+ client.selected_db = this.selected_db;
+ if (typeof callback === 'function') {
+ var ready_listener = function () {
+ callback(null, client);
+ client.removeAllListeners(error_listener);
+ };
+ var error_listener = function (err) {
+ callback(err);
+ client.end(true);
+ };
+ client.once('ready', ready_listener);
+ client.once('error', error_listener);
+ return;
+ }
+ return client;
+};
diff --git a/node_modules/connect-redis/node_modules/redis/lib/individualCommands.js b/node_modules/connect-redis/node_modules/redis/lib/individualCommands.js
new file mode 100644
index 0000000..d366b64
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/lib/individualCommands.js
@@ -0,0 +1,617 @@
+'use strict';
+
+var utils = require('./utils');
+var debug = require('./debug');
+var Multi = require('./multi');
+var Command = require('./command');
+var no_password_is_set = /no password is set/;
+var loading = /LOADING/;
+var RedisClient = require('../').RedisClient;
+
+/********************************************************************************************
+ Replace built-in redis functions
+
+ The callback may be hooked as needed. The same does not apply to the rest of the function.
+ State should not be set outside of the callback if not absolutly necessary.
+ This is important to make sure it works the same as single command or in a multi context.
+ To make sure everything works with the offline queue use the "call_on_write" function.
+ This is going to be executed while writing to the stream.
+
+ TODO: Implement individal command generation as soon as possible to prevent divergent code
+ on single and multi calls!
+********************************************************************************************/
+
+RedisClient.prototype.multi = RedisClient.prototype.MULTI = function multi (args) {
+ var multi = new Multi(this, args);
+ multi.exec = multi.EXEC = multi.exec_transaction;
+ return multi;
+};
+
+// ATTENTION: This is not a native function but is still handled as a individual command as it behaves just the same as multi
+RedisClient.prototype.batch = RedisClient.prototype.BATCH = function batch (args) {
+ return new Multi(this, args);
+};
+
+function select_callback (self, db, callback) {
+ return function (err, res) {
+ if (err === null) {
+ // Store db in this.select_db to restore it on reconnect
+ self.selected_db = db;
+ }
+ utils.callback_or_emit(self, callback, err, res);
+ };
+}
+
+RedisClient.prototype.select = RedisClient.prototype.SELECT = function select (db, callback) {
+ return this.internal_send_command(new Command('select', [db], select_callback(this, db, callback)));
+};
+
+Multi.prototype.select = Multi.prototype.SELECT = function select (db, callback) {
+ this.queue.push(new Command('select', [db], select_callback(this._client, db, callback)));
+ return this;
+};
+
+RedisClient.prototype.monitor = RedisClient.prototype.MONITOR = function monitor (callback) {
+ // Use a individual command, as this is a special case that does not has to be checked for any other command
+ var self = this;
+ var call_on_write = function () {
+ // Activating monitor mode has to happen before Redis returned the callback. The monitor result is returned first.
+ // Therefore we expect the command to be properly processed. If this is not the case, it's not an issue either.
+ self.monitoring = true;
+ };
+ return this.internal_send_command(new Command('monitor', [], callback, call_on_write));
+};
+
+// Only works with batch, not in a transaction
+Multi.prototype.monitor = Multi.prototype.MONITOR = function monitor (callback) {
+ // Use a individual command, as this is a special case that does not has to be checked for any other command
+ if (this.exec !== this.exec_transaction) {
+ var self = this;
+ var call_on_write = function () {
+ self._client.monitoring = true;
+ };
+ this.queue.push(new Command('monitor', [], callback, call_on_write));
+ return this;
+ }
+ // Set multi monitoring to indicate the exec that it should abort
+ // Remove this "hack" as soon as Redis might fix this
+ this.monitoring = true;
+ return this;
+};
+
+function quit_callback (self, callback) {
+ return function (err, res) {
+ if (err && err.code === 'NR_CLOSED') {
+ // Pretent the quit command worked properly in this case.
+ // Either the quit landed in the offline queue and was flushed at the reconnect
+ // or the offline queue is deactivated and the command was rejected right away
+ // or the stream is not writable
+ // or while sending the quit, the connection ended / closed
+ err = null;
+ res = 'OK';
+ }
+ utils.callback_or_emit(self, callback, err, res);
+ if (self.stream.writable) {
+ // If the socket is still alive, kill it. This could happen if quit got a NR_CLOSED error code
+ self.stream.destroy();
+ }
+ };
+}
+
+RedisClient.prototype.QUIT = RedisClient.prototype.quit = function quit (callback) {
+ // TODO: Consider this for v.3
+ // Allow the quit command to be fired as soon as possible to prevent it landing in the offline queue.
+ // this.ready = this.offline_queue.length === 0;
+ var backpressure_indicator = this.internal_send_command(new Command('quit', [], quit_callback(this, callback)));
+ // Calling quit should always end the connection, no matter if there's a connection or not
+ this.closing = true;
+ this.ready = false;
+ return backpressure_indicator;
+};
+
+// Only works with batch, not in a transaction
+Multi.prototype.QUIT = Multi.prototype.quit = function quit (callback) {
+ var self = this._client;
+ var call_on_write = function () {
+ // If called in a multi context, we expect redis is available
+ self.closing = true;
+ self.ready = false;
+ };
+ this.queue.push(new Command('quit', [], quit_callback(self, callback), call_on_write));
+ return this;
+};
+
+function info_callback (self, callback) {
+ return function (err, res) {
+ if (res) {
+ var obj = {};
+ var lines = res.toString().split('\r\n');
+ var line, parts, sub_parts;
+
+ for (var i = 0; i < lines.length; i++) {
+ parts = lines[i].split(':');
+ if (parts[1]) {
+ if (parts[0].indexOf('db') === 0) {
+ sub_parts = parts[1].split(',');
+ obj[parts[0]] = {};
+ while (line = sub_parts.pop()) {
+ line = line.split('=');
+ obj[parts[0]][line[0]] = +line[1];
+ }
+ } else {
+ obj[parts[0]] = parts[1];
+ }
+ }
+ }
+ obj.versions = [];
+ if (obj.redis_version) {
+ obj.redis_version.split('.').forEach(function (num) {
+ obj.versions.push(+num);
+ });
+ }
+ // Expose info key/vals to users
+ self.server_info = obj;
+ } else {
+ self.server_info = {};
+ }
+ utils.callback_or_emit(self, callback, err, res);
+ };
+}
+
+// Store info in this.server_info after each call
+RedisClient.prototype.info = RedisClient.prototype.INFO = function info (section, callback) {
+ var args = [];
+ if (typeof section === 'function') {
+ callback = section;
+ } else if (section !== undefined) {
+ args = Array.isArray(section) ? section : [section];
+ }
+ return this.internal_send_command(new Command('info', args, info_callback(this, callback)));
+};
+
+Multi.prototype.info = Multi.prototype.INFO = function info (section, callback) {
+ var args = [];
+ if (typeof section === 'function') {
+ callback = section;
+ } else if (section !== undefined) {
+ args = Array.isArray(section) ? section : [section];
+ }
+ this.queue.push(new Command('info', args, info_callback(this._client, callback)));
+ return this;
+};
+
+function auth_callback (self, pass, callback) {
+ return function (err, res) {
+ if (err) {
+ if (no_password_is_set.test(err.message)) {
+ self.warn('Warning: Redis server does not require a password, but a password was supplied.');
+ err = null;
+ res = 'OK';
+ } else if (loading.test(err.message)) {
+ // If redis is still loading the db, it will not authenticate and everything else will fail
+ debug('Redis still loading, trying to authenticate later');
+ setTimeout(function () {
+ self.auth(pass, callback);
+ }, 100);
+ return;
+ }
+ }
+ utils.callback_or_emit(self, callback, err, res);
+ };
+}
+
+RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (pass, callback) {
+ debug('Sending auth to ' + this.address + ' id ' + this.connection_id);
+
+ // Stash auth for connect and reconnect.
+ this.auth_pass = pass;
+ var ready = this.ready;
+ this.ready = ready || this.offline_queue.length === 0;
+ var tmp = this.internal_send_command(new Command('auth', [pass], auth_callback(this, pass, callback)));
+ this.ready = ready;
+ return tmp;
+};
+
+// Only works with batch, not in a transaction
+Multi.prototype.auth = Multi.prototype.AUTH = function auth (pass, callback) {
+ debug('Sending auth to ' + this.address + ' id ' + this.connection_id);
+
+ // Stash auth for connect and reconnect.
+ this.auth_pass = pass;
+ this.queue.push(new Command('auth', [pass], auth_callback(this._client, callback)));
+ return this;
+};
+
+RedisClient.prototype.client = RedisClient.prototype.CLIENT = function client () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ callback = arguments[1];
+ } else if (Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this;
+ var call_on_write = undefined;
+ // CLIENT REPLY ON|OFF|SKIP
+ /* istanbul ignore next: TODO: Remove this as soon as Travis runs Redis 3.2 */
+ if (arr.length === 2 && arr[0].toString().toUpperCase() === 'REPLY') {
+ var reply_on_off = arr[1].toString().toUpperCase();
+ if (reply_on_off === 'ON' || reply_on_off === 'OFF' || reply_on_off === 'SKIP') {
+ call_on_write = function () {
+ self.reply = reply_on_off;
+ };
+ }
+ }
+ return this.internal_send_command(new Command('client', arr, callback, call_on_write));
+};
+
+Multi.prototype.client = Multi.prototype.CLIENT = function client () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ callback = arguments[1];
+ } else if (Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this._client;
+ var call_on_write = undefined;
+ // CLIENT REPLY ON|OFF|SKIP
+ /* istanbul ignore next: TODO: Remove this as soon as Travis runs Redis 3.2 */
+ if (arr.length === 2 && arr[0].toString().toUpperCase() === 'REPLY') {
+ var reply_on_off = arr[1].toString().toUpperCase();
+ if (reply_on_off === 'ON' || reply_on_off === 'OFF' || reply_on_off === 'SKIP') {
+ call_on_write = function () {
+ self.reply = reply_on_off;
+ };
+ }
+ }
+ this.queue.push(new Command('client', arr, callback, call_on_write));
+ return this;
+};
+
+RedisClient.prototype.hmset = RedisClient.prototype.HMSET = function hmset () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ callback = arguments[1];
+ } else if (Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else if (typeof arguments[1] === 'object' && (arguments.length === 2 || arguments.length === 3 && (typeof arguments[2] === 'function' || typeof arguments[2] === 'undefined'))) {
+ arr = [arguments[0]];
+ for (var field in arguments[1]) {
+ arr.push(field, arguments[1][field]);
+ }
+ callback = arguments[2];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ return this.internal_send_command(new Command('hmset', arr, callback));
+};
+
+Multi.prototype.hmset = Multi.prototype.HMSET = function hmset () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ callback = arguments[1];
+ } else if (Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else if (typeof arguments[1] === 'object' && (arguments.length === 2 || arguments.length === 3 && (typeof arguments[2] === 'function' || typeof arguments[2] === 'undefined'))) {
+ arr = [arguments[0]];
+ for (var field in arguments[1]) {
+ arr.push(field, arguments[1][field]);
+ }
+ callback = arguments[2];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ this.queue.push(new Command('hmset', arr, callback));
+ return this;
+};
+
+RedisClient.prototype.subscribe = RedisClient.prototype.SUBSCRIBE = function subscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this;
+ var call_on_write = function () {
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ return this.internal_send_command(new Command('subscribe', arr, callback, call_on_write));
+};
+
+Multi.prototype.subscribe = Multi.prototype.SUBSCRIBE = function subscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this._client;
+ var call_on_write = function () {
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ this.queue.push(new Command('subscribe', arr, callback, call_on_write));
+ return this;
+};
+
+RedisClient.prototype.unsubscribe = RedisClient.prototype.UNSUBSCRIBE = function unsubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this;
+ var call_on_write = function () {
+ // Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ return this.internal_send_command(new Command('unsubscribe', arr, callback, call_on_write));
+};
+
+Multi.prototype.unsubscribe = Multi.prototype.UNSUBSCRIBE = function unsubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this._client;
+ var call_on_write = function () {
+ // Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ this.queue.push(new Command('unsubscribe', arr, callback, call_on_write));
+ return this;
+};
+
+RedisClient.prototype.psubscribe = RedisClient.prototype.PSUBSCRIBE = function psubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this;
+ var call_on_write = function () {
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ return this.internal_send_command(new Command('psubscribe', arr, callback, call_on_write));
+};
+
+Multi.prototype.psubscribe = Multi.prototype.PSUBSCRIBE = function psubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this._client;
+ var call_on_write = function () {
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ this.queue.push(new Command('psubscribe', arr, callback, call_on_write));
+ return this;
+};
+
+RedisClient.prototype.punsubscribe = RedisClient.prototype.PUNSUBSCRIBE = function punsubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this;
+ var call_on_write = function () {
+ // Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ return this.internal_send_command(new Command('punsubscribe', arr, callback, call_on_write));
+};
+
+Multi.prototype.punsubscribe = Multi.prototype.PUNSUBSCRIBE = function punsubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this._client;
+ var call_on_write = function () {
+ // Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ this.queue.push(new Command('punsubscribe', arr, callback, call_on_write));
+ return this;
+};
diff --git a/node_modules/connect-redis/node_modules/redis/lib/multi.js b/node_modules/connect-redis/node_modules/redis/lib/multi.js
new file mode 100644
index 0000000..63f5d21
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/lib/multi.js
@@ -0,0 +1,187 @@
+'use strict';
+
+var Queue = require('double-ended-queue');
+var utils = require('./utils');
+var Command = require('./command');
+
+function Multi (client, args) {
+ this._client = client;
+ this.queue = new Queue();
+ var command, tmp_args;
+ if (args) { // Either undefined or an array. Fail hard if it's not an array
+ for (var i = 0; i < args.length; i++) {
+ command = args[i][0];
+ tmp_args = args[i].slice(1);
+ if (Array.isArray(command)) {
+ this[command[0]].apply(this, command.slice(1).concat(tmp_args));
+ } else {
+ this[command].apply(this, tmp_args);
+ }
+ }
+ }
+}
+
+function pipeline_transaction_command (self, command_obj, index) {
+ // Queueing is done first, then the commands are executed
+ var tmp = command_obj.callback;
+ command_obj.callback = function (err, reply) {
+ // Ignore the multi command. This is applied by node_redis and the user does not benefit by it
+ if (err && index !== -1) {
+ if (tmp) {
+ tmp(err);
+ }
+ err.position = index;
+ self.errors.push(err);
+ }
+ // Keep track of who wants buffer responses:
+ // By the time the callback is called the command_obj got the buffer_args attribute attached
+ self.wants_buffers[index] = command_obj.buffer_args;
+ command_obj.callback = tmp;
+ };
+ self._client.internal_send_command(command_obj);
+}
+
+Multi.prototype.exec_atomic = Multi.prototype.EXEC_ATOMIC = Multi.prototype.execAtomic = function exec_atomic (callback) {
+ if (this.queue.length < 2) {
+ return this.exec_batch(callback);
+ }
+ return this.exec(callback);
+};
+
+function multi_callback (self, err, replies) {
+ var i = 0, command_obj;
+
+ if (err) {
+ err.errors = self.errors;
+ if (self.callback) {
+ self.callback(err);
+ // Exclude connection errors so that those errors won't be emitted twice
+ } else if (err.code !== 'CONNECTION_BROKEN') {
+ self._client.emit('error', err);
+ }
+ return;
+ }
+
+ if (replies) {
+ while (command_obj = self.queue.shift()) {
+ if (replies[i] instanceof Error) {
+ var match = replies[i].message.match(utils.err_code);
+ // LUA script could return user errors that don't behave like all other errors!
+ if (match) {
+ replies[i].code = match[1];
+ }
+ replies[i].command = command_obj.command.toUpperCase();
+ if (typeof command_obj.callback === 'function') {
+ command_obj.callback(replies[i]);
+ }
+ } else {
+ // If we asked for strings, even in detect_buffers mode, then return strings:
+ replies[i] = self._client.handle_reply(replies[i], command_obj.command, self.wants_buffers[i]);
+ if (typeof command_obj.callback === 'function') {
+ command_obj.callback(null, replies[i]);
+ }
+ }
+ i++;
+ }
+ }
+
+ if (self.callback) {
+ self.callback(null, replies);
+ }
+}
+
+Multi.prototype.exec_transaction = function exec_transaction (callback) {
+ if (this.monitoring || this._client.monitoring) {
+ var err = new RangeError(
+ 'Using transaction with a client that is in monitor mode does not work due to faulty return values of Redis.'
+ );
+ err.command = 'EXEC';
+ err.code = 'EXECABORT';
+ return utils.reply_in_order(this._client, callback, err);
+ }
+ var self = this;
+ var len = self.queue.length;
+ self.errors = [];
+ self.callback = callback;
+ self._client.cork();
+ self.wants_buffers = new Array(len);
+ pipeline_transaction_command(self, new Command('multi', []), -1);
+ // Drain queue, callback will catch 'QUEUED' or error
+ for (var index = 0; index < len; index++) {
+ // The commands may not be shifted off, since they are needed in the result handler
+ pipeline_transaction_command(self, self.queue.get(index), index);
+ }
+
+ self._client.internal_send_command(new Command('exec', [], function (err, replies) {
+ multi_callback(self, err, replies);
+ }));
+ self._client.uncork();
+ return !self._client.should_buffer;
+};
+
+function batch_callback (self, cb, i) {
+ return function batch_callback (err, res) {
+ if (err) {
+ self.results[i] = err;
+ // Add the position to the error
+ self.results[i].position = i;
+ } else {
+ self.results[i] = res;
+ }
+ cb(err, res);
+ };
+}
+
+Multi.prototype.exec = Multi.prototype.EXEC = Multi.prototype.exec_batch = function exec_batch (callback) {
+ var self = this;
+ var len = self.queue.length;
+ var index = 0;
+ var command_obj;
+ if (len === 0) {
+ utils.reply_in_order(self._client, callback, null, []);
+ return !self._client.should_buffer;
+ }
+ self._client.cork();
+ if (!callback) {
+ while (command_obj = self.queue.shift()) {
+ self._client.internal_send_command(command_obj);
+ }
+ self._client.uncork();
+ return !self._client.should_buffer;
+ }
+ var callback_without_own_cb = function (err, res) {
+ if (err) {
+ self.results.push(err);
+ // Add the position to the error
+ var i = self.results.length - 1;
+ self.results[i].position = i;
+ } else {
+ self.results.push(res);
+ }
+ // Do not emit an error here. Otherwise each error would result in one emit.
+ // The errors will be returned in the result anyway
+ };
+ var last_callback = function (cb) {
+ return function (err, res) {
+ cb(err, res);
+ callback(null, self.results);
+ };
+ };
+ self.results = [];
+ while (command_obj = self.queue.shift()) {
+ if (typeof command_obj.callback === 'function') {
+ command_obj.callback = batch_callback(self, command_obj.callback, index);
+ } else {
+ command_obj.callback = callback_without_own_cb;
+ }
+ if (typeof callback === 'function' && index === len - 1) {
+ command_obj.callback = last_callback(command_obj.callback);
+ }
+ this._client.internal_send_command(command_obj);
+ index++;
+ }
+ self._client.uncork();
+ return !self._client.should_buffer;
+};
+
+module.exports = Multi;
diff --git a/node_modules/connect-redis/node_modules/redis/lib/utils.js b/node_modules/connect-redis/node_modules/redis/lib/utils.js
new file mode 100644
index 0000000..52e58ec
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/lib/utils.js
@@ -0,0 +1,134 @@
+'use strict';
+
+// hgetall converts its replies to an Object. If the reply is empty, null is returned.
+// These function are only called with internal data and have therefore always the same instanceof X
+function replyToObject (reply) {
+ // The reply might be a string or a buffer if this is called in a transaction (multi)
+ if (reply.length === 0 || !(reply instanceof Array)) {
+ return null;
+ }
+ var obj = {};
+ for (var i = 0; i < reply.length; i += 2) {
+ obj[reply[i].toString('binary')] = reply[i + 1];
+ }
+ return obj;
+}
+
+function replyToStrings (reply) {
+ if (reply instanceof Buffer) {
+ return reply.toString();
+ }
+ if (reply instanceof Array) {
+ var res = new Array(reply.length);
+ for (var i = 0; i < reply.length; i++) {
+ // Recusivly call the function as slowlog returns deep nested replies
+ res[i] = replyToStrings(reply[i]);
+ }
+ return res;
+ }
+
+ return reply;
+}
+
+function print (err, reply) {
+ if (err) {
+ // A error always begins with Error:
+ console.log(err.toString());
+ } else {
+ console.log('Reply: ' + reply);
+ }
+}
+
+var camelCase;
+// Deep clone arbitrary objects with arrays. Can't handle cyclic structures (results in a range error)
+// Any attribute with a non primitive value besides object and array will be passed by reference (e.g. Buffers, Maps, Functions)
+// All capital letters are going to be replaced with a lower case letter and a underscore infront of it
+function clone (obj) {
+ var copy;
+ if (Array.isArray(obj)) {
+ copy = new Array(obj.length);
+ for (var i = 0; i < obj.length; i++) {
+ copy[i] = clone(obj[i]);
+ }
+ return copy;
+ }
+ if (Object.prototype.toString.call(obj) === '[object Object]') {
+ copy = {};
+ var elems = Object.keys(obj);
+ var elem;
+ while (elem = elems.pop()) {
+ if (elem === 'tls') { // special handle tls
+ copy[elem] = obj[elem];
+ continue;
+ }
+ // Accept camelCase options and convert them to snake_case
+ var snake_case = elem.replace(/[A-Z][^A-Z]/g, '_$&').toLowerCase();
+ // If camelCase is detected, pass it to the client, so all variables are going to be camelCased
+ // There are no deep nested options objects yet, but let's handle this future proof
+ if (snake_case !== elem.toLowerCase()) {
+ camelCase = true;
+ }
+ copy[snake_case] = clone(obj[elem]);
+ }
+ return copy;
+ }
+ return obj;
+}
+
+function convenienceClone (obj) {
+ camelCase = false;
+ obj = clone(obj) || {};
+ if (camelCase) {
+ obj.camel_case = true;
+ }
+ return obj;
+}
+
+function callbackOrEmit (self, callback, err, res) {
+ if (callback) {
+ callback(err, res);
+ } else if (err) {
+ self.emit('error', err);
+ }
+}
+
+function replyInOrder (self, callback, err, res, queue) {
+ // If the queue is explicitly passed, use that, otherwise fall back to the offline queue first,
+ // as there might be commands in both queues at the same time
+ var command_obj;
+ /* istanbul ignore if: TODO: Remove this as soon as we test Redis 3.2 on travis */
+ if (queue) {
+ command_obj = queue.peekBack();
+ } else {
+ command_obj = self.offline_queue.peekBack() || self.command_queue.peekBack();
+ }
+ if (!command_obj) {
+ process.nextTick(function () {
+ callbackOrEmit(self, callback, err, res);
+ });
+ } else {
+ var tmp = command_obj.callback;
+ command_obj.callback = tmp ?
+ function (e, r) {
+ tmp(e, r);
+ callbackOrEmit(self, callback, err, res);
+ } :
+ function (e, r) {
+ if (e) {
+ self.emit('error', e);
+ }
+ callbackOrEmit(self, callback, err, res);
+ };
+ }
+}
+
+module.exports = {
+ reply_to_strings: replyToStrings,
+ reply_to_object: replyToObject,
+ print: print,
+ err_code: /^([A-Z]+)\s+(.+)$/,
+ monitor_regex: /^[0-9]{10,11}\.[0-9]+ \[[0-9]+ .+\]( ".+?")+$/,
+ clone: convenienceClone,
+ callback_or_emit: callbackOrEmit,
+ reply_in_order: replyInOrder
+};
diff --git a/node_modules/connect-redis/node_modules/redis/package.json b/node_modules/connect-redis/node_modules/redis/package.json
new file mode 100644
index 0000000..4b6d6e9
--- /dev/null
+++ b/node_modules/connect-redis/node_modules/redis/package.json
@@ -0,0 +1,59 @@
+{
+ "name": "redis",
+ "version": "2.8.0",
+ "description": "Redis client library",
+ "keywords": [
+ "database",
+ "redis",
+ "transaction",
+ "pipelining",
+ "performance",
+ "queue",
+ "nodejs",
+ "pubsub",
+ "backpressure"
+ ],
+ "author": "Matt Ranney ",
+ "license": "MIT",
+ "main": "./index.js",
+ "scripts": {
+ "coveralls": "nyc report --reporter=text-lcov | coveralls",
+ "coverage": "nyc report --reporter=html",
+ "benchmark": "node benchmarks/multi_bench.js",
+ "test": "nyc --cache mocha ./test/*.js ./test/commands/*.js --timeout=8000",
+ "lint": "eslint . --fix && npm run coverage",
+ "compare": "node benchmarks/diff_multi_bench_output.js beforeBench.txt afterBench.txt"
+ },
+ "dependencies": {
+ "double-ended-queue": "^2.1.0-0",
+ "redis-commands": "^1.2.0",
+ "redis-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "devDependencies": {
+ "bluebird": "^3.0.2",
+ "coveralls": "^2.11.2",
+ "eslint": "^4.2.0",
+ "intercept-stdout": "~0.1.2",
+ "metrics": "^0.1.9",
+ "mocha": "^3.1.2",
+ "nyc": "^10.0.0",
+ "tcp-port-used": "^0.1.2",
+ "uuid": "^2.0.1",
+ "win-spawn": "^2.0.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/NodeRedis/node_redis.git"
+ },
+ "bugs": {
+ "url": "https://github.com/NodeRedis/node_redis/issues"
+ },
+ "homepage": "https://github.com/NodeRedis/node_redis",
+ "directories": {
+ "example": "examples",
+ "test": "test"
+ }
+}
diff --git a/node_modules/dot-prop/index.js b/node_modules/dot-prop/index.js
old mode 100755
new mode 100644
index 15282bb..189831c
--- a/node_modules/dot-prop/index.js
+++ b/node_modules/dot-prop/index.js
@@ -1,6 +1,14 @@
'use strict';
const isObj = require('is-obj');
+const disallowedKeys = [
+ '__proto__',
+ 'prototype',
+ 'constructor'
+];
+
+const isValidPath = pathSegments => !pathSegments.some(segment => disallowedKeys.includes(segment));
+
function getPathSegments(path) {
const pathArr = path.split('.');
const parts = [];
@@ -16,6 +24,10 @@ function getPathSegments(path) {
parts.push(p);
}
+ if (!isValidPath(parts)) {
+ return [];
+ }
+
return parts;
}
@@ -26,6 +38,9 @@ module.exports = {
}
const pathArr = getPathSegments(path);
+ if (pathArr.length === 0) {
+ return;
+ }
for (let i = 0; i < pathArr.length; i++) {
if (!Object.prototype.propertyIsEnumerable.call(obj, pathArr[i])) {
@@ -58,6 +73,9 @@ module.exports = {
const root = obj;
const pathArr = getPathSegments(path);
+ if (pathArr.length === 0) {
+ return;
+ }
for (let i = 0; i < pathArr.length; i++) {
const p = pathArr[i];
diff --git a/node_modules/dot-prop/license b/node_modules/dot-prop/license
old mode 100755
new mode 100644
diff --git a/node_modules/dot-prop/package.json b/node_modules/dot-prop/package.json
old mode 100755
new mode 100644
index 8831c7e..c9b0f58
--- a/node_modules/dot-prop/package.json
+++ b/node_modules/dot-prop/package.json
@@ -1,53 +1,24 @@
{
- "_from": "dot-prop@^4.1.0",
- "_id": "dot-prop@4.2.0",
- "_inBundle": false,
- "_integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
- "_location": "/dot-prop",
- "_phantomChildren": {},
- "_requested": {
- "type": "range",
- "registry": true,
- "raw": "dot-prop@^4.1.0",
- "name": "dot-prop",
- "escapedName": "dot-prop",
- "rawSpec": "^4.1.0",
- "saveSpec": null,
- "fetchSpec": "^4.1.0"
- },
- "_requiredBy": [
- "/configstore"
- ],
- "_resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
- "_shasum": "1f19e0c2e1aa0e32797c49799f2837ac6af69c57",
- "_spec": "dot-prop@^4.1.0",
- "_where": "/home/pi/Node Projects/x-chat/node_modules/configstore",
+ "name": "dot-prop",
+ "version": "4.2.1",
+ "description": "Get, set, or delete a property from a nested object using a dot path",
+ "license": "MIT",
+ "repository": "sindresorhus/dot-prop",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
- "bugs": {
- "url": "https://github.com/sindresorhus/dot-prop/issues"
- },
- "bundleDependencies": false,
- "dependencies": {
- "is-obj": "^1.0.0"
- },
- "deprecated": false,
- "description": "Get, set, or delete a property from a nested object using a dot path",
- "devDependencies": {
- "ava": "*",
- "matcha": "^0.7.0",
- "xo": "*"
- },
"engines": {
"node": ">=4"
},
+ "scripts": {
+ "test": "xo && ava",
+ "bench": "matcha bench.js"
+ },
"files": [
"index.js"
],
- "homepage": "https://github.com/sindresorhus/dot-prop#readme",
"keywords": [
"obj",
"object",
@@ -63,17 +34,14 @@
"notation",
"dotty"
],
- "license": "MIT",
- "name": "dot-prop",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/sindresorhus/dot-prop.git"
+ "dependencies": {
+ "is-obj": "^1.0.0"
},
- "scripts": {
- "bench": "matcha bench.js",
- "test": "xo && ava"
+ "devDependencies": {
+ "ava": "1.4.1",
+ "matcha": "^0.7.0",
+ "xo": "0.24.0"
},
- "version": "4.2.0",
"xo": {
"esnext": true
}
diff --git a/node_modules/dot-prop/readme.md b/node_modules/dot-prop/readme.md
old mode 100755
new mode 100644
index fab3b7a..0e18f78
--- a/node_modules/dot-prop/readme.md
+++ b/node_modules/dot-prop/readme.md
@@ -85,6 +85,8 @@ Path of the property in the object, using `.` to separate each nested key.
Use `\\.` if you have a `.` in the key.
+The following path components are invalid and results in `undefined` being returned: `__proto__`, `prototype`, `constructor`.
+
#### value
Type: `any`
diff --git a/node_modules/engine.io-client/CHANGELOG.md b/node_modules/engine.io-client/CHANGELOG.md
new file mode 100644
index 0000000..0e274e2
--- /dev/null
+++ b/node_modules/engine.io-client/CHANGELOG.md
@@ -0,0 +1,35 @@
+# [3.5.0](https://github.com/socketio/engine.io-client/compare/3.4.4...3.5.0) (2020-12-30)
+
+
+### Bug Fixes
+
+* check the type of the initial packet ([8750356](https://github.com/socketio/engine.io-client/commit/8750356dba5409ba0e1d3a27da6d214118702b3e))
+
+
+
+## [3.4.4](https://github.com/socketio/engine.io-client/compare/3.4.3...3.4.4) (2020-09-30)
+
+
+
+## [3.4.3](https://github.com/socketio/engine.io-client/compare/3.4.2...3.4.3) (2020-06-04)
+
+
+### Bug Fixes
+
+* **react-native:** restrict the list of options for the WebSocket object ([e5bc106](https://github.com/socketio/engine.io-client/commit/e5bc1063cc90a7b6262146c7b5338ffff1ff9e5b))
+
+
+
+## [3.4.2](https://github.com/socketio/engine.io-client/compare/3.4.1...3.4.2) (2020-05-13)
+
+
+
+## [3.4.1](https://github.com/socketio/engine.io-client/compare/3.4.0...3.4.1) (2020-04-17)
+
+
+### Bug Fixes
+
+* use globalThis polyfill instead of self/global ([357f01d](https://github.com/socketio/engine.io-client/commit/357f01d90448d8565b650377bc7cabb351d991bd))
+
+
+
diff --git a/node_modules/engine.io-client/README.md b/node_modules/engine.io-client/README.md
index 9ab91ca..436f317 100755
--- a/node_modules/engine.io-client/README.md
+++ b/node_modules/engine.io-client/README.md
@@ -1,7 +1,7 @@
# Engine.IO client
-[![Build Status](https://travis-ci.org/socketio/engine.io-client.svg?branch=master)](http://travis-ci.org/socketio/engine.io-client)
+[![Build Status](https://github.com/socketio/engine.io-client/workflows/CI/badge.svg)](https://github.com/socketio/engine.io-client/actions)
[![NPM version](https://badge.fury.io/js/engine.io-client.svg)](http://badge.fury.io/js/engine.io-client)
This is the client for [Engine.IO](http://github.com/socketio/engine.io),
@@ -196,6 +196,7 @@ Exposed as `eio` in the browser standalone build.
will be used instead.
- `forceBase64` (`Boolean`): forces base 64 encoding for polling transport even when XHR2 responseType is available and WebSocket even if the used standard supports binary.
- `enablesXDR` (`Boolean`): enables XDomainRequest for IE8 to avoid loading bar flashing with click sound. default to `false` because XDomainRequest has a flaw of not sending cookie.
+ - `withCredentials` (`Boolean`): defaults to `true`, whether to include credentials (cookies, authorization headers, TLS client certificates, etc.) with cross-origin XHR polling requests.
- `timestampRequests` (`Boolean`): whether to add the timestamp with each
transport request. Note: polling requests are always stamped unless this
option is explicitly set to `false` (`false`)
diff --git a/node_modules/engine.io-client/engine.io.js b/node_modules/engine.io-client/engine.io.js
index c57356f..71abb1d 100755
--- a/node_modules/engine.io-client/engine.io.js
+++ b/node_modules/engine.io-client/engine.io.js
@@ -54,8 +54,7 @@ return /******/ (function(modules) { // webpackBootstrap
/* 0 */
/***/ function(module, exports, __webpack_require__) {
- 'use strict';
-
+
module.exports = __webpack_require__(1);
/**
@@ -64,27 +63,24 @@ return /******/ (function(modules) { // webpackBootstrap
* @api public
*
*/
- module.exports.parser = __webpack_require__(8);
+ module.exports.parser = __webpack_require__(9);
+
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
- 'use strict';
-
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
/**
* Module dependencies.
*/
var transports = __webpack_require__(2);
- var Emitter = __webpack_require__(17);
- var debug = __webpack_require__(21)('engine.io-client:socket');
- var index = __webpack_require__(28);
- var parser = __webpack_require__(8);
- var parseuri = __webpack_require__(29);
- var parseqs = __webpack_require__(18);
+ var Emitter = __webpack_require__(18);
+ var debug = __webpack_require__(22)('engine.io-client:socket');
+ var index = __webpack_require__(29);
+ var parser = __webpack_require__(9);
+ var parseuri = __webpack_require__(30);
+ var parseqs = __webpack_require__(19);
/**
* Module exports.
@@ -100,12 +96,12 @@ return /******/ (function(modules) { // webpackBootstrap
* @api public
*/
- function Socket(uri, opts) {
+ function Socket (uri, opts) {
if (!(this instanceof Socket)) return new Socket(uri, opts);
opts = opts || {};
- if (uri && 'object' === (typeof uri === 'undefined' ? 'undefined' : _typeof(uri))) {
+ if (uri && 'object' === typeof uri) {
opts = uri;
uri = null;
}
@@ -120,7 +116,8 @@ return /******/ (function(modules) { // webpackBootstrap
opts.hostname = parseuri(opts.host).host;
}
- this.secure = null != opts.secure ? opts.secure : typeof location !== 'undefined' && 'https:' === location.protocol;
+ this.secure = null != opts.secure ? opts.secure
+ : (typeof location !== 'undefined' && 'https:' === location.protocol);
if (opts.hostname && !opts.port) {
// if no port is specified manually, use the protocol default
@@ -128,8 +125,11 @@ return /******/ (function(modules) { // webpackBootstrap
}
this.agent = opts.agent || false;
- this.hostname = opts.hostname || (typeof location !== 'undefined' ? location.hostname : 'localhost');
- this.port = opts.port || (typeof location !== 'undefined' && location.port ? location.port : this.secure ? 443 : 80);
+ this.hostname = opts.hostname ||
+ (typeof location !== 'undefined' ? location.hostname : 'localhost');
+ this.port = opts.port || (typeof location !== 'undefined' && location.port
+ ? location.port
+ : (this.secure ? 443 : 80));
this.query = opts.query || {};
if ('string' === typeof this.query) this.query = parseqs.decode(this.query);
this.upgrade = false !== opts.upgrade;
@@ -138,6 +138,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.jsonp = false !== opts.jsonp;
this.forceBase64 = !!opts.forceBase64;
this.enablesXDR = !!opts.enablesXDR;
+ this.withCredentials = false !== opts.withCredentials;
this.timestampParam = opts.timestampParam || 't';
this.timestampRequests = opts.timestampRequests;
this.transports = opts.transports || ['polling', 'websocket'];
@@ -149,7 +150,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.rememberUpgrade = opts.rememberUpgrade || false;
this.binaryType = null;
this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
- this.perMessageDeflate = false !== opts.perMessageDeflate ? opts.perMessageDeflate || {} : false;
+ this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || {}) : false;
if (true === this.perMessageDeflate) this.perMessageDeflate = {};
if (this.perMessageDeflate && null == this.perMessageDeflate.threshold) {
@@ -167,7 +168,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.forceNode = !!opts.forceNode;
// detect ReactNative environment
- this.isReactNative = typeof navigator !== 'undefined' && typeof navigator.product === 'string' && navigator.product.toLowerCase() === 'reactnative';
+ this.isReactNative = (typeof navigator !== 'undefined' && typeof navigator.product === 'string' && navigator.product.toLowerCase() === 'reactnative');
// other options for Node.js or ReactNative client
if (typeof self === 'undefined' || this.isReactNative) {
@@ -215,9 +216,9 @@ return /******/ (function(modules) { // webpackBootstrap
*/
Socket.Socket = Socket;
- Socket.Transport = __webpack_require__(7);
+ Socket.Transport = __webpack_require__(8);
Socket.transports = __webpack_require__(2);
- Socket.parser = __webpack_require__(8);
+ Socket.parser = __webpack_require__(9);
/**
* Creates transport of the given type.
@@ -255,6 +256,7 @@ return /******/ (function(modules) { // webpackBootstrap
jsonp: options.jsonp || this.jsonp,
forceBase64: options.forceBase64 || this.forceBase64,
enablesXDR: options.enablesXDR || this.enablesXDR,
+ withCredentials: options.withCredentials || this.withCredentials,
timestampRequests: options.timestampRequests || this.timestampRequests,
timestampParam: options.timestampParam || this.timestampParam,
policyPort: options.policyPort || this.policyPort,
@@ -270,14 +272,14 @@ return /******/ (function(modules) { // webpackBootstrap
forceNode: options.forceNode || this.forceNode,
localAddress: options.localAddress || this.localAddress,
requestTimeout: options.requestTimeout || this.requestTimeout,
- protocols: options.protocols || void 0,
+ protocols: options.protocols || void (0),
isReactNative: this.isReactNative
});
return transport;
};
- function clone(obj) {
+ function clone (obj) {
var o = {};
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
@@ -340,13 +342,17 @@ return /******/ (function(modules) { // webpackBootstrap
this.transport = transport;
// set up transport listeners
- transport.on('drain', function () {
+ transport
+ .on('drain', function () {
self.onDrain();
- }).on('packet', function (packet) {
+ })
+ .on('packet', function (packet) {
self.onPacket(packet);
- }).on('error', function (e) {
+ })
+ .on('error', function (e) {
self.onError(e);
- }).on('close', function () {
+ })
+ .on('close', function () {
self.onClose('transport close');
});
};
@@ -366,7 +372,7 @@ return /******/ (function(modules) { // webpackBootstrap
Socket.priorWebsocketSuccess = false;
- function onTransportOpen() {
+ function onTransportOpen () {
if (self.onlyBinaryUpgrades) {
var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
failed = failed || upgradeLosesBinary;
@@ -408,7 +414,7 @@ return /******/ (function(modules) { // webpackBootstrap
});
}
- function freezeTransport() {
+ function freezeTransport () {
if (failed) return;
// Any callback called by transport should be ignored since now
@@ -421,7 +427,7 @@ return /******/ (function(modules) { // webpackBootstrap
}
// Handle any error that happens while probing
- function onerror(err) {
+ function onerror (err) {
var error = new Error('probe error: ' + err);
error.transport = transport.name;
@@ -432,17 +438,17 @@ return /******/ (function(modules) { // webpackBootstrap
self.emit('upgradeError', error);
}
- function onTransportClose() {
+ function onTransportClose () {
onerror('transport closed');
}
// When the socket is closed while we're probing
- function onclose() {
+ function onclose () {
onerror('socket closed');
}
// When the socket is upgraded while we're probing
- function onupgrade(to) {
+ function onupgrade (to) {
if (transport && to.name !== transport.name) {
debug('"%s" works - aborting "%s"', to.name, transport.name);
freezeTransport();
@@ -450,7 +456,7 @@ return /******/ (function(modules) { // webpackBootstrap
}
// Remove all listeners on the transport and on self
- function cleanup() {
+ function cleanup () {
transport.removeListener('open', onTransportOpen);
transport.removeListener('error', onerror);
transport.removeListener('close', onTransportClose);
@@ -498,7 +504,8 @@ return /******/ (function(modules) { // webpackBootstrap
*/
Socket.prototype.onPacket = function (packet) {
- if ('opening' === this.readyState || 'open' === this.readyState || 'closing' === this.readyState) {
+ if ('opening' === this.readyState || 'open' === this.readyState ||
+ 'closing' === this.readyState) {
debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
this.emit('packet', packet);
@@ -568,7 +575,7 @@ return /******/ (function(modules) { // webpackBootstrap
self.pingTimeoutTimer = setTimeout(function () {
if ('closed' === self.readyState) return;
self.onClose('ping timeout');
- }, timeout || self.pingInterval + self.pingTimeout);
+ }, timeout || (self.pingInterval + self.pingTimeout));
};
/**
@@ -629,7 +636,8 @@ return /******/ (function(modules) { // webpackBootstrap
*/
Socket.prototype.flush = function () {
- if ('closed' !== this.readyState && this.transport.writable && !this.upgrading && this.writeBuffer.length) {
+ if ('closed' !== this.readyState && this.transport.writable &&
+ !this.upgrading && this.writeBuffer.length) {
debug('flushing %d packets in socket', this.writeBuffer.length);
this.transport.send(this.writeBuffer);
// keep track of current length of writeBuffer
@@ -649,7 +657,8 @@ return /******/ (function(modules) { // webpackBootstrap
* @api public
*/
- Socket.prototype.write = Socket.prototype.send = function (msg, options, fn) {
+ Socket.prototype.write =
+ Socket.prototype.send = function (msg, options, fn) {
this.sendPacket('message', msg, options, fn);
return this;
};
@@ -720,19 +729,19 @@ return /******/ (function(modules) { // webpackBootstrap
}
}
- function close() {
+ function close () {
self.onClose('forced close');
debug('socket closing - telling transport to close');
self.transport.close();
}
- function cleanupAndClose() {
+ function cleanupAndClose () {
self.removeListener('upgrade', cleanupAndClose);
self.removeListener('upgradeError', cleanupAndClose);
close();
}
- function waitForUpgrade() {
+ function waitForUpgrade () {
// wait for upgrade to finish since we can't send packets while pausing a transport
self.once('upgrade', cleanupAndClose);
self.once('upgradeError', cleanupAndClose);
@@ -810,20 +819,19 @@ return /******/ (function(modules) { // webpackBootstrap
return filteredUpgrades;
};
+
/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {
- 'use strict';
-
/**
* Module dependencies
*/
var XMLHttpRequest = __webpack_require__(3);
- var XHR = __webpack_require__(5);
- var JSONP = __webpack_require__(25);
- var websocket = __webpack_require__(26);
+ var XHR = __webpack_require__(6);
+ var JSONP = __webpack_require__(26);
+ var websocket = __webpack_require__(27);
/**
* Export transports.
@@ -839,7 +847,7 @@ return /******/ (function(modules) { // webpackBootstrap
* @api private
*/
- function polling(opts) {
+ function polling (opts) {
var xhr;
var xd = false;
var xs = false;
@@ -870,15 +878,15 @@ return /******/ (function(modules) { // webpackBootstrap
}
}
+
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {
- 'use strict';
-
// browser shim for xmlhttprequest module
var hasCORS = __webpack_require__(4);
+ var globalThis = __webpack_require__(5);
module.exports = function (opts) {
var xdomain = opts.xdomain;
@@ -896,7 +904,7 @@ return /******/ (function(modules) { // webpackBootstrap
if ('undefined' !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
return new XMLHttpRequest();
}
- } catch (e) {}
+ } catch (e) { }
// Use XDomainRequest for IE8 if enablesXDR is true
// because loading bar keeps flashing when using jsonp-polling
@@ -905,15 +913,16 @@ return /******/ (function(modules) { // webpackBootstrap
if ('undefined' !== typeof XDomainRequest && !xscheme && enablesXDR) {
return new XDomainRequest();
}
- } catch (e) {}
+ } catch (e) { }
if (!xdomain) {
try {
- return new self[['Active'].concat('Object').join('X')]('Microsoft.XMLHTTP');
- } catch (e) {}
+ return new globalThis[['Active'].concat('Object').join('X')]('Microsoft.XMLHTTP');
+ } catch (e) { }
}
};
+
/***/ },
/* 4 */
/***/ function(module, exports) {
@@ -939,9 +948,22 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
/* 5 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ function(module, exports) {
- 'use strict';
+ module.exports = (function () {
+ if (typeof self !== 'undefined') {
+ return self;
+ } else if (typeof window !== 'undefined') {
+ return window;
+ } else {
+ return Function('return this')(); // eslint-disable-line no-new-func
+ }
+ })();
+
+
+/***/ },
+/* 6 */
+/***/ function(module, exports, __webpack_require__) {
/* global attachEvent */
@@ -950,10 +972,11 @@ return /******/ (function(modules) { // webpackBootstrap
*/
var XMLHttpRequest = __webpack_require__(3);
- var Polling = __webpack_require__(6);
- var Emitter = __webpack_require__(17);
- var inherit = __webpack_require__(19);
- var debug = __webpack_require__(21)('engine.io-client:polling-xhr');
+ var Polling = __webpack_require__(7);
+ var Emitter = __webpack_require__(18);
+ var inherit = __webpack_require__(20);
+ var debug = __webpack_require__(22)('engine.io-client:polling-xhr');
+ var globalThis = __webpack_require__(5);
/**
* Module exports.
@@ -966,7 +989,7 @@ return /******/ (function(modules) { // webpackBootstrap
* Empty function
*/
- function empty() {}
+ function empty () {}
/**
* XHR Polling constructor.
@@ -975,7 +998,7 @@ return /******/ (function(modules) { // webpackBootstrap
* @api public
*/
- function XHR(opts) {
+ function XHR (opts) {
Polling.call(this, opts);
this.requestTimeout = opts.requestTimeout;
this.extraHeaders = opts.extraHeaders;
@@ -989,7 +1012,8 @@ return /******/ (function(modules) { // webpackBootstrap
port = isSSL ? 443 : 80;
}
- this.xd = typeof location !== 'undefined' && opts.hostname !== location.hostname || port !== opts.port;
+ this.xd = (typeof location !== 'undefined' && opts.hostname !== location.hostname) ||
+ port !== opts.port;
this.xs = opts.secure !== isSSL;
}
}
@@ -1021,6 +1045,7 @@ return /******/ (function(modules) { // webpackBootstrap
opts.agent = this.agent || false;
opts.supportsBinary = this.supportsBinary;
opts.enablesXDR = this.enablesXDR;
+ opts.withCredentials = this.withCredentials;
// SSL options for Node.js client
opts.pfx = this.pfx;
@@ -1083,7 +1108,7 @@ return /******/ (function(modules) { // webpackBootstrap
* @api public
*/
- function Request(opts) {
+ function Request (opts) {
this.method = opts.method || 'GET';
this.uri = opts.uri;
this.xd = !!opts.xd;
@@ -1094,6 +1119,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.isBinary = opts.isBinary;
this.supportsBinary = opts.supportsBinary;
this.enablesXDR = opts.enablesXDR;
+ this.withCredentials = opts.withCredentials;
this.requestTimeout = opts.requestTimeout;
// SSL options for Node.js client
@@ -1168,7 +1194,7 @@ return /******/ (function(modules) { // webpackBootstrap
// ie6 check
if ('withCredentials' in xhr) {
- xhr.withCredentials = true;
+ xhr.withCredentials = this.withCredentials;
}
if (this.requestTimeout) {
@@ -1187,7 +1213,7 @@ return /******/ (function(modules) { // webpackBootstrap
if (xhr.readyState === 2) {
try {
var contentType = xhr.getResponseHeader('Content-Type');
- if (self.supportsBinary && contentType === 'application/octet-stream') {
+ if (self.supportsBinary && contentType === 'application/octet-stream' || contentType === 'application/octet-stream; charset=UTF-8') {
xhr.responseType = 'arraybuffer';
}
} catch (e) {}
@@ -1199,7 +1225,7 @@ return /******/ (function(modules) { // webpackBootstrap
// make sure the `error` event handler that's user-set
// does not throw in the same tick and gets caught here
setTimeout(function () {
- self.onError(xhr.status);
+ self.onError(typeof xhr.status === 'number' ? xhr.status : 0);
}, 0);
}
};
@@ -1299,7 +1325,7 @@ return /******/ (function(modules) { // webpackBootstrap
try {
contentType = this.xhr.getResponseHeader('Content-Type');
} catch (e) {}
- if (contentType === 'application/octet-stream') {
+ if (contentType === 'application/octet-stream' || contentType === 'application/octet-stream; charset=UTF-8') {
data = this.xhr.response || this.xhr.responseText;
} else {
data = this.xhr.responseText;
@@ -1345,12 +1371,12 @@ return /******/ (function(modules) { // webpackBootstrap
if (typeof attachEvent === 'function') {
attachEvent('onunload', unloadHandler);
} else if (typeof addEventListener === 'function') {
- var terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';
+ var terminationEvent = 'onpagehide' in globalThis ? 'pagehide' : 'unload';
addEventListener(terminationEvent, unloadHandler, false);
}
}
- function unloadHandler() {
+ function unloadHandler () {
for (var i in Request.requests) {
if (Request.requests.hasOwnProperty(i)) {
Request.requests[i].abort();
@@ -1358,22 +1384,21 @@ return /******/ (function(modules) { // webpackBootstrap
}
}
+
/***/ },
-/* 6 */
+/* 7 */
/***/ function(module, exports, __webpack_require__) {
- 'use strict';
-
/**
* Module dependencies.
*/
- var Transport = __webpack_require__(7);
- var parseqs = __webpack_require__(18);
- var parser = __webpack_require__(8);
- var inherit = __webpack_require__(19);
- var yeast = __webpack_require__(20);
- var debug = __webpack_require__(21)('engine.io-client:polling');
+ var Transport = __webpack_require__(8);
+ var parseqs = __webpack_require__(19);
+ var parser = __webpack_require__(9);
+ var inherit = __webpack_require__(20);
+ var yeast = __webpack_require__(21);
+ var debug = __webpack_require__(22)('engine.io-client:polling');
/**
* Module exports.
@@ -1385,11 +1410,11 @@ return /******/ (function(modules) { // webpackBootstrap
* Is XHR2 supported?
*/
- var hasXHR2 = function () {
+ var hasXHR2 = (function () {
var XMLHttpRequest = __webpack_require__(3);
var xhr = new XMLHttpRequest({ xdomain: false });
return null != xhr.responseType;
- }();
+ })();
/**
* Polling interface.
@@ -1398,8 +1423,8 @@ return /******/ (function(modules) { // webpackBootstrap
* @api private
*/
- function Polling(opts) {
- var forceBase64 = opts && opts.forceBase64;
+ function Polling (opts) {
+ var forceBase64 = (opts && opts.forceBase64);
if (!hasXHR2 || forceBase64) {
this.supportsBinary = false;
}
@@ -1441,7 +1466,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.readyState = 'pausing';
- function pause() {
+ function pause () {
debug('paused');
self.readyState = 'paused';
onPause();
@@ -1494,9 +1519,9 @@ return /******/ (function(modules) { // webpackBootstrap
Polling.prototype.onData = function (data) {
var self = this;
debug('polling got data %s', data);
- var callback = function callback(packet, index, total) {
+ var callback = function (packet, index, total) {
// if its the first message we consider the transport open
- if ('opening' === self.readyState) {
+ if ('opening' === self.readyState && packet.type === 'open') {
self.onOpen();
}
@@ -1536,7 +1561,7 @@ return /******/ (function(modules) { // webpackBootstrap
Polling.prototype.doClose = function () {
var self = this;
- function close() {
+ function close () {
debug('writing close packet');
self.write([{ type: 'close' }]);
}
@@ -1563,7 +1588,7 @@ return /******/ (function(modules) { // webpackBootstrap
Polling.prototype.write = function (packets) {
var self = this;
this.writable = false;
- var callbackfn = function callbackfn() {
+ var callbackfn = function () {
self.writable = true;
self.emit('drain');
};
@@ -1596,7 +1621,8 @@ return /******/ (function(modules) { // webpackBootstrap
query = parseqs.encode(query);
// avoid port if default for schema
- if (this.port && ('https' === schema && Number(this.port) !== 443 || 'http' === schema && Number(this.port) !== 80)) {
+ if (this.port && (('https' === schema && Number(this.port) !== 443) ||
+ ('http' === schema && Number(this.port) !== 80))) {
port = ':' + this.port;
}
@@ -1609,18 +1635,17 @@ return /******/ (function(modules) { // webpackBootstrap
return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query;
};
+
/***/ },
-/* 7 */
+/* 8 */
/***/ function(module, exports, __webpack_require__) {
- 'use strict';
-
/**
* Module dependencies.
*/
- var parser = __webpack_require__(8);
- var Emitter = __webpack_require__(17);
+ var parser = __webpack_require__(9);
+ var Emitter = __webpack_require__(18);
/**
* Module exports.
@@ -1635,7 +1660,7 @@ return /******/ (function(modules) { // webpackBootstrap
* @api private
*/
- function Transport(opts) {
+ function Transport (opts) {
this.path = opts.path;
this.hostname = opts.hostname;
this.port = opts.port;
@@ -1647,6 +1672,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.agent = opts.agent || false;
this.socket = opts.socket;
this.enablesXDR = opts.enablesXDR;
+ this.withCredentials = opts.withCredentials;
// SSL options for Node.js client
this.pfx = opts.pfx;
@@ -1776,23 +1802,24 @@ return /******/ (function(modules) { // webpackBootstrap
this.emit('close');
};
+
/***/ },
-/* 8 */
+/* 9 */
/***/ function(module, exports, __webpack_require__) {
/**
* Module dependencies.
*/
- var keys = __webpack_require__(9);
- var hasBinary = __webpack_require__(10);
- var sliceBuffer = __webpack_require__(12);
- var after = __webpack_require__(13);
- var utf8 = __webpack_require__(14);
+ var keys = __webpack_require__(10);
+ var hasBinary = __webpack_require__(11);
+ var sliceBuffer = __webpack_require__(13);
+ var after = __webpack_require__(14);
+ var utf8 = __webpack_require__(15);
var base64encoder;
if (typeof ArrayBuffer !== 'undefined') {
- base64encoder = __webpack_require__(15);
+ base64encoder = __webpack_require__(16);
}
/**
@@ -1850,7 +1877,7 @@ return /******/ (function(modules) { // webpackBootstrap
* Create a blob api even for blob builder when vendor prefixes exist
*/
- var Blob = __webpack_require__(16);
+ var Blob = __webpack_require__(17);
/**
* Encodes a packet.
@@ -2388,7 +2415,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 9 */
+/* 10 */
/***/ function(module, exports) {
@@ -2413,7 +2440,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 10 */
+/* 11 */
/***/ function(module, exports, __webpack_require__) {
/* global Blob File */
@@ -2422,7 +2449,7 @@ return /******/ (function(modules) { // webpackBootstrap
* Module requirements.
*/
- var isArray = __webpack_require__(11);
+ var isArray = __webpack_require__(12);
var toString = Object.prototype.toString;
var withNativeBlob = typeof Blob === 'function' ||
@@ -2483,7 +2510,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 11 */
+/* 12 */
/***/ function(module, exports) {
var toString = {}.toString;
@@ -2494,7 +2521,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 12 */
+/* 13 */
/***/ function(module, exports) {
/**
@@ -2529,7 +2556,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 13 */
+/* 14 */
/***/ function(module, exports) {
module.exports = after
@@ -2563,7 +2590,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 14 */
+/* 15 */
/***/ function(module, exports) {
/*! https://mths.be/utf8js v2.1.2 by @mathias */
@@ -2779,7 +2806,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 15 */
+/* 16 */
/***/ function(module, exports) {
/*
@@ -2852,7 +2879,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 16 */
+/* 17 */
/***/ function(module, exports) {
/**
@@ -2958,7 +2985,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 17 */
+/* 18 */
/***/ function(module, exports, __webpack_require__) {
@@ -3074,6 +3101,13 @@ return /******/ (function(modules) { // webpackBootstrap
break;
}
}
+
+ // Remove event specific arrays for event types that no
+ // one is subscribed for to avoid memory leak.
+ if (callbacks.length === 0) {
+ delete this._callbacks['$' + event];
+ }
+
return this;
};
@@ -3087,9 +3121,14 @@ return /******/ (function(modules) { // webpackBootstrap
Emitter.prototype.emit = function(event){
this._callbacks = this._callbacks || {};
- var args = [].slice.call(arguments, 1)
+
+ var args = new Array(arguments.length - 1)
, callbacks = this._callbacks['$' + event];
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+
if (callbacks) {
callbacks = callbacks.slice(0);
for (var i = 0, len = callbacks.length; i < len; ++i) {
@@ -3127,7 +3166,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 18 */
+/* 19 */
/***/ function(module, exports) {
/**
@@ -3170,7 +3209,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 19 */
+/* 20 */
/***/ function(module, exports) {
@@ -3182,7 +3221,7 @@ return /******/ (function(modules) { // webpackBootstrap
};
/***/ },
-/* 20 */
+/* 21 */
/***/ function(module, exports) {
'use strict';
@@ -3256,43 +3295,32 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 21 */
+/* 22 */
/***/ function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(process) {/**
+ /* WEBPACK VAR INJECTION */(function(process) {'use strict';
+
+ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+ /**
* This is the web browser implementation of `debug()`.
*
* Expose `debug()` as the module.
*/
- exports = module.exports = __webpack_require__(23);
+ exports = module.exports = __webpack_require__(24);
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
- exports.storage = 'undefined' != typeof chrome
- && 'undefined' != typeof chrome.storage
- ? chrome.storage.local
- : localstorage();
+ exports.storage = 'undefined' != typeof chrome && 'undefined' != typeof chrome.storage ? chrome.storage.local : localstorage();
/**
* Colors.
*/
- exports.colors = [
- '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC',
- '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF',
- '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC',
- '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF',
- '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC',
- '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033',
- '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366',
- '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933',
- '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC',
- '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF',
- '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'
- ];
+ exports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'];
/**
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
@@ -3317,21 +3345,21 @@ return /******/ (function(modules) { // webpackBootstrap
// is webkit? http://stackoverflow.com/a/16459606/376773
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
- return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
- // is firebug? http://stackoverflow.com/a/398120/376773
- (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
- // is firefox >= v31?
- // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
- (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
- // double check webkit in userAgent just in case we are in a worker
- (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
+ return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance ||
+ // is firebug? http://stackoverflow.com/a/398120/376773
+ typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) ||
+ // is firefox >= v31?
+ // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+ typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 ||
+ // double check webkit in userAgent just in case we are in a worker
+ typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
}
/**
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
*/
- exports.formatters.j = function(v) {
+ exports.formatters.j = function (v) {
try {
return JSON.stringify(v);
} catch (err) {
@@ -3339,7 +3367,6 @@ return /******/ (function(modules) { // webpackBootstrap
}
};
-
/**
* Colorize log arguments if enabled.
*
@@ -3349,24 +3376,19 @@ return /******/ (function(modules) { // webpackBootstrap
function formatArgs(args) {
var useColors = this.useColors;
- args[0] = (useColors ? '%c' : '')
- + this.namespace
- + (useColors ? ' %c' : ' ')
- + args[0]
- + (useColors ? '%c ' : ' ')
- + '+' + exports.humanize(this.diff);
+ args[0] = (useColors ? '%c' : '') + this.namespace + (useColors ? ' %c' : ' ') + args[0] + (useColors ? '%c ' : ' ') + '+' + exports.humanize(this.diff);
if (!useColors) return;
var c = 'color: ' + this.color;
- args.splice(1, 0, c, 'color: inherit')
+ args.splice(1, 0, c, 'color: inherit');
// the final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
// figure out the correct index to insert the CSS into
var index = 0;
var lastC = 0;
- args[0].replace(/%[a-zA-Z%]/g, function(match) {
+ args[0].replace(/%[a-zA-Z%]/g, function (match) {
if ('%%' === match) return;
index++;
if ('%c' === match) {
@@ -3389,9 +3411,7 @@ return /******/ (function(modules) { // webpackBootstrap
function log() {
// this hackery is required for IE8/9, where
// the `console.log` function doesn't have 'apply'
- return 'object' === typeof console
- && console.log
- && Function.prototype.apply.call(console.log, console, arguments);
+ return 'object' === (typeof console === 'undefined' ? 'undefined' : _typeof(console)) && console.log && Function.prototype.apply.call(console.log, console, arguments);
}
/**
@@ -3408,7 +3428,7 @@ return /******/ (function(modules) { // webpackBootstrap
} else {
exports.storage.debug = namespaces;
}
- } catch(e) {}
+ } catch (e) {}
}
/**
@@ -3422,7 +3442,7 @@ return /******/ (function(modules) { // webpackBootstrap
var r;
try {
r = exports.storage.debug;
- } catch(e) {}
+ } catch (e) {}
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
if (!r && typeof process !== 'undefined' && 'env' in process) {
@@ -3454,11 +3474,10 @@ return /******/ (function(modules) { // webpackBootstrap
return window.localStorage;
} catch (e) {}
}
-
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(22)))
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(23)))
/***/ },
-/* 22 */
+/* 23 */
/***/ function(module, exports) {
// shim for using process in browser
@@ -3648,10 +3667,11 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 23 */
+/* 24 */
/***/ function(module, exports, __webpack_require__) {
-
+ 'use strict';
+
/**
* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
@@ -3664,7 +3684,7 @@ return /******/ (function(modules) { // webpackBootstrap
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
- exports.humanize = __webpack_require__(24);
+ exports.humanize = __webpack_require__(25);
/**
* Active `debug` instances.
@@ -3694,10 +3714,11 @@ return /******/ (function(modules) { // webpackBootstrap
*/
function selectColor(namespace) {
- var hash = 0, i;
+ var hash = 0,
+ i;
for (i in namespace) {
- hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
+ hash = (hash << 5) - hash + namespace.charCodeAt(i);
hash |= 0; // Convert to 32bit integer
}
@@ -3745,7 +3766,7 @@ return /******/ (function(modules) { // webpackBootstrap
// apply any `formatters` transformations
var index = 0;
- args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
+ args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) {
// if we encounter an escaped % then don't increase the array index
if (match === '%%') return match;
index++;
@@ -3784,7 +3805,7 @@ return /******/ (function(modules) { // webpackBootstrap
return debug;
}
- function destroy () {
+ function destroy() {
var index = exports.instances.indexOf(this);
if (index !== -1) {
exports.instances.splice(index, 1);
@@ -3877,9 +3898,8 @@ return /******/ (function(modules) { // webpackBootstrap
return val;
}
-
/***/ },
-/* 24 */
+/* 25 */
/***/ function(module, exports) {
/**
@@ -4037,17 +4057,16 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 25 */
+/* 26 */
/***/ function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(global) {'use strict';
-
/**
* Module requirements.
*/
- var Polling = __webpack_require__(6);
- var inherit = __webpack_require__(19);
+ var Polling = __webpack_require__(7);
+ var inherit = __webpack_require__(20);
+ var globalThis = __webpack_require__(5);
/**
* Module exports.
@@ -4072,14 +4091,7 @@ return /******/ (function(modules) { // webpackBootstrap
* Noop.
*/
- function empty() {}
-
- /**
- * Until https://github.com/tc39/proposal-global is shipped.
- */
- function glob() {
- return typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : {};
- }
+ function empty () { }
/**
* JSONP Polling constructor.
@@ -4088,7 +4100,7 @@ return /******/ (function(modules) { // webpackBootstrap
* @api public
*/
- function JSONPPolling(opts) {
+ function JSONPPolling (opts) {
Polling.call(this, opts);
this.query = this.query || {};
@@ -4097,8 +4109,7 @@ return /******/ (function(modules) { // webpackBootstrap
// we do this here (lazily) to avoid unneeded global pollution
if (!callbacks) {
// we need to consider multiple engines in the same page
- var global = glob();
- callbacks = global.___eio = global.___eio || [];
+ callbacks = globalThis.___eio = (globalThis.___eio || []);
}
// callback identifier
@@ -4228,12 +4239,12 @@ return /******/ (function(modules) { // webpackBootstrap
this.form.action = this.uri();
- function complete() {
+ function complete () {
initIframe();
fn();
}
- function initIframe() {
+ function initIframe () {
if (self.iframe) {
try {
self.form.removeChild(self.iframe);
@@ -4279,24 +4290,22 @@ return /******/ (function(modules) { // webpackBootstrap
this.iframe.onload = complete;
}
};
- /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
+
/***/ },
-/* 26 */
+/* 27 */
/***/ function(module, exports, __webpack_require__) {
- 'use strict';
-
/**
* Module dependencies.
*/
- var Transport = __webpack_require__(7);
- var parser = __webpack_require__(8);
- var parseqs = __webpack_require__(18);
- var inherit = __webpack_require__(19);
- var yeast = __webpack_require__(20);
- var debug = __webpack_require__(21)('engine.io-client:websocket');
+ var Transport = __webpack_require__(8);
+ var parser = __webpack_require__(9);
+ var parseqs = __webpack_require__(19);
+ var inherit = __webpack_require__(20);
+ var yeast = __webpack_require__(21);
+ var debug = __webpack_require__(22)('engine.io-client:websocket');
var BrowserWebSocket, NodeWebSocket;
@@ -4304,10 +4313,12 @@ return /******/ (function(modules) { // webpackBootstrap
BrowserWebSocket = WebSocket;
} else if (typeof self !== 'undefined') {
BrowserWebSocket = self.WebSocket || self.MozWebSocket;
- } else {
+ }
+
+ if (typeof window === 'undefined') {
try {
- NodeWebSocket = __webpack_require__(27);
- } catch (e) {}
+ NodeWebSocket = __webpack_require__(28);
+ } catch (e) { }
}
/**
@@ -4331,8 +4342,8 @@ return /******/ (function(modules) { // webpackBootstrap
* @api public
*/
- function WS(opts) {
- var forceBase64 = opts && opts.forceBase64;
+ function WS (opts) {
+ var forceBase64 = (opts && opts.forceBase64);
if (forceBase64) {
this.supportsBinary = false;
}
@@ -4379,19 +4390,23 @@ return /******/ (function(modules) { // webpackBootstrap
var uri = this.uri();
var protocols = this.protocols;
- var opts = {
- agent: this.agent,
- perMessageDeflate: this.perMessageDeflate
- };
- // SSL options for Node.js client
- opts.pfx = this.pfx;
- opts.key = this.key;
- opts.passphrase = this.passphrase;
- opts.cert = this.cert;
- opts.ca = this.ca;
- opts.ciphers = this.ciphers;
- opts.rejectUnauthorized = this.rejectUnauthorized;
+ var opts = {};
+
+ if (!this.isReactNative) {
+ opts.agent = this.agent;
+ opts.perMessageDeflate = this.perMessageDeflate;
+
+ // SSL options for Node.js client
+ opts.pfx = this.pfx;
+ opts.key = this.key;
+ opts.passphrase = this.passphrase;
+ opts.cert = this.cert;
+ opts.ca = this.ca;
+ opts.ciphers = this.ciphers;
+ opts.rejectUnauthorized = this.rejectUnauthorized;
+ }
+
if (this.extraHeaders) {
opts.headers = this.extraHeaders;
}
@@ -4400,7 +4415,12 @@ return /******/ (function(modules) { // webpackBootstrap
}
try {
- this.ws = this.usingBrowserWebSocket && !this.isReactNative ? protocols ? new WebSocketImpl(uri, protocols) : new WebSocketImpl(uri) : new WebSocketImpl(uri, protocols, opts);
+ this.ws =
+ this.usingBrowserWebSocket && !this.isReactNative
+ ? protocols
+ ? new WebSocketImpl(uri, protocols)
+ : new WebSocketImpl(uri)
+ : new WebSocketImpl(uri, protocols, opts);
} catch (err) {
return this.emit('error', err);
}
@@ -4493,7 +4513,7 @@ return /******/ (function(modules) { // webpackBootstrap
})(packets[i]);
}
- function done() {
+ function done () {
self.emit('flush');
// fake drain
@@ -4539,7 +4559,8 @@ return /******/ (function(modules) { // webpackBootstrap
var port = '';
// avoid port if default for schema
- if (this.port && ('wss' === schema && Number(this.port) !== 443 || 'ws' === schema && Number(this.port) !== 80)) {
+ if (this.port && (('wss' === schema && Number(this.port) !== 443) ||
+ ('ws' === schema && Number(this.port) !== 80))) {
port = ':' + this.port;
}
@@ -4575,14 +4596,15 @@ return /******/ (function(modules) { // webpackBootstrap
return !!WebSocketImpl && !('__initialize' in WebSocketImpl && this.name === WS.prototype.name);
};
+
/***/ },
-/* 27 */
+/* 28 */
/***/ function(module, exports) {
/* (ignored) */
/***/ },
-/* 28 */
+/* 29 */
/***/ function(module, exports) {
@@ -4597,7 +4619,7 @@ return /******/ (function(modules) { // webpackBootstrap
};
/***/ },
-/* 29 */
+/* 30 */
/***/ function(module, exports) {
/**
@@ -4637,9 +4659,38 @@ return /******/ (function(modules) { // webpackBootstrap
uri.ipv6uri = true;
}
+ uri.pathNames = pathNames(uri, uri['path']);
+ uri.queryKey = queryKey(uri, uri['query']);
+
return uri;
};
+ function pathNames(obj, path) {
+ var regx = /\/{2,9}/g,
+ names = path.replace(regx, "/").split("/");
+
+ if (path.substr(0, 1) == '/' || path.length === 0) {
+ names.splice(0, 1);
+ }
+ if (path.substr(path.length - 1, 1) == '/') {
+ names.splice(names.length - 1, 1);
+ }
+
+ return names;
+ }
+
+ function queryKey(uri, query) {
+ var data = {};
+
+ query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {
+ if ($1) {
+ data[$1] = $2;
+ }
+ });
+
+ return data;
+ }
+
/***/ }
/******/ ])
diff --git a/node_modules/engine.io-client/lib/globalThis.browser.js b/node_modules/engine.io-client/lib/globalThis.browser.js
new file mode 100644
index 0000000..11b0f28
--- /dev/null
+++ b/node_modules/engine.io-client/lib/globalThis.browser.js
@@ -0,0 +1,9 @@
+module.exports = (function () {
+ if (typeof self !== 'undefined') {
+ return self;
+ } else if (typeof window !== 'undefined') {
+ return window;
+ } else {
+ return Function('return this')(); // eslint-disable-line no-new-func
+ }
+})();
diff --git a/node_modules/engine.io-client/lib/globalThis.js b/node_modules/engine.io-client/lib/globalThis.js
new file mode 100644
index 0000000..e1465f2
--- /dev/null
+++ b/node_modules/engine.io-client/lib/globalThis.js
@@ -0,0 +1 @@
+module.exports = global;
diff --git a/node_modules/engine.io-client/lib/socket.js b/node_modules/engine.io-client/lib/socket.js
index 0800a1a..8a67cfa 100755
--- a/node_modules/engine.io-client/lib/socket.js
+++ b/node_modules/engine.io-client/lib/socket.js
@@ -66,6 +66,7 @@ function Socket (uri, opts) {
this.jsonp = false !== opts.jsonp;
this.forceBase64 = !!opts.forceBase64;
this.enablesXDR = !!opts.enablesXDR;
+ this.withCredentials = false !== opts.withCredentials;
this.timestampParam = opts.timestampParam || 't';
this.timestampRequests = opts.timestampRequests;
this.transports = opts.transports || ['polling', 'websocket'];
@@ -183,6 +184,7 @@ Socket.prototype.createTransport = function (name) {
jsonp: options.jsonp || this.jsonp,
forceBase64: options.forceBase64 || this.forceBase64,
enablesXDR: options.enablesXDR || this.enablesXDR,
+ withCredentials: options.withCredentials || this.withCredentials,
timestampRequests: options.timestampRequests || this.timestampRequests,
timestampParam: options.timestampParam || this.timestampParam,
policyPort: options.policyPort || this.policyPort,
diff --git a/node_modules/engine.io-client/lib/transport.js b/node_modules/engine.io-client/lib/transport.js
index fb043c7..9ed5a35 100755
--- a/node_modules/engine.io-client/lib/transport.js
+++ b/node_modules/engine.io-client/lib/transport.js
@@ -30,6 +30,7 @@ function Transport (opts) {
this.agent = opts.agent || false;
this.socket = opts.socket;
this.enablesXDR = opts.enablesXDR;
+ this.withCredentials = opts.withCredentials;
// SSL options for Node.js client
this.pfx = opts.pfx;
diff --git a/node_modules/engine.io-client/lib/transports/polling-jsonp.js b/node_modules/engine.io-client/lib/transports/polling-jsonp.js
index 8e69337..fe65705 100755
--- a/node_modules/engine.io-client/lib/transports/polling-jsonp.js
+++ b/node_modules/engine.io-client/lib/transports/polling-jsonp.js
@@ -4,6 +4,7 @@
var Polling = require('./polling');
var inherit = require('component-inherit');
+var globalThis = require('../globalThis');
/**
* Module exports.
@@ -30,15 +31,6 @@ var callbacks;
function empty () { }
-/**
- * Until https://github.com/tc39/proposal-global is shipped.
- */
-function glob () {
- return typeof self !== 'undefined' ? self
- : typeof window !== 'undefined' ? window
- : typeof global !== 'undefined' ? global : {};
-}
-
/**
* JSONP Polling constructor.
*
@@ -55,8 +47,7 @@ function JSONPPolling (opts) {
// we do this here (lazily) to avoid unneeded global pollution
if (!callbacks) {
// we need to consider multiple engines in the same page
- var global = glob();
- callbacks = global.___eio = (global.___eio || []);
+ callbacks = globalThis.___eio = (globalThis.___eio || []);
}
// callback identifier
diff --git a/node_modules/engine.io-client/lib/transports/polling-xhr.js b/node_modules/engine.io-client/lib/transports/polling-xhr.js
index cc16d9d..43f529c 100755
--- a/node_modules/engine.io-client/lib/transports/polling-xhr.js
+++ b/node_modules/engine.io-client/lib/transports/polling-xhr.js
@@ -9,6 +9,7 @@ var Polling = require('./polling');
var Emitter = require('component-emitter');
var inherit = require('component-inherit');
var debug = require('debug')('engine.io-client:polling-xhr');
+var globalThis = require('../globalThis');
/**
* Module exports.
@@ -77,6 +78,7 @@ XHR.prototype.request = function (opts) {
opts.agent = this.agent || false;
opts.supportsBinary = this.supportsBinary;
opts.enablesXDR = this.enablesXDR;
+ opts.withCredentials = this.withCredentials;
// SSL options for Node.js client
opts.pfx = this.pfx;
@@ -150,6 +152,7 @@ function Request (opts) {
this.isBinary = opts.isBinary;
this.supportsBinary = opts.supportsBinary;
this.enablesXDR = opts.enablesXDR;
+ this.withCredentials = opts.withCredentials;
this.requestTimeout = opts.requestTimeout;
// SSL options for Node.js client
@@ -224,7 +227,7 @@ Request.prototype.create = function () {
// ie6 check
if ('withCredentials' in xhr) {
- xhr.withCredentials = true;
+ xhr.withCredentials = this.withCredentials;
}
if (this.requestTimeout) {
@@ -243,7 +246,7 @@ Request.prototype.create = function () {
if (xhr.readyState === 2) {
try {
var contentType = xhr.getResponseHeader('Content-Type');
- if (self.supportsBinary && contentType === 'application/octet-stream') {
+ if (self.supportsBinary && contentType === 'application/octet-stream' || contentType === 'application/octet-stream; charset=UTF-8') {
xhr.responseType = 'arraybuffer';
}
} catch (e) {}
@@ -255,7 +258,7 @@ Request.prototype.create = function () {
// make sure the `error` event handler that's user-set
// does not throw in the same tick and gets caught here
setTimeout(function () {
- self.onError(xhr.status);
+ self.onError(typeof xhr.status === 'number' ? xhr.status : 0);
}, 0);
}
};
@@ -355,7 +358,7 @@ Request.prototype.onLoad = function () {
try {
contentType = this.xhr.getResponseHeader('Content-Type');
} catch (e) {}
- if (contentType === 'application/octet-stream') {
+ if (contentType === 'application/octet-stream' || contentType === 'application/octet-stream; charset=UTF-8') {
data = this.xhr.response || this.xhr.responseText;
} else {
data = this.xhr.responseText;
@@ -401,7 +404,7 @@ if (typeof document !== 'undefined') {
if (typeof attachEvent === 'function') {
attachEvent('onunload', unloadHandler);
} else if (typeof addEventListener === 'function') {
- var terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';
+ var terminationEvent = 'onpagehide' in globalThis ? 'pagehide' : 'unload';
addEventListener(terminationEvent, unloadHandler, false);
}
}
diff --git a/node_modules/engine.io-client/lib/transports/polling.js b/node_modules/engine.io-client/lib/transports/polling.js
index 970313e..786398b 100755
--- a/node_modules/engine.io-client/lib/transports/polling.js
+++ b/node_modules/engine.io-client/lib/transports/polling.js
@@ -130,7 +130,7 @@ Polling.prototype.onData = function (data) {
debug('polling got data %s', data);
var callback = function (packet, index, total) {
// if its the first message we consider the transport open
- if ('opening' === self.readyState) {
+ if ('opening' === self.readyState && packet.type === 'open') {
self.onOpen();
}
diff --git a/node_modules/engine.io-client/lib/transports/websocket.js b/node_modules/engine.io-client/lib/transports/websocket.js
index 4964fd5..f9c4b7a 100755
--- a/node_modules/engine.io-client/lib/transports/websocket.js
+++ b/node_modules/engine.io-client/lib/transports/websocket.js
@@ -15,7 +15,9 @@ if (typeof WebSocket !== 'undefined') {
BrowserWebSocket = WebSocket;
} else if (typeof self !== 'undefined') {
BrowserWebSocket = self.WebSocket || self.MozWebSocket;
-} else {
+}
+
+if (typeof window === 'undefined') {
try {
NodeWebSocket = require('ws');
} catch (e) { }
@@ -90,19 +92,23 @@ WS.prototype.doOpen = function () {
var uri = this.uri();
var protocols = this.protocols;
- var opts = {
- agent: this.agent,
- perMessageDeflate: this.perMessageDeflate
- };
- // SSL options for Node.js client
- opts.pfx = this.pfx;
- opts.key = this.key;
- opts.passphrase = this.passphrase;
- opts.cert = this.cert;
- opts.ca = this.ca;
- opts.ciphers = this.ciphers;
- opts.rejectUnauthorized = this.rejectUnauthorized;
+ var opts = {};
+
+ if (!this.isReactNative) {
+ opts.agent = this.agent;
+ opts.perMessageDeflate = this.perMessageDeflate;
+
+ // SSL options for Node.js client
+ opts.pfx = this.pfx;
+ opts.key = this.key;
+ opts.passphrase = this.passphrase;
+ opts.cert = this.cert;
+ opts.ca = this.ca;
+ opts.ciphers = this.ciphers;
+ opts.rejectUnauthorized = this.rejectUnauthorized;
+ }
+
if (this.extraHeaders) {
opts.headers = this.extraHeaders;
}
diff --git a/node_modules/engine.io-client/lib/xmlhttprequest.js b/node_modules/engine.io-client/lib/xmlhttprequest.js
index 1413e63..9d078c1 100755
--- a/node_modules/engine.io-client/lib/xmlhttprequest.js
+++ b/node_modules/engine.io-client/lib/xmlhttprequest.js
@@ -1,6 +1,7 @@
// browser shim for xmlhttprequest module
var hasCORS = require('has-cors');
+var globalThis = require('./globalThis');
module.exports = function (opts) {
var xdomain = opts.xdomain;
@@ -31,7 +32,7 @@ module.exports = function (opts) {
if (!xdomain) {
try {
- return new self[['Active'].concat('Object').join('X')]('Microsoft.XMLHTTP');
+ return new globalThis[['Active'].concat('Object').join('X')]('Microsoft.XMLHTTP');
} catch (e) { }
}
};
diff --git a/node_modules/engine.io-client/node_modules/component-emitter/History.md b/node_modules/engine.io-client/node_modules/component-emitter/History.md
new file mode 100644
index 0000000..e9fb4bc
--- /dev/null
+++ b/node_modules/engine.io-client/node_modules/component-emitter/History.md
@@ -0,0 +1,75 @@
+
+1.3.0 / 2018-04-15
+==================
+
+ * removed bower support
+ * expose emitter on `exports`
+ * prevent de-optimization from using `arguments`
+
+1.2.1 / 2016-04-18
+==================
+
+ * enable client side use
+
+1.2.0 / 2014-02-12
+==================
+
+ * prefix events with `$` to support object prototype method names
+
+1.1.3 / 2014-06-20
+==================
+
+ * republish for npm
+ * add LICENSE file
+
+1.1.2 / 2014-02-10
+==================
+
+ * package: rename to "component-emitter"
+ * package: update "main" and "component" fields
+ * Add license to Readme (same format as the other components)
+ * created .npmignore
+ * travis stuff
+
+1.1.1 / 2013-12-01
+==================
+
+ * fix .once adding .on to the listener
+ * docs: Emitter#off()
+ * component: add `.repo` prop
+
+1.1.0 / 2013-10-20
+==================
+
+ * add `.addEventListener()` and `.removeEventListener()` aliases
+
+1.0.1 / 2013-06-27
+==================
+
+ * add support for legacy ie
+
+1.0.0 / 2013-02-26
+==================
+
+ * add `.off()` support for removing all listeners
+
+0.0.6 / 2012-10-08
+==================
+
+ * add `this._callbacks` initialization to prevent funky gotcha
+
+0.0.5 / 2012-09-07
+==================
+
+ * fix `Emitter.call(this)` usage
+
+0.0.3 / 2012-07-11
+==================
+
+ * add `.listeners()`
+ * rename `.has()` to `.hasListeners()`
+
+0.0.2 / 2012-06-28
+==================
+
+ * fix `.off()` with `.once()`-registered callbacks
diff --git a/node_modules/engine.io-client/node_modules/component-emitter/LICENSE b/node_modules/engine.io-client/node_modules/component-emitter/LICENSE
new file mode 100644
index 0000000..de51692
--- /dev/null
+++ b/node_modules/engine.io-client/node_modules/component-emitter/LICENSE
@@ -0,0 +1,24 @@
+(The MIT License)
+
+Copyright (c) 2014 Component contributors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/engine.io-client/node_modules/component-emitter/Readme.md b/node_modules/engine.io-client/node_modules/component-emitter/Readme.md
new file mode 100644
index 0000000..0f3f9b9
--- /dev/null
+++ b/node_modules/engine.io-client/node_modules/component-emitter/Readme.md
@@ -0,0 +1,74 @@
+# Emitter [![Build Status](https://travis-ci.org/component/emitter.png)](https://travis-ci.org/component/emitter)
+
+ Event emitter component.
+
+## Installation
+
+```
+$ component install component/emitter
+```
+
+## API
+
+### Emitter(obj)
+
+ The `Emitter` may also be used as a mixin. For example
+ a "plain" object may become an emitter, or you may
+ extend an existing prototype.
+
+ As an `Emitter` instance:
+
+```js
+var Emitter = require('emitter');
+var emitter = new Emitter;
+emitter.emit('something');
+```
+
+ As a mixin:
+
+```js
+var Emitter = require('emitter');
+var user = { name: 'tobi' };
+Emitter(user);
+
+user.emit('im a user');
+```
+
+ As a prototype mixin:
+
+```js
+var Emitter = require('emitter');
+Emitter(User.prototype);
+```
+
+### Emitter#on(event, fn)
+
+ Register an `event` handler `fn`.
+
+### Emitter#once(event, fn)
+
+ Register a single-shot `event` handler `fn`,
+ removed immediately after it is invoked the
+ first time.
+
+### Emitter#off(event, fn)
+
+ * Pass `event` and `fn` to remove a listener.
+ * Pass `event` to remove all listeners on that event.
+ * Pass nothing to remove all listeners on all events.
+
+### Emitter#emit(event, ...)
+
+ Emit an `event` with variable option args.
+
+### Emitter#listeners(event)
+
+ Return an array of callbacks, or an empty array.
+
+### Emitter#hasListeners(event)
+
+ Check if this emitter has `event` handlers.
+
+## License
+
+MIT
diff --git a/node_modules/engine.io-client/node_modules/component-emitter/index.js b/node_modules/engine.io-client/node_modules/component-emitter/index.js
new file mode 100644
index 0000000..6d7ed0a
--- /dev/null
+++ b/node_modules/engine.io-client/node_modules/component-emitter/index.js
@@ -0,0 +1,175 @@
+
+/**
+ * Expose `Emitter`.
+ */
+
+if (typeof module !== 'undefined') {
+ module.exports = Emitter;
+}
+
+/**
+ * Initialize a new `Emitter`.
+ *
+ * @api public
+ */
+
+function Emitter(obj) {
+ if (obj) return mixin(obj);
+};
+
+/**
+ * Mixin the emitter properties.
+ *
+ * @param {Object} obj
+ * @return {Object}
+ * @api private
+ */
+
+function mixin(obj) {
+ for (var key in Emitter.prototype) {
+ obj[key] = Emitter.prototype[key];
+ }
+ return obj;
+}
+
+/**
+ * Listen on the given `event` with `fn`.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+Emitter.prototype.on =
+Emitter.prototype.addEventListener = function(event, fn){
+ this._callbacks = this._callbacks || {};
+ (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
+ .push(fn);
+ return this;
+};
+
+/**
+ * Adds an `event` listener that will be invoked a single
+ * time then automatically removed.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+Emitter.prototype.once = function(event, fn){
+ function on() {
+ this.off(event, on);
+ fn.apply(this, arguments);
+ }
+
+ on.fn = fn;
+ this.on(event, on);
+ return this;
+};
+
+/**
+ * Remove the given callback for `event` or all
+ * registered callbacks.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+Emitter.prototype.off =
+Emitter.prototype.removeListener =
+Emitter.prototype.removeAllListeners =
+Emitter.prototype.removeEventListener = function(event, fn){
+ this._callbacks = this._callbacks || {};
+
+ // all
+ if (0 == arguments.length) {
+ this._callbacks = {};
+ return this;
+ }
+
+ // specific event
+ var callbacks = this._callbacks['$' + event];
+ if (!callbacks) return this;
+
+ // remove all handlers
+ if (1 == arguments.length) {
+ delete this._callbacks['$' + event];
+ return this;
+ }
+
+ // remove specific handler
+ var cb;
+ for (var i = 0; i < callbacks.length; i++) {
+ cb = callbacks[i];
+ if (cb === fn || cb.fn === fn) {
+ callbacks.splice(i, 1);
+ break;
+ }
+ }
+
+ // Remove event specific arrays for event types that no
+ // one is subscribed for to avoid memory leak.
+ if (callbacks.length === 0) {
+ delete this._callbacks['$' + event];
+ }
+
+ return this;
+};
+
+/**
+ * Emit `event` with the given args.
+ *
+ * @param {String} event
+ * @param {Mixed} ...
+ * @return {Emitter}
+ */
+
+Emitter.prototype.emit = function(event){
+ this._callbacks = this._callbacks || {};
+
+ var args = new Array(arguments.length - 1)
+ , callbacks = this._callbacks['$' + event];
+
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+
+ if (callbacks) {
+ callbacks = callbacks.slice(0);
+ for (var i = 0, len = callbacks.length; i < len; ++i) {
+ callbacks[i].apply(this, args);
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Return array of callbacks for `event`.
+ *
+ * @param {String} event
+ * @return {Array}
+ * @api public
+ */
+
+Emitter.prototype.listeners = function(event){
+ this._callbacks = this._callbacks || {};
+ return this._callbacks['$' + event] || [];
+};
+
+/**
+ * Check if this emitter has `event` handlers.
+ *
+ * @param {String} event
+ * @return {Boolean}
+ * @api public
+ */
+
+Emitter.prototype.hasListeners = function(event){
+ return !! this.listeners(event).length;
+};
diff --git a/node_modules/engine.io-client/node_modules/component-emitter/package.json b/node_modules/engine.io-client/node_modules/component-emitter/package.json
new file mode 100644
index 0000000..0375fcf
--- /dev/null
+++ b/node_modules/engine.io-client/node_modules/component-emitter/package.json
@@ -0,0 +1,56 @@
+{
+ "_from": "component-emitter@~1.3.0",
+ "_id": "component-emitter@1.3.0",
+ "_inBundle": false,
+ "_integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+ "_location": "/engine.io-client/component-emitter",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "range",
+ "registry": true,
+ "raw": "component-emitter@~1.3.0",
+ "name": "component-emitter",
+ "escapedName": "component-emitter",
+ "rawSpec": "~1.3.0",
+ "saveSpec": null,
+ "fetchSpec": "~1.3.0"
+ },
+ "_requiredBy": [
+ "/engine.io-client"
+ ],
+ "_resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "_shasum": "16e4070fba8ae29b679f2215853ee181ab2eabc0",
+ "_spec": "component-emitter@~1.3.0",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\engine.io-client",
+ "bugs": {
+ "url": "https://github.com/component/emitter/issues"
+ },
+ "bundleDependencies": false,
+ "component": {
+ "scripts": {
+ "emitter/index.js": "index.js"
+ }
+ },
+ "deprecated": false,
+ "description": "Event emitter",
+ "devDependencies": {
+ "mocha": "*",
+ "should": "*"
+ },
+ "files": [
+ "index.js",
+ "LICENSE"
+ ],
+ "homepage": "https://github.com/component/emitter#readme",
+ "license": "MIT",
+ "main": "index.js",
+ "name": "component-emitter",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/component/emitter.git"
+ },
+ "scripts": {
+ "test": "make test"
+ },
+ "version": "1.3.0"
+}
diff --git a/node_modules/engine.io-client/package.json b/node_modules/engine.io-client/package.json
index c41f568..e8e60c0 100755
--- a/node_modules/engine.io-client/package.json
+++ b/node_modules/engine.io-client/package.json
@@ -1,8 +1,8 @@
{
- "_from": "engine.io-client@~3.3.1",
- "_id": "engine.io-client@3.3.2",
+ "_from": "engine.io-client@~3.5.0",
+ "_id": "engine.io-client@3.5.0",
"_inBundle": false,
- "_integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==",
+ "_integrity": "sha512-12wPRfMrugVw/DNyJk34GQ5vIVArEcVMXWugQGGuw2XxUSztFNmJggZmv8IZlLyEdnpO1QB9LkcjeWewO2vxtA==",
"_location": "/engine.io-client",
"_phantomChildren": {
"ms": "2.0.0"
@@ -10,23 +10,24 @@
"_requested": {
"type": "range",
"registry": true,
- "raw": "engine.io-client@~3.3.1",
+ "raw": "engine.io-client@~3.5.0",
"name": "engine.io-client",
"escapedName": "engine.io-client",
- "rawSpec": "~3.3.1",
+ "rawSpec": "~3.5.0",
"saveSpec": null,
- "fetchSpec": "~3.3.1"
+ "fetchSpec": "~3.5.0"
},
"_requiredBy": [
"/socket.io-client"
],
- "_resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz",
- "_shasum": "04e068798d75beda14375a264bb3d742d7bc33aa",
- "_spec": "engine.io-client@~3.3.1",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/socket.io-client",
+ "_resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.0.tgz",
+ "_shasum": "fc1b4d9616288ce4f2daf06dcf612413dec941c7",
+ "_spec": "engine.io-client@~3.5.0",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\socket.io-client",
"browser": {
"ws": false,
- "xmlhttprequest-ssl": "./lib/xmlhttprequest.js"
+ "xmlhttprequest-ssl": "./lib/xmlhttprequest.js",
+ "./lib/globalThis.js": "./lib/globalThis.browser.js"
},
"bugs": {
"url": "https://github.com/socketio/engine.io-client/issues"
@@ -51,15 +52,15 @@
}
],
"dependencies": {
- "component-emitter": "1.2.1",
+ "component-emitter": "~1.3.0",
"component-inherit": "0.0.3",
"debug": "~3.1.0",
- "engine.io-parser": "~2.1.1",
+ "engine.io-parser": "~2.2.0",
"has-cors": "1.1.0",
"indexof": "0.0.1",
- "parseqs": "0.0.5",
- "parseuri": "0.0.5",
- "ws": "~6.1.0",
+ "parseqs": "0.0.6",
+ "parseuri": "0.0.6",
+ "ws": "~7.4.2",
"xmlhttprequest-ssl": "~1.5.4",
"yeast": "0.1.2"
},
@@ -74,7 +75,7 @@
"concat-stream": "^1.6.0",
"del": "^2.2.2",
"derequire": "^2.0.6",
- "engine.io": "3.3.1",
+ "engine.io": "3.4.0",
"eslint-config-standard": "4.4.0",
"eslint-plugin-standard": "1.3.1",
"expect.js": "^0.3.1",
@@ -109,5 +110,5 @@
"scripts": {
"test": "gulp test"
},
- "version": "3.3.2"
+ "version": "3.5.0"
}
diff --git a/node_modules/engine.io-parser/CHANGELOG.md b/node_modules/engine.io-parser/CHANGELOG.md
new file mode 100644
index 0000000..a442aeb
--- /dev/null
+++ b/node_modules/engine.io-parser/CHANGELOG.md
@@ -0,0 +1 @@
+## [2.2.1](https://github.com/socketio/engine.io-parser/compare/2.2.0...2.2.1) (2020-09-30)
diff --git a/node_modules/engine.io-parser/Readme.md b/node_modules/engine.io-parser/Readme.md
index 02bf538..97326bb 100755
--- a/node_modules/engine.io-parser/Readme.md
+++ b/node_modules/engine.io-parser/Readme.md
@@ -1,8 +1,8 @@
# engine.io-parser
-[![Build Status](https://secure.travis-ci.org/socketio/engine.io-parser.svg)](http://travis-ci.org/socketio/engine.io-parser)
-[![NPM version](https://badge.fury.io/js/engine.io-parser.svg)](http://badge.fury.io/js/engine.io-parser)
+[![Build Status](https://secure.travis-ci.org/socketio/engine.io-parser.svg?branch=master)](https://travis-ci.org/socketio/engine.io-parser)
+[![NPM version](https://badge.fury.io/js/engine.io-parser.svg)](https://npmjs.com/package/engine.io-parser)
This is the JavaScript parser for the engine.io protocol encoding,
shared by both
diff --git a/node_modules/engine.io-parser/lib/index.js b/node_modules/engine.io-parser/lib/index.js
index 4d9029b..5df4df2 100755
--- a/node_modules/engine.io-parser/lib/index.js
+++ b/node_modules/engine.io-parser/lib/index.js
@@ -34,6 +34,8 @@ var packetslist = keys(packets);
var err = { type: 'error', data: 'parser error' };
+const EMPTY_BUFFER = Buffer.concat([]);
+
/**
* Encodes a packet.
*
@@ -88,7 +90,7 @@ function encodeBuffer(packet, supportsBinary, callback) {
}
var data = packet.data;
- var typeBuffer = new Buffer(1);
+ var typeBuffer = Buffer.allocUnsafe(1);
typeBuffer[0] = packets[packet.type];
return callback(Buffer.concat([typeBuffer, data]));
}
@@ -181,7 +183,7 @@ function tryDecode(data) {
exports.decodeBase64Packet = function(msg, binaryType) {
var type = packetslist[msg.charAt(0)];
- var data = new Buffer(msg.substr(1), 'base64');
+ var data = Buffer.from(msg.substr(1), 'base64');
if (binaryType === 'arraybuffer') {
var abv = new Uint8Array(data.length);
for (var i = 0; i < abv.length; i++){
@@ -345,7 +347,7 @@ function bufferToString(buffer) {
*/
function stringToBuffer(string) {
- var buf = new Buffer(string.length);
+ var buf = Buffer.allocUnsafe(string.length);
for (var i = 0, l = string.length; i < l; i++) {
buf.writeUInt8(string.charCodeAt(i), i);
}
@@ -361,15 +363,10 @@ function stringToBuffer(string) {
function arrayBufferToBuffer(data) {
// data is either an ArrayBuffer or ArrayBufferView.
- var array = new Uint8Array(data.buffer || data);
var length = data.byteLength || data.length;
var offset = data.byteOffset || 0;
- var buffer = new Buffer(length);
- for (var i = 0; i < length; i++) {
- buffer[i] = array[offset + i];
- }
- return buffer;
+ return Buffer.from(data.buffer || data, offset, length);
}
/**
@@ -388,7 +385,7 @@ function arrayBufferToBuffer(data) {
exports.encodePayloadAsBinary = function (packets, callback) {
if (!packets.length) {
- return callback(new Buffer(0));
+ return callback(EMPTY_BUFFER);
}
map(packets, encodeOneBinaryPacket, function(err, results) {
@@ -404,7 +401,7 @@ function encodeOneBinaryPacket(p, doneCallback) {
var sizeBuffer;
if (typeof packet === 'string') {
- sizeBuffer = new Buffer(encodingLength.length + 2);
+ sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
sizeBuffer[0] = 0; // is a string (not true binary = 0)
for (var i = 0; i < encodingLength.length; i++) {
sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
@@ -413,7 +410,7 @@ function encodeOneBinaryPacket(p, doneCallback) {
return doneCallback(null, Buffer.concat([sizeBuffer, stringToBuffer(packet)]));
}
- sizeBuffer = new Buffer(encodingLength.length + 2);
+ sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
sizeBuffer[0] = 1; // is binary (true binary = 1)
for (var i = 0; i < encodingLength.length; i++) {
sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
diff --git a/node_modules/engine.io-parser/package.json b/node_modules/engine.io-parser/package.json
index 881dbb9..fe318b5 100755
--- a/node_modules/engine.io-parser/package.json
+++ b/node_modules/engine.io-parser/package.json
@@ -1,28 +1,28 @@
{
- "_from": "engine.io-parser@~2.1.0",
- "_id": "engine.io-parser@2.1.3",
+ "_from": "engine.io-parser@~2.2.0",
+ "_id": "engine.io-parser@2.2.1",
"_inBundle": false,
- "_integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
+ "_integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==",
"_location": "/engine.io-parser",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
- "raw": "engine.io-parser@~2.1.0",
+ "raw": "engine.io-parser@~2.2.0",
"name": "engine.io-parser",
"escapedName": "engine.io-parser",
- "rawSpec": "~2.1.0",
+ "rawSpec": "~2.2.0",
"saveSpec": null,
- "fetchSpec": "~2.1.0"
+ "fetchSpec": "~2.2.0"
},
"_requiredBy": [
"/engine.io",
"/engine.io-client"
],
- "_resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
- "_shasum": "757ab970fbf2dfb32c7b74b033216d5739ef79a6",
- "_spec": "engine.io-parser@~2.1.0",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/engine.io",
+ "_resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz",
+ "_shasum": "57ce5611d9370ee94f99641b589f94c97e4f5da7",
+ "_spec": "engine.io-parser@~2.2.0",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\engine.io",
"browser": "./lib/browser.js",
"bugs": {
"url": "https://github.com/socketio/engine.io-parser/issues"
@@ -31,13 +31,14 @@
"dependencies": {
"after": "0.8.2",
"arraybuffer.slice": "~0.0.7",
- "base64-arraybuffer": "0.1.5",
+ "base64-arraybuffer": "0.1.4",
"blob": "0.0.5",
"has-binary2": "~1.0.2"
},
"deprecated": false,
"description": "Parser for the client for the realtime Engine",
"devDependencies": {
+ "benchmark": "^2.1.4",
"expect.js": "0.3.1",
"mocha": "^5.2.0",
"socket.io-browsers": "^1.0.2",
@@ -58,5 +59,5 @@
"scripts": {
"test": "make test"
},
- "version": "2.1.3"
+ "version": "2.2.1"
}
diff --git a/node_modules/engine.io/CHANGELOG.md b/node_modules/engine.io/CHANGELOG.md
new file mode 100644
index 0000000..8b2261f
--- /dev/null
+++ b/node_modules/engine.io/CHANGELOG.md
@@ -0,0 +1,29 @@
+# [3.5.0](https://github.com/socketio/engine.io/compare/3.4.2...3.5.0) (2020-12-30)
+
+
+### Features
+
+* add support for all cookie options ([19cc582](https://github.com/socketio/engine.io/commit/19cc58264a06dca47ed401fbaca32dcdb80a903b)), closes [/github.com/jshttp/cookie#options-1](https://github.com//github.com/jshttp/cookie/issues/options-1)
+* disable perMessageDeflate by default ([5ad2736](https://github.com/socketio/engine.io/commit/5ad273601eb66c7b318542f87026837bf9dddd21))
+
+
+
+## [3.4.2](https://github.com/socketio/engine.io/compare/3.4.1...3.4.2) (2020-06-04)
+
+
+### Bug Fixes
+
+* remove explicit require of uws ([85e544a](https://github.com/socketio/engine.io/commit/85e544afd95a5890761a613263a5eba0c9a18a93))
+
+
+
+## [3.4.1](https://github.com/socketio/engine.io/compare/3.4.0...3.4.1) (2020-04-17)
+
+
+### Bug Fixes
+
+* ignore errors when forcefully closing the socket ([da851ec](https://github.com/socketio/engine.io/commit/da851ec4ec89d96df2ee5c711f328b5d795423e9))
+* use SameSite=Strict by default ([001ca62](https://github.com/socketio/engine.io/commit/001ca62cc4a8f511f3b2fbd9e4493ad274a6a0e5))
+
+
+
diff --git a/node_modules/engine.io/README.md b/node_modules/engine.io/README.md
index 7c63206..8009d68 100755
--- a/node_modules/engine.io/README.md
+++ b/node_modules/engine.io/README.md
@@ -1,7 +1,7 @@
# Engine.IO: the realtime engine
-[![Build Status](https://travis-ci.org/socketio/engine.io.svg?branch=master)](http://travis-ci.org/socketio/engine.io)
+[![Build Status](https://github.com/socketio/engine.io/workflows/CI/badge.svg)](https://github.com/socketio/engine.io/actions)
[![NPM version](https://badge.fury.io/js/engine.io.svg)](http://badge.fury.io/js/engine.io)
`Engine.IO` is the implementation of transport-based
@@ -239,7 +239,7 @@ to a single process.
- `allowUpgrades` (`Boolean`): whether to allow transport upgrades
(`true`)
- `perMessageDeflate` (`Object|Boolean`): parameters of the WebSocket permessage-deflate extension
- (see [ws module](https://github.com/einaros/ws) api docs). Set to `false` to disable. (`true`)
+ (see [ws module](https://github.com/einaros/ws) api docs). Set to `true` to enable. (`false`)
- `threshold` (`Number`): data is compressed only if the byte size is above this value (`1024`)
- `httpCompression` (`Object|Boolean`): parameters of the http compression for the polling transports
(see [zlib](http://nodejs.org/api/zlib.html#zlib_options) api docs). Set to `false` to disable. (`true`)
diff --git a/node_modules/engine.io/lib/server.js b/node_modules/engine.io/lib/server.js
index df4058e..c691561 100755
--- a/node_modules/engine.io/lib/server.js
+++ b/node_modules/engine.io/lib/server.js
@@ -47,7 +47,7 @@ function Server (opts) {
this.cookie = false !== opts.cookie ? (opts.cookie || 'io') : false;
this.cookiePath = false !== opts.cookiePath ? (opts.cookiePath || '/') : false;
this.cookieHttpOnly = false !== opts.cookieHttpOnly;
- this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || true) : false;
+ this.perMessageDeflate = opts.perMessageDeflate || false;
this.httpCompression = false !== opts.httpCompression ? (opts.httpCompression || {}) : false;
this.initialPacket = opts.initialPacket;
@@ -102,12 +102,8 @@ Server.prototype.init = function () {
if (this.ws) this.ws.close();
- var wsModule;
- switch (this.wsEngine) {
- case 'uws': wsModule = require('uws'); break;
- case 'ws': wsModule = require('ws'); break;
- default: throw new Error('unknown wsEngine');
- }
+ // add explicit require for bundlers like webpack
+ var wsModule = this.wsEngine === 'ws' ? require('ws') : require(this.wsEngine);
this.ws = new wsModule.Server({
noServer: true,
clientTracking: false,
@@ -148,6 +144,7 @@ Server.prototype.verify = function (req, upgrade, fn) {
var isOriginInvalid = checkInvalidHeaderChar(req.headers.origin);
if (isOriginInvalid) {
req.headers.origin = null;
+ debug('origin header invalid');
return fn(Server.errors.BAD_REQUEST, false);
}
@@ -155,6 +152,7 @@ Server.prototype.verify = function (req, upgrade, fn) {
var sid = req._query.sid;
if (sid) {
if (!this.clients.hasOwnProperty(sid)) {
+ debug('unknown sid "%s"', sid);
return fn(Server.errors.UNKNOWN_SID, false);
}
if (!upgrade && this.clients[sid].transport.name !== transport) {
@@ -309,6 +307,7 @@ Server.prototype.handshake = function (transportName, req) {
transport.supportsBinary = true;
}
} catch (e) {
+ debug('error handshaking to transport "%s"', transportName);
sendErrorMessage(req, req.res, Server.errors.BAD_REQUEST);
return;
}
@@ -317,11 +316,16 @@ Server.prototype.handshake = function (transportName, req) {
if (false !== this.cookie) {
transport.on('headers', function (headers) {
- headers['Set-Cookie'] = cookieMod.serialize(self.cookie, id,
- {
- path: self.cookiePath,
- httpOnly: self.cookiePath ? self.cookieHttpOnly : false
- });
+ if (typeof self.cookie === 'object') {
+ headers['Set-Cookie'] = cookieMod.serialize(self.cookie.name, id, self.cookie);
+ } else {
+ headers['Set-Cookie'] = cookieMod.serialize(self.cookie, id,
+ {
+ path: self.cookiePath,
+ httpOnly: self.cookiePath ? self.cookieHttpOnly : false,
+ sameSite: true
+ });
+ }
});
}
@@ -500,6 +504,9 @@ Server.prototype.attach = function (server, options) {
*/
function abortConnection (socket, code) {
+ socket.on('error', () => {
+ debug('ignoring error from closed connection');
+ });
if (socket.writable) {
var message = Server.errorMessages.hasOwnProperty(code) ? Server.errorMessages[code] : String(code || '');
var length = Buffer.byteLength(message);
@@ -552,23 +559,33 @@ function checkInvalidHeaderChar(val) {
val += '';
if (val.length < 1)
return false;
- if (!validHdrChars[val.charCodeAt(0)])
+ if (!validHdrChars[val.charCodeAt(0)]) {
+ debug('invalid header, index 0, char "%s"', val.charCodeAt(0));
return true;
+ }
if (val.length < 2)
return false;
- if (!validHdrChars[val.charCodeAt(1)])
+ if (!validHdrChars[val.charCodeAt(1)]) {
+ debug('invalid header, index 1, char "%s"', val.charCodeAt(1));
return true;
+ }
if (val.length < 3)
return false;
- if (!validHdrChars[val.charCodeAt(2)])
+ if (!validHdrChars[val.charCodeAt(2)]) {
+ debug('invalid header, index 2, char "%s"', val.charCodeAt(2));
return true;
+ }
if (val.length < 4)
return false;
- if (!validHdrChars[val.charCodeAt(3)])
+ if (!validHdrChars[val.charCodeAt(3)]) {
+ debug('invalid header, index 3, char "%s"', val.charCodeAt(3));
return true;
+ }
for (var i = 4; i < val.length; ++i) {
- if (!validHdrChars[val.charCodeAt(i)])
+ if (!validHdrChars[val.charCodeAt(i)]) {
+ debug('invalid header, index "%i", char "%s"', i, val.charCodeAt(i));
return true;
+ }
}
return false;
}
diff --git a/node_modules/engine.io/node_modules/cookie/HISTORY.md b/node_modules/engine.io/node_modules/cookie/HISTORY.md
index 5bd6485..ce080e0 100755
--- a/node_modules/engine.io/node_modules/cookie/HISTORY.md
+++ b/node_modules/engine.io/node_modules/cookie/HISTORY.md
@@ -1,3 +1,13 @@
+0.4.1 / 2020-04-21
+==================
+
+ * Fix `maxAge` option to reject invalid values
+
+0.4.0 / 2019-05-15
+==================
+
+ * Add `SameSite=None` support
+
0.3.1 / 2016-05-26
==================
diff --git a/node_modules/engine.io/node_modules/cookie/README.md b/node_modules/engine.io/node_modules/cookie/README.md
index db0d078..18b2c2c 100755
--- a/node_modules/engine.io/node_modules/cookie/README.md
+++ b/node_modules/engine.io/node_modules/cookie/README.md
@@ -1,7 +1,7 @@
# cookie
-[![NPM Version][npm-image]][npm-url]
-[![NPM Downloads][downloads-image]][downloads-url]
+[![NPM Version][npm-version-image]][npm-url]
+[![NPM Downloads][npm-downloads-image]][npm-url]
[![Node.js Version][node-version-image]][node-version-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]
@@ -10,6 +10,10 @@ Basic HTTP cookie parser and serializer for HTTP servers.
## Installation
+This is a [Node.js](https://nodejs.org/en/) module available through the
+[npm registry](https://www.npmjs.com/). Installation is done using the
+[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
+
```sh
$ npm install cookie
```
@@ -64,7 +68,7 @@ var setCookie = cookie.serialize('foo', 'bar');
##### domain
-Specifies the value for the [`Domain` `Set-Cookie` attribute][rfc-6266-5.2.3]. By default, no
+Specifies the value for the [`Domain` `Set-Cookie` attribute][rfc-6265-5.2.3]. By default, no
domain is set, and most clients will consider the cookie to apply to only the current domain.
##### encode
@@ -73,22 +77,22 @@ Specifies a function that will be used to encode a cookie's value. Since value o
has a limited character set (and must be a simple string), this function can be used to encode
a value into a string suited for a cookie's value.
-The default function is the global `ecodeURIComponent`, which will encode a JavaScript string
+The default function is the global `encodeURIComponent`, which will encode a JavaScript string
into UTF-8 byte sequences and then URL-encode any that fall outside of the cookie range.
##### expires
-Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute][rfc-6266-5.2.1].
+Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute][rfc-6265-5.2.1].
By default, no expiration is set, and most clients will consider this a "non-persistent cookie" and
will delete it on a condition like exiting a web browser application.
-**note** the [cookie storage model specification][rfc-6266-5.3] states that if both `expires` and
-`magAge` are set, then `maxAge` takes precedence, but it is possiblke not all clients by obey this,
+**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and
+`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
so if both are set, they should point to the same date and time.
##### httpOnly
-Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute][rfc-6266-5.2.6]. When truthy,
+Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute][rfc-6265-5.2.6]. When truthy,
the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly` attribute is not set.
**note** be careful when setting this to `true`, as compliant clients will not allow client-side
@@ -96,38 +100,37 @@ JavaScript to see the cookie in `document.cookie`.
##### maxAge
-Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute][rfc-6266-5.2.2].
+Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute][rfc-6265-5.2.2].
The given number will be converted to an integer by rounding down. By default, no maximum age is set.
-**note** the [cookie storage model specification][rfc-6266-5.3] states that if both `expires` and
-`magAge` are set, then `maxAge` takes precedence, but it is possiblke not all clients by obey this,
+**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and
+`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
so if both are set, they should point to the same date and time.
##### path
-Specifies the value for the [`Path` `Set-Cookie` attribute][rfc-6266-5.2.4]. By default, the path
-is considered the ["default path"][rfc-6266-5.1.4]. By default, no maximum age is set, and most
-clients will consider this a "non-persistent cookie" and will delete it on a condition like exiting
-a web browser application.
+Specifies the value for the [`Path` `Set-Cookie` attribute][rfc-6265-5.2.4]. By default, the path
+is considered the ["default path"][rfc-6265-5.1.4].
##### sameSite
-Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][draft-west-first-party-cookies-07].
+Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][rfc-6265bis-03-4.1.2.7].
- `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
- `false` will not set the `SameSite` attribute.
- `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
+ - `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
- `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
-More information about the different enforcement levels can be found in the specification
-https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1.1
+More information about the different enforcement levels can be found in
+[the specification][rfc-6265bis-03-4.1.2.7].
**note** This is an attribute that has not yet been fully standardized, and may change in the future.
This also means many clients may ignore this attribute until they understand it.
##### secure
-Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute][rfc-6266-5.2.5]. When truthy,
+Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute][rfc-6265-5.2.5]. When truthy,
the `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set.
**note** be careful when setting this to `true`, as compliant clients will not send the cookie back to
@@ -178,7 +181,7 @@ function onRequest(req, res) {
res.write('');
}
http.createServer(onRequest).listen(3000);
@@ -190,31 +193,65 @@ http.createServer(onRequest).listen(3000);
$ npm test
```
+## Benchmark
+
+```
+$ npm run bench
+
+> cookie@0.3.1 bench cookie
+> node benchmark/index.js
+
+ http_parser@2.8.0
+ node@6.14.2
+ v8@5.1.281.111
+ uv@1.16.1
+ zlib@1.2.11
+ ares@1.10.1-DEV
+ icu@58.2
+ modules@48
+ napi@3
+ openssl@1.0.2o
+
+> node benchmark/parse.js
+
+ cookie.parse
+
+ 6 tests completed.
+
+ simple x 1,200,691 ops/sec ±1.12% (189 runs sampled)
+ decode x 1,012,994 ops/sec ±0.97% (186 runs sampled)
+ unquote x 1,074,174 ops/sec ±2.43% (186 runs sampled)
+ duplicates x 438,424 ops/sec ±2.17% (184 runs sampled)
+ 10 cookies x 147,154 ops/sec ±1.01% (186 runs sampled)
+ 100 cookies x 14,274 ops/sec ±1.07% (187 runs sampled)
+```
+
## References
-- [RFC 6266: HTTP State Management Mechanism][rfc-6266]
-- [Same-site Cookies][draft-west-first-party-cookies-07]
+- [RFC 6265: HTTP State Management Mechanism][rfc-6265]
+- [Same-site Cookies][rfc-6265bis-03-4.1.2.7]
-[draft-west-first-party-cookies-07]: https://tools.ietf.org/html/draft-west-first-party-cookies-07
-[rfc-6266]: https://tools.ietf.org/html/rfc6266
-[rfc-6266-5.1.4]: https://tools.ietf.org/html/rfc6266#section-5.1.4
-[rfc-6266-5.2.1]: https://tools.ietf.org/html/rfc6266#section-5.2.1
-[rfc-6266-5.2.2]: https://tools.ietf.org/html/rfc6266#section-5.2.2
-[rfc-6266-5.2.3]: https://tools.ietf.org/html/rfc6266#section-5.2.3
-[rfc-6266-5.2.4]: https://tools.ietf.org/html/rfc6266#section-5.2.4
-[rfc-6266-5.3]: https://tools.ietf.org/html/rfc6266#section-5.3
+[rfc-6265bis-03-4.1.2.7]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7
+[rfc-6265]: https://tools.ietf.org/html/rfc6265
+[rfc-6265-5.1.4]: https://tools.ietf.org/html/rfc6265#section-5.1.4
+[rfc-6265-5.2.1]: https://tools.ietf.org/html/rfc6265#section-5.2.1
+[rfc-6265-5.2.2]: https://tools.ietf.org/html/rfc6265#section-5.2.2
+[rfc-6265-5.2.3]: https://tools.ietf.org/html/rfc6265#section-5.2.3
+[rfc-6265-5.2.4]: https://tools.ietf.org/html/rfc6265#section-5.2.4
+[rfc-6265-5.2.5]: https://tools.ietf.org/html/rfc6265#section-5.2.5
+[rfc-6265-5.2.6]: https://tools.ietf.org/html/rfc6265#section-5.2.6
+[rfc-6265-5.3]: https://tools.ietf.org/html/rfc6265#section-5.3
## License
[MIT](LICENSE)
-[npm-image]: https://img.shields.io/npm/v/cookie.svg
-[npm-url]: https://npmjs.org/package/cookie
-[node-version-image]: https://img.shields.io/node/v/cookie.svg
+[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/cookie/master
+[coveralls-url]: https://coveralls.io/r/jshttp/cookie?branch=master
+[node-version-image]: https://badgen.net/npm/node/cookie
[node-version-url]: https://nodejs.org/en/download
-[travis-image]: https://img.shields.io/travis/jshttp/cookie/master.svg
+[npm-downloads-image]: https://badgen.net/npm/dm/cookie
+[npm-url]: https://npmjs.org/package/cookie
+[npm-version-image]: https://badgen.net/npm/v/cookie
+[travis-image]: https://badgen.net/travis/jshttp/cookie/master
[travis-url]: https://travis-ci.org/jshttp/cookie
-[coveralls-image]: https://img.shields.io/coveralls/jshttp/cookie/master.svg
-[coveralls-url]: https://coveralls.io/r/jshttp/cookie?branch=master
-[downloads-image]: https://img.shields.io/npm/dm/cookie.svg
-[downloads-url]: https://npmjs.org/package/cookie
diff --git a/node_modules/engine.io/node_modules/cookie/index.js b/node_modules/engine.io/node_modules/cookie/index.js
index ab2e467..760f32e 100755
--- a/node_modules/engine.io/node_modules/cookie/index.js
+++ b/node_modules/engine.io/node_modules/cookie/index.js
@@ -120,7 +120,11 @@ function serialize(name, val, options) {
if (null != opt.maxAge) {
var maxAge = opt.maxAge - 0;
- if (isNaN(maxAge)) throw new Error('maxAge should be a Number');
+
+ if (isNaN(maxAge) || !isFinite(maxAge)) {
+ throw new TypeError('option maxAge is invalid')
+ }
+
str += '; Max-Age=' + Math.floor(maxAge);
}
@@ -170,6 +174,9 @@ function serialize(name, val, options) {
case 'strict':
str += '; SameSite=Strict';
break;
+ case 'none':
+ str += '; SameSite=None';
+ break;
default:
throw new TypeError('option sameSite is invalid');
}
diff --git a/node_modules/engine.io/node_modules/cookie/package.json b/node_modules/engine.io/node_modules/cookie/package.json
index 8cff0fe..c4b8d11 100755
--- a/node_modules/engine.io/node_modules/cookie/package.json
+++ b/node_modules/engine.io/node_modules/cookie/package.json
@@ -1,27 +1,27 @@
{
- "_from": "cookie@0.3.1",
- "_id": "cookie@0.3.1",
+ "_from": "cookie@~0.4.1",
+ "_id": "cookie@0.4.1",
"_inBundle": false,
- "_integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+ "_integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
"_location": "/engine.io/cookie",
"_phantomChildren": {},
"_requested": {
- "type": "version",
+ "type": "range",
"registry": true,
- "raw": "cookie@0.3.1",
+ "raw": "cookie@~0.4.1",
"name": "cookie",
"escapedName": "cookie",
- "rawSpec": "0.3.1",
+ "rawSpec": "~0.4.1",
"saveSpec": null,
- "fetchSpec": "0.3.1"
+ "fetchSpec": "~0.4.1"
},
"_requiredBy": [
"/engine.io"
],
- "_resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
- "_shasum": "e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb",
- "_spec": "cookie@0.3.1",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/engine.io",
+ "_resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
+ "_shasum": "afd713fe26ebd21ba95ceb61f9a8116e50a537d1",
+ "_spec": "cookie@~0.4.1",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\engine.io",
"author": {
"name": "Roman Shtylman",
"email": "shtylman@gmail.com"
@@ -39,8 +39,12 @@
"deprecated": false,
"description": "HTTP server cookie parsing and serialization",
"devDependencies": {
- "istanbul": "0.4.3",
- "mocha": "1.21.5"
+ "beautify-benchmark": "0.2.4",
+ "benchmark": "2.1.4",
+ "eslint": "6.8.0",
+ "eslint-plugin-markdown": "1.0.2",
+ "mocha": "7.1.1",
+ "nyc": "15.0.1"
},
"engines": {
"node": ">= 0.6"
@@ -63,9 +67,12 @@
"url": "git+https://github.com/jshttp/cookie.git"
},
"scripts": {
- "test": "mocha --reporter spec --bail --check-leaks test/",
- "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/",
- "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/"
+ "bench": "node benchmark/index.js",
+ "lint": "eslint --plugin markdown --ext js,md .",
+ "test": "mocha --reporter spec --bail --check-leaks --ui qunit test/",
+ "test-ci": "nyc --reporter=text npm test",
+ "test-cov": "nyc --reporter=html --reporter=text npm test",
+ "version": "node scripts/version-history.js && git add HISTORY.md"
},
- "version": "0.3.1"
+ "version": "0.4.1"
}
diff --git a/node_modules/engine.io/node_modules/debug/.coveralls.yml b/node_modules/engine.io/node_modules/debug/.coveralls.yml
deleted file mode 100755
index 20a7068..0000000
--- a/node_modules/engine.io/node_modules/debug/.coveralls.yml
+++ /dev/null
@@ -1 +0,0 @@
-repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
diff --git a/node_modules/engine.io/node_modules/debug/.eslintrc b/node_modules/engine.io/node_modules/debug/.eslintrc
deleted file mode 100755
index 146371e..0000000
--- a/node_modules/engine.io/node_modules/debug/.eslintrc
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "env": {
- "browser": true,
- "node": true
- },
- "globals": {
- "chrome": true
- },
- "rules": {
- "no-console": 0,
- "no-empty": [1, { "allowEmptyCatch": true }]
- },
- "extends": "eslint:recommended"
-}
diff --git a/node_modules/engine.io/node_modules/debug/.npmignore b/node_modules/engine.io/node_modules/debug/.npmignore
deleted file mode 100755
index 5f60eec..0000000
--- a/node_modules/engine.io/node_modules/debug/.npmignore
+++ /dev/null
@@ -1,9 +0,0 @@
-support
-test
-examples
-example
-*.sock
-dist
-yarn.lock
-coverage
-bower.json
diff --git a/node_modules/engine.io/node_modules/debug/.travis.yml b/node_modules/engine.io/node_modules/debug/.travis.yml
deleted file mode 100755
index a764300..0000000
--- a/node_modules/engine.io/node_modules/debug/.travis.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-sudo: false
-
-language: node_js
-
-node_js:
- - "4"
- - "6"
- - "8"
-
-install:
- - make install
-
-script:
- - make lint
- - make test
-
-matrix:
- include:
- - node_js: '8'
- env: BROWSER=1
diff --git a/node_modules/engine.io/node_modules/debug/Makefile b/node_modules/engine.io/node_modules/debug/Makefile
deleted file mode 100755
index 3ddd136..0000000
--- a/node_modules/engine.io/node_modules/debug/Makefile
+++ /dev/null
@@ -1,58 +0,0 @@
-# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
-THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
-THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
-
-# BIN directory
-BIN := $(THIS_DIR)/node_modules/.bin
-
-# Path
-PATH := node_modules/.bin:$(PATH)
-SHELL := /bin/bash
-
-# applications
-NODE ?= $(shell which node)
-YARN ?= $(shell which yarn)
-PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
-BROWSERIFY ?= $(NODE) $(BIN)/browserify
-
-install: node_modules
-
-browser: dist/debug.js
-
-node_modules: package.json
- @NODE_ENV= $(PKG) install
- @touch node_modules
-
-dist/debug.js: src/*.js node_modules
- @mkdir -p dist
- @$(BROWSERIFY) \
- --standalone debug \
- . > dist/debug.js
-
-lint:
- @eslint *.js src/*.js
-
-test-node:
- @istanbul cover node_modules/mocha/bin/_mocha -- test/**.js
- @cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
-
-test-browser:
- @$(MAKE) browser
- @karma start --single-run
-
-test-all:
- @concurrently \
- "make test-node" \
- "make test-browser"
-
-test:
- @if [ "x$(BROWSER)" = "x" ]; then \
- $(MAKE) test-node; \
- else \
- $(MAKE) test-browser; \
- fi
-
-clean:
- rimraf dist coverage
-
-.PHONY: browser install clean lint test test-all test-node test-browser
diff --git a/node_modules/engine.io/node_modules/debug/README.md b/node_modules/engine.io/node_modules/debug/README.md
index 8e754d1..88dae35 100755
--- a/node_modules/engine.io/node_modules/debug/README.md
+++ b/node_modules/engine.io/node_modules/debug/README.md
@@ -70,7 +70,9 @@ Here are some examples:
-#### Windows note
+#### Windows command prompt notes
+
+##### CMD
On Windows the environment variable is set using the `set` command.
@@ -78,14 +80,32 @@ On Windows the environment variable is set using the `set` command.
set DEBUG=*,-not_this
```
-Note that PowerShell uses different syntax to set environment variables.
+Example:
+
+```cmd
+set DEBUG=* & node app.js
+```
+
+##### PowerShell (VS Code default)
+
+PowerShell uses different syntax to set environment variables.
```cmd
$env:DEBUG = "*,-not_this"
```
+Example:
+
+```cmd
+$env:DEBUG='app';node app.js
+```
+
Then, run the program to be debugged as usual.
+npm script example:
+```js
+ "windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js",
+```
## Namespace Colors
@@ -248,6 +268,73 @@ error('now goes to stdout via console.info');
log('still goes to stdout, but via console.info now');
```
+## Extend
+You can simply extend debugger
+```js
+const log = require('debug')('auth');
+
+//creates new debug instance with extended namespace
+const logSign = log.extend('sign');
+const logLogin = log.extend('login');
+
+log('hello'); // auth hello
+logSign('hello'); //auth:sign hello
+logLogin('hello'); //auth:login hello
+```
+
+## Set dynamically
+
+You can also enable debug dynamically by calling the `enable()` method :
+
+```js
+let debug = require('debug');
+
+console.log(1, debug.enabled('test'));
+
+debug.enable('test');
+console.log(2, debug.enabled('test'));
+
+debug.disable();
+console.log(3, debug.enabled('test'));
+
+```
+
+print :
+```
+1 false
+2 true
+3 false
+```
+
+Usage :
+`enable(namespaces)`
+`namespaces` can include modes separated by a colon and wildcards.
+
+Note that calling `enable()` completely overrides previously set DEBUG variable :
+
+```
+$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))'
+=> false
+```
+
+`disable()`
+
+Will disable all namespaces. The functions returns the namespaces currently
+enabled (and skipped). This can be useful if you want to disable debugging
+temporarily without knowing what was enabled to begin with.
+
+For example:
+
+```js
+let debug = require('debug');
+debug.enable('foo:*,-foo:bar');
+let namespaces = debug.disable();
+debug.enable(namespaces);
+```
+
+Note: There is no guarantee that the string will be identical to the initial
+enable string, but semantically they will be identical.
+
## Checking whether a debug target is enabled
After you've created a debug instance, you can determine whether or not it is
diff --git a/node_modules/engine.io/node_modules/debug/dist/debug.js b/node_modules/engine.io/node_modules/debug/dist/debug.js
new file mode 100644
index 0000000..89ad0c2
--- /dev/null
+++ b/node_modules/engine.io/node_modules/debug/dist/debug.js
@@ -0,0 +1,912 @@
+"use strict";
+
+function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
+
+function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
+
+function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
+
+function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+(function (f) {
+ if ((typeof exports === "undefined" ? "undefined" : _typeof(exports)) === "object" && typeof module !== "undefined") {
+ module.exports = f();
+ } else if (typeof define === "function" && define.amd) {
+ define([], f);
+ } else {
+ var g;
+
+ if (typeof window !== "undefined") {
+ g = window;
+ } else if (typeof global !== "undefined") {
+ g = global;
+ } else if (typeof self !== "undefined") {
+ g = self;
+ } else {
+ g = this;
+ }
+
+ g.debug = f();
+ }
+})(function () {
+ var define, module, exports;
+ return function () {
+ function r(e, n, t) {
+ function o(i, f) {
+ if (!n[i]) {
+ if (!e[i]) {
+ var c = "function" == typeof require && require;
+ if (!f && c) return c(i, !0);
+ if (u) return u(i, !0);
+ var a = new Error("Cannot find module '" + i + "'");
+ throw a.code = "MODULE_NOT_FOUND", a;
+ }
+
+ var p = n[i] = {
+ exports: {}
+ };
+ e[i][0].call(p.exports, function (r) {
+ var n = e[i][1][r];
+ return o(n || r);
+ }, p, p.exports, r, e, n, t);
+ }
+
+ return n[i].exports;
+ }
+
+ for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) {
+ o(t[i]);
+ }
+
+ return o;
+ }
+
+ return r;
+ }()({
+ 1: [function (require, module, exports) {
+ /**
+ * Helpers.
+ */
+ var s = 1000;
+ var m = s * 60;
+ var h = m * 60;
+ var d = h * 24;
+ var w = d * 7;
+ var y = d * 365.25;
+ /**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ * - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+ module.exports = function (val, options) {
+ options = options || {};
+
+ var type = _typeof(val);
+
+ if (type === 'string' && val.length > 0) {
+ return parse(val);
+ } else if (type === 'number' && isNaN(val) === false) {
+ return options.long ? fmtLong(val) : fmtShort(val);
+ }
+
+ throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val));
+ };
+ /**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+
+ function parse(str) {
+ str = String(str);
+
+ if (str.length > 100) {
+ return;
+ }
+
+ var match = /^((?:\d+)?\-?\d?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);
+
+ if (!match) {
+ return;
+ }
+
+ var n = parseFloat(match[1]);
+ var type = (match[2] || 'ms').toLowerCase();
+
+ switch (type) {
+ case 'years':
+ case 'year':
+ case 'yrs':
+ case 'yr':
+ case 'y':
+ return n * y;
+
+ case 'weeks':
+ case 'week':
+ case 'w':
+ return n * w;
+
+ case 'days':
+ case 'day':
+ case 'd':
+ return n * d;
+
+ case 'hours':
+ case 'hour':
+ case 'hrs':
+ case 'hr':
+ case 'h':
+ return n * h;
+
+ case 'minutes':
+ case 'minute':
+ case 'mins':
+ case 'min':
+ case 'm':
+ return n * m;
+
+ case 'seconds':
+ case 'second':
+ case 'secs':
+ case 'sec':
+ case 's':
+ return n * s;
+
+ case 'milliseconds':
+ case 'millisecond':
+ case 'msecs':
+ case 'msec':
+ case 'ms':
+ return n;
+
+ default:
+ return undefined;
+ }
+ }
+ /**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+
+ function fmtShort(ms) {
+ var msAbs = Math.abs(ms);
+
+ if (msAbs >= d) {
+ return Math.round(ms / d) + 'd';
+ }
+
+ if (msAbs >= h) {
+ return Math.round(ms / h) + 'h';
+ }
+
+ if (msAbs >= m) {
+ return Math.round(ms / m) + 'm';
+ }
+
+ if (msAbs >= s) {
+ return Math.round(ms / s) + 's';
+ }
+
+ return ms + 'ms';
+ }
+ /**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+
+ function fmtLong(ms) {
+ var msAbs = Math.abs(ms);
+
+ if (msAbs >= d) {
+ return plural(ms, msAbs, d, 'day');
+ }
+
+ if (msAbs >= h) {
+ return plural(ms, msAbs, h, 'hour');
+ }
+
+ if (msAbs >= m) {
+ return plural(ms, msAbs, m, 'minute');
+ }
+
+ if (msAbs >= s) {
+ return plural(ms, msAbs, s, 'second');
+ }
+
+ return ms + ' ms';
+ }
+ /**
+ * Pluralization helper.
+ */
+
+
+ function plural(ms, msAbs, n, name) {
+ var isPlural = msAbs >= n * 1.5;
+ return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
+ }
+ }, {}],
+ 2: [function (require, module, exports) {
+ // shim for using process in browser
+ var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it
+ // don't break things. But we need to wrap it in a try catch in case it is
+ // wrapped in strict mode code which doesn't define any globals. It's inside a
+ // function because try/catches deoptimize in certain engines.
+
+ var cachedSetTimeout;
+ var cachedClearTimeout;
+
+ function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+ }
+
+ function defaultClearTimeout() {
+ throw new Error('clearTimeout has not been defined');
+ }
+
+ (function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ })();
+
+ function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ } // if setTimeout wasn't available but was latter defined
+
+
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch (e) {
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch (e) {
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+ }
+
+ function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ } // if clearTimeout wasn't available but was latter defined
+
+
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e) {
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e) {
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+ }
+
+ var queue = [];
+ var draining = false;
+ var currentQueue;
+ var queueIndex = -1;
+
+ function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+
+ draining = false;
+
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+
+ if (queue.length) {
+ drainQueue();
+ }
+ }
+
+ function drainQueue() {
+ if (draining) {
+ return;
+ }
+
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+ var len = queue.length;
+
+ while (len) {
+ currentQueue = queue;
+ queue = [];
+
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+
+ queueIndex = -1;
+ len = queue.length;
+ }
+
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+ }
+
+ process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+
+ queue.push(new Item(fun, args));
+
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+ }; // v8 likes predictible objects
+
+
+ function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+ }
+
+ Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+ };
+
+ process.title = 'browser';
+ process.browser = true;
+ process.env = {};
+ process.argv = [];
+ process.version = ''; // empty string to avoid regexp issues
+
+ process.versions = {};
+
+ function noop() {}
+
+ process.on = noop;
+ process.addListener = noop;
+ process.once = noop;
+ process.off = noop;
+ process.removeListener = noop;
+ process.removeAllListeners = noop;
+ process.emit = noop;
+ process.prependListener = noop;
+ process.prependOnceListener = noop;
+
+ process.listeners = function (name) {
+ return [];
+ };
+
+ process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+ };
+
+ process.cwd = function () {
+ return '/';
+ };
+
+ process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+ };
+
+ process.umask = function () {
+ return 0;
+ };
+ }, {}],
+ 3: [function (require, module, exports) {
+ /**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ */
+ function setup(env) {
+ createDebug.debug = createDebug;
+ createDebug.default = createDebug;
+ createDebug.coerce = coerce;
+ createDebug.disable = disable;
+ createDebug.enable = enable;
+ createDebug.enabled = enabled;
+ createDebug.humanize = require('ms');
+ Object.keys(env).forEach(function (key) {
+ createDebug[key] = env[key];
+ });
+ /**
+ * Active `debug` instances.
+ */
+
+ createDebug.instances = [];
+ /**
+ * The currently active debug mode names, and names to skip.
+ */
+
+ createDebug.names = [];
+ createDebug.skips = [];
+ /**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+ */
+
+ createDebug.formatters = {};
+ /**
+ * Selects a color for a debug namespace
+ * @param {String} namespace The namespace string for the for the debug instance to be colored
+ * @return {Number|String} An ANSI color code for the given namespace
+ * @api private
+ */
+
+ function selectColor(namespace) {
+ var hash = 0;
+
+ for (var i = 0; i < namespace.length; i++) {
+ hash = (hash << 5) - hash + namespace.charCodeAt(i);
+ hash |= 0; // Convert to 32bit integer
+ }
+
+ return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
+ }
+
+ createDebug.selectColor = selectColor;
+ /**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+
+ function createDebug(namespace) {
+ var prevTime;
+
+ function debug() {
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ // Disabled?
+ if (!debug.enabled) {
+ return;
+ }
+
+ var self = debug; // Set `diff` timestamp
+
+ var curr = Number(new Date());
+ var ms = curr - (prevTime || curr);
+ self.diff = ms;
+ self.prev = prevTime;
+ self.curr = curr;
+ prevTime = curr;
+ args[0] = createDebug.coerce(args[0]);
+
+ if (typeof args[0] !== 'string') {
+ // Anything else let's inspect with %O
+ args.unshift('%O');
+ } // Apply any `formatters` transformations
+
+
+ var index = 0;
+ args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) {
+ // If we encounter an escaped % then don't increase the array index
+ if (match === '%%') {
+ return match;
+ }
+
+ index++;
+ var formatter = createDebug.formatters[format];
+
+ if (typeof formatter === 'function') {
+ var val = args[index];
+ match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format`
+
+ args.splice(index, 1);
+ index--;
+ }
+
+ return match;
+ }); // Apply env-specific formatting (colors, etc.)
+
+ createDebug.formatArgs.call(self, args);
+ var logFn = self.log || createDebug.log;
+ logFn.apply(self, args);
+ }
+
+ debug.namespace = namespace;
+ debug.enabled = createDebug.enabled(namespace);
+ debug.useColors = createDebug.useColors();
+ debug.color = selectColor(namespace);
+ debug.destroy = destroy;
+ debug.extend = extend; // Debug.formatArgs = formatArgs;
+ // debug.rawLog = rawLog;
+ // env-specific initialization logic for debug instances
+
+ if (typeof createDebug.init === 'function') {
+ createDebug.init(debug);
+ }
+
+ createDebug.instances.push(debug);
+ return debug;
+ }
+
+ function destroy() {
+ var index = createDebug.instances.indexOf(this);
+
+ if (index !== -1) {
+ createDebug.instances.splice(index, 1);
+ return true;
+ }
+
+ return false;
+ }
+
+ function extend(namespace, delimiter) {
+ var newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
+ newDebug.log = this.log;
+ return newDebug;
+ }
+ /**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+
+
+ function enable(namespaces) {
+ createDebug.save(namespaces);
+ createDebug.names = [];
+ createDebug.skips = [];
+ var i;
+ var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+ var len = split.length;
+
+ for (i = 0; i < len; i++) {
+ if (!split[i]) {
+ // ignore empty strings
+ continue;
+ }
+
+ namespaces = split[i].replace(/\*/g, '.*?');
+
+ if (namespaces[0] === '-') {
+ createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+ } else {
+ createDebug.names.push(new RegExp('^' + namespaces + '$'));
+ }
+ }
+
+ for (i = 0; i < createDebug.instances.length; i++) {
+ var instance = createDebug.instances[i];
+ instance.enabled = createDebug.enabled(instance.namespace);
+ }
+ }
+ /**
+ * Disable debug output.
+ *
+ * @return {String} namespaces
+ * @api public
+ */
+
+
+ function disable() {
+ var namespaces = [].concat(_toConsumableArray(createDebug.names.map(toNamespace)), _toConsumableArray(createDebug.skips.map(toNamespace).map(function (namespace) {
+ return '-' + namespace;
+ }))).join(',');
+ createDebug.enable('');
+ return namespaces;
+ }
+ /**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+
+ function enabled(name) {
+ if (name[name.length - 1] === '*') {
+ return true;
+ }
+
+ var i;
+ var len;
+
+ for (i = 0, len = createDebug.skips.length; i < len; i++) {
+ if (createDebug.skips[i].test(name)) {
+ return false;
+ }
+ }
+
+ for (i = 0, len = createDebug.names.length; i < len; i++) {
+ if (createDebug.names[i].test(name)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ /**
+ * Convert regexp to namespace
+ *
+ * @param {RegExp} regxep
+ * @return {String} namespace
+ * @api private
+ */
+
+
+ function toNamespace(regexp) {
+ return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\.\*\?$/, '*');
+ }
+ /**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+
+
+ function coerce(val) {
+ if (val instanceof Error) {
+ return val.stack || val.message;
+ }
+
+ return val;
+ }
+
+ createDebug.enable(createDebug.load());
+ return createDebug;
+ }
+
+ module.exports = setup;
+ }, {
+ "ms": 1
+ }],
+ 4: [function (require, module, exports) {
+ (function (process) {
+ /* eslint-env browser */
+
+ /**
+ * This is the web browser implementation of `debug()`.
+ */
+ exports.log = log;
+ exports.formatArgs = formatArgs;
+ exports.save = save;
+ exports.load = load;
+ exports.useColors = useColors;
+ exports.storage = localstorage();
+ /**
+ * Colors.
+ */
+
+ exports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'];
+ /**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
+ // eslint-disable-next-line complexity
+
+ function useColors() {
+ // NB: In an Electron preload script, document will be defined but not fully
+ // initialized. Since we know we're in Chrome, we'll just detect this case
+ // explicitly
+ if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
+ return true;
+ } // Internet Explorer and Edge do not support colors.
+
+
+ if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
+ return false;
+ } // Is webkit? http://stackoverflow.com/a/16459606/376773
+ // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+
+
+ return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773
+ typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?
+ // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+ typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker
+ typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
+ }
+ /**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
+
+
+ function formatArgs(args) {
+ args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff);
+
+ if (!this.useColors) {
+ return;
+ }
+
+ var c = 'color: ' + this.color;
+ args.splice(1, 0, c, 'color: inherit'); // The final "%c" is somewhat tricky, because there could be other
+ // arguments passed either before or after the %c, so we need to
+ // figure out the correct index to insert the CSS into
+
+ var index = 0;
+ var lastC = 0;
+ args[0].replace(/%[a-zA-Z%]/g, function (match) {
+ if (match === '%%') {
+ return;
+ }
+
+ index++;
+
+ if (match === '%c') {
+ // We only are interested in the *last* %c
+ // (the user may have provided their own)
+ lastC = index;
+ }
+ });
+ args.splice(lastC, 0, c);
+ }
+ /**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
+
+
+ function log() {
+ var _console;
+
+ // This hackery is required for IE8/9, where
+ // the `console.log` function doesn't have 'apply'
+ return (typeof console === "undefined" ? "undefined" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments);
+ }
+ /**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+
+ function save(namespaces) {
+ try {
+ if (namespaces) {
+ exports.storage.setItem('debug', namespaces);
+ } else {
+ exports.storage.removeItem('debug');
+ }
+ } catch (error) {// Swallow
+ // XXX (@Qix-) should we be logging these?
+ }
+ }
+ /**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+
+ function load() {
+ var r;
+
+ try {
+ r = exports.storage.getItem('debug');
+ } catch (error) {} // Swallow
+ // XXX (@Qix-) should we be logging these?
+ // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+
+
+ if (!r && typeof process !== 'undefined' && 'env' in process) {
+ r = process.env.DEBUG;
+ }
+
+ return r;
+ }
+ /**
+ * Localstorage attempts to return the localstorage.
+ *
+ * This is necessary because safari throws
+ * when a user disables cookies/localstorage
+ * and you attempt to access it.
+ *
+ * @return {LocalStorage}
+ * @api private
+ */
+
+
+ function localstorage() {
+ try {
+ // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
+ // The Browser also has localStorage in the global context.
+ return localStorage;
+ } catch (error) {// Swallow
+ // XXX (@Qix-) should we be logging these?
+ }
+ }
+
+ module.exports = require('./common')(exports);
+ var formatters = module.exports.formatters;
+ /**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+ formatters.j = function (v) {
+ try {
+ return JSON.stringify(v);
+ } catch (error) {
+ return '[UnexpectedJSONParseError]: ' + error.message;
+ }
+ };
+ }).call(this, require('_process'));
+ }, {
+ "./common": 3,
+ "_process": 2
+ }]
+ }, {}, [4])(4);
+});
diff --git a/node_modules/engine.io/node_modules/debug/karma.conf.js b/node_modules/engine.io/node_modules/debug/karma.conf.js
deleted file mode 100755
index 103a82d..0000000
--- a/node_modules/engine.io/node_modules/debug/karma.conf.js
+++ /dev/null
@@ -1,70 +0,0 @@
-// Karma configuration
-// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
-
-module.exports = function(config) {
- config.set({
-
- // base path that will be used to resolve all patterns (eg. files, exclude)
- basePath: '',
-
-
- // frameworks to use
- // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
- frameworks: ['mocha', 'chai', 'sinon'],
-
-
- // list of files / patterns to load in the browser
- files: [
- 'dist/debug.js',
- 'test/*spec.js'
- ],
-
-
- // list of files to exclude
- exclude: [
- 'src/node.js'
- ],
-
-
- // preprocess matching files before serving them to the browser
- // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
- preprocessors: {
- },
-
- // test results reporter to use
- // possible values: 'dots', 'progress'
- // available reporters: https://npmjs.org/browse/keyword/karma-reporter
- reporters: ['progress'],
-
-
- // web server port
- port: 9876,
-
-
- // enable / disable colors in the output (reporters and logs)
- colors: true,
-
-
- // level of logging
- // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- logLevel: config.LOG_INFO,
-
-
- // enable / disable watching file and executing tests whenever any file changes
- autoWatch: true,
-
-
- // start these browsers
- // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
- browsers: ['PhantomJS'],
-
-
- // Continuous Integration mode
- // if true, Karma captures browsers, runs the tests and exits
- singleRun: false,
-
- // Concurrency level
- // how many browser should be started simultaneous
- concurrency: Infinity
- })
-}
diff --git a/node_modules/engine.io/node_modules/debug/node.js b/node_modules/engine.io/node_modules/debug/node.js
deleted file mode 100755
index 7fc36fe..0000000
--- a/node_modules/engine.io/node_modules/debug/node.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('./src/node');
diff --git a/node_modules/engine.io/node_modules/debug/package.json b/node_modules/engine.io/node_modules/debug/package.json
index 55b83c7..cfa6fb4 100755
--- a/node_modules/engine.io/node_modules/debug/package.json
+++ b/node_modules/engine.io/node_modules/debug/package.json
@@ -1,27 +1,27 @@
{
- "_from": "debug@~3.1.0",
- "_id": "debug@3.1.0",
+ "_from": "debug@~4.1.0",
+ "_id": "debug@4.1.1",
"_inBundle": false,
- "_integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "_integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"_location": "/engine.io/debug",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
- "raw": "debug@~3.1.0",
+ "raw": "debug@~4.1.0",
"name": "debug",
"escapedName": "debug",
- "rawSpec": "~3.1.0",
+ "rawSpec": "~4.1.0",
"saveSpec": null,
- "fetchSpec": "~3.1.0"
+ "fetchSpec": "~4.1.0"
},
"_requiredBy": [
"/engine.io"
],
- "_resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
- "_shasum": "5bb5a0672628b64149566ba16819e61518c67261",
- "_spec": "debug@~3.1.0",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/engine.io",
+ "_resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "_shasum": "3b72260255109c6b589cee050f1d516139664791",
+ "_spec": "debug@~4.1.0",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\engine.io",
"author": {
"name": "TJ Holowaychuk",
"email": "tj@vision-media.ca"
@@ -43,28 +43,34 @@
}
],
"dependencies": {
- "ms": "2.0.0"
+ "ms": "^2.1.1"
},
- "deprecated": false,
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
"description": "small debugging utility",
"devDependencies": {
+ "@babel/cli": "^7.0.0",
+ "@babel/core": "^7.0.0",
+ "@babel/preset-env": "^7.0.0",
"browserify": "14.4.0",
"chai": "^3.5.0",
"concurrently": "^3.1.0",
- "coveralls": "^2.11.15",
- "eslint": "^3.12.1",
+ "coveralls": "^3.0.2",
"istanbul": "^0.4.5",
- "karma": "^1.3.0",
+ "karma": "^3.0.0",
"karma-chai": "^0.1.0",
"karma-mocha": "^1.3.0",
"karma-phantomjs-launcher": "^1.0.2",
- "karma-sinon": "^1.0.5",
- "mocha": "^3.2.0",
+ "mocha": "^5.2.0",
"mocha-lcov-reporter": "^1.2.0",
"rimraf": "^2.5.4",
- "sinon": "^1.17.6",
- "sinon-chai": "^2.8.0"
+ "xo": "^0.23.0"
},
+ "files": [
+ "src",
+ "dist/debug.js",
+ "LICENSE",
+ "README.md"
+ ],
"homepage": "https://github.com/visionmedia/debug#readme",
"keywords": [
"debug",
@@ -78,5 +84,19 @@
"type": "git",
"url": "git://github.com/visionmedia/debug.git"
},
- "version": "3.1.0"
+ "scripts": {
+ "build": "npm run build:debug && npm run build:test",
+ "build:debug": "babel -o dist/debug.js dist/debug.es6.js > dist/debug.js",
+ "build:test": "babel -d dist test.js",
+ "clean": "rimraf dist coverage",
+ "lint": "xo",
+ "prebuild:debug": "mkdir -p dist && browserify --standalone debug -o dist/debug.es6.js .",
+ "pretest:browser": "npm run build",
+ "test": "npm run test:node && npm run test:browser",
+ "test:browser": "karma start --single-run",
+ "test:coverage": "cat ./coverage/lcov.info | coveralls",
+ "test:node": "istanbul cover _mocha -- test.js"
+ },
+ "unpkg": "./dist/debug.js",
+ "version": "4.1.1"
}
diff --git a/node_modules/engine.io/node_modules/debug/src/browser.js b/node_modules/engine.io/node_modules/debug/src/browser.js
index f5149ff..5f34c0d 100755
--- a/node_modules/engine.io/node_modules/debug/src/browser.js
+++ b/node_modules/engine.io/node_modules/debug/src/browser.js
@@ -1,36 +1,97 @@
+/* eslint-env browser */
+
/**
* This is the web browser implementation of `debug()`.
- *
- * Expose `debug()` as the module.
*/
-exports = module.exports = require('./debug');
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
-exports.storage = 'undefined' != typeof chrome
- && 'undefined' != typeof chrome.storage
- ? chrome.storage.local
- : localstorage();
+exports.storage = localstorage();
/**
* Colors.
*/
exports.colors = [
- '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC',
- '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF',
- '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC',
- '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF',
- '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC',
- '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033',
- '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366',
- '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933',
- '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC',
- '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF',
- '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'
+ '#0000CC',
+ '#0000FF',
+ '#0033CC',
+ '#0033FF',
+ '#0066CC',
+ '#0066FF',
+ '#0099CC',
+ '#0099FF',
+ '#00CC00',
+ '#00CC33',
+ '#00CC66',
+ '#00CC99',
+ '#00CCCC',
+ '#00CCFF',
+ '#3300CC',
+ '#3300FF',
+ '#3333CC',
+ '#3333FF',
+ '#3366CC',
+ '#3366FF',
+ '#3399CC',
+ '#3399FF',
+ '#33CC00',
+ '#33CC33',
+ '#33CC66',
+ '#33CC99',
+ '#33CCCC',
+ '#33CCFF',
+ '#6600CC',
+ '#6600FF',
+ '#6633CC',
+ '#6633FF',
+ '#66CC00',
+ '#66CC33',
+ '#9900CC',
+ '#9900FF',
+ '#9933CC',
+ '#9933FF',
+ '#99CC00',
+ '#99CC33',
+ '#CC0000',
+ '#CC0033',
+ '#CC0066',
+ '#CC0099',
+ '#CC00CC',
+ '#CC00FF',
+ '#CC3300',
+ '#CC3333',
+ '#CC3366',
+ '#CC3399',
+ '#CC33CC',
+ '#CC33FF',
+ '#CC6600',
+ '#CC6633',
+ '#CC9900',
+ '#CC9933',
+ '#CCCC00',
+ '#CCCC33',
+ '#FF0000',
+ '#FF0033',
+ '#FF0066',
+ '#FF0099',
+ '#FF00CC',
+ '#FF00FF',
+ '#FF3300',
+ '#FF3333',
+ '#FF3366',
+ '#FF3399',
+ '#FF33CC',
+ '#FF33FF',
+ '#FF6600',
+ '#FF6633',
+ '#FF9900',
+ '#FF9933',
+ '#FFCC00',
+ '#FFCC33'
];
/**
@@ -41,43 +102,31 @@ exports.colors = [
* TODO: add a `localStorage` variable to explicitly enable/disable colors
*/
+// eslint-disable-next-line complexity
function useColors() {
- // NB: In an Electron preload script, document will be defined but not fully
- // initialized. Since we know we're in Chrome, we'll just detect this case
- // explicitly
- if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
- return true;
- }
-
- // Internet Explorer and Edge do not support colors.
- if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
- return false;
- }
-
- // is webkit? http://stackoverflow.com/a/16459606/376773
- // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
- return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
- // is firebug? http://stackoverflow.com/a/398120/376773
- (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
- // is firefox >= v31?
- // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
- (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
- // double check webkit in userAgent just in case we are in a worker
- (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
-}
-
-/**
- * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
- */
+ // NB: In an Electron preload script, document will be defined but not fully
+ // initialized. Since we know we're in Chrome, we'll just detect this case
+ // explicitly
+ if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
+ return true;
+ }
-exports.formatters.j = function(v) {
- try {
- return JSON.stringify(v);
- } catch (err) {
- return '[UnexpectedJSONParseError]: ' + err.message;
- }
-};
+ // Internet Explorer and Edge do not support colors.
+ if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
+ return false;
+ }
+ // Is webkit? http://stackoverflow.com/a/16459606/376773
+ // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+ return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
+ // Is firebug? http://stackoverflow.com/a/398120/376773
+ (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
+ // Is firefox >= v31?
+ // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+ (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
+ // Double check webkit in userAgent just in case we are in a worker
+ (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
+}
/**
* Colorize log arguments if enabled.
@@ -86,36 +135,38 @@ exports.formatters.j = function(v) {
*/
function formatArgs(args) {
- var useColors = this.useColors;
-
- args[0] = (useColors ? '%c' : '')
- + this.namespace
- + (useColors ? ' %c' : ' ')
- + args[0]
- + (useColors ? '%c ' : ' ')
- + '+' + exports.humanize(this.diff);
-
- if (!useColors) return;
-
- var c = 'color: ' + this.color;
- args.splice(1, 0, c, 'color: inherit')
-
- // the final "%c" is somewhat tricky, because there could be other
- // arguments passed either before or after the %c, so we need to
- // figure out the correct index to insert the CSS into
- var index = 0;
- var lastC = 0;
- args[0].replace(/%[a-zA-Z%]/g, function(match) {
- if ('%%' === match) return;
- index++;
- if ('%c' === match) {
- // we only are interested in the *last* %c
- // (the user may have provided their own)
- lastC = index;
- }
- });
-
- args.splice(lastC, 0, c);
+ args[0] = (this.useColors ? '%c' : '') +
+ this.namespace +
+ (this.useColors ? ' %c' : ' ') +
+ args[0] +
+ (this.useColors ? '%c ' : ' ') +
+ '+' + module.exports.humanize(this.diff);
+
+ if (!this.useColors) {
+ return;
+ }
+
+ const c = 'color: ' + this.color;
+ args.splice(1, 0, c, 'color: inherit');
+
+ // The final "%c" is somewhat tricky, because there could be other
+ // arguments passed either before or after the %c, so we need to
+ // figure out the correct index to insert the CSS into
+ let index = 0;
+ let lastC = 0;
+ args[0].replace(/%[a-zA-Z%]/g, match => {
+ if (match === '%%') {
+ return;
+ }
+ index++;
+ if (match === '%c') {
+ // We only are interested in the *last* %c
+ // (the user may have provided their own)
+ lastC = index;
+ }
+ });
+
+ args.splice(lastC, 0, c);
}
/**
@@ -124,13 +175,12 @@ function formatArgs(args) {
*
* @api public
*/
-
-function log() {
- // this hackery is required for IE8/9, where
- // the `console.log` function doesn't have 'apply'
- return 'object' === typeof console
- && console.log
- && Function.prototype.apply.call(console.log, console, arguments);
+function log(...args) {
+ // This hackery is required for IE8/9, where
+ // the `console.log` function doesn't have 'apply'
+ return typeof console === 'object' &&
+ console.log &&
+ console.log(...args);
}
/**
@@ -139,15 +189,17 @@ function log() {
* @param {String} namespaces
* @api private
*/
-
function save(namespaces) {
- try {
- if (null == namespaces) {
- exports.storage.removeItem('debug');
- } else {
- exports.storage.debug = namespaces;
- }
- } catch(e) {}
+ try {
+ if (namespaces) {
+ exports.storage.setItem('debug', namespaces);
+ } else {
+ exports.storage.removeItem('debug');
+ }
+ } catch (error) {
+ // Swallow
+ // XXX (@Qix-) should we be logging these?
+ }
}
/**
@@ -156,27 +208,23 @@ function save(namespaces) {
* @return {String} returns the previously persisted debug modes
* @api private
*/
-
function load() {
- var r;
- try {
- r = exports.storage.debug;
- } catch(e) {}
+ let r;
+ try {
+ r = exports.storage.getItem('debug');
+ } catch (error) {
+ // Swallow
+ // XXX (@Qix-) should we be logging these?
+ }
- // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
- if (!r && typeof process !== 'undefined' && 'env' in process) {
- r = process.env.DEBUG;
- }
+ // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+ if (!r && typeof process !== 'undefined' && 'env' in process) {
+ r = process.env.DEBUG;
+ }
- return r;
+ return r;
}
-/**
- * Enable namespaces listed in `localStorage.debug` initially.
- */
-
-exports.enable(load());
-
/**
* Localstorage attempts to return the localstorage.
*
@@ -189,7 +237,28 @@ exports.enable(load());
*/
function localstorage() {
- try {
- return window.localStorage;
- } catch (e) {}
+ try {
+ // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
+ // The Browser also has localStorage in the global context.
+ return localStorage;
+ } catch (error) {
+ // Swallow
+ // XXX (@Qix-) should we be logging these?
+ }
}
+
+module.exports = require('./common')(exports);
+
+const {formatters} = module.exports;
+
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+formatters.j = function (v) {
+ try {
+ return JSON.stringify(v);
+ } catch (error) {
+ return '[UnexpectedJSONParseError]: ' + error.message;
+ }
+};
diff --git a/node_modules/engine.io/node_modules/debug/src/common.js b/node_modules/engine.io/node_modules/debug/src/common.js
new file mode 100644
index 0000000..2f82b8d
--- /dev/null
+++ b/node_modules/engine.io/node_modules/debug/src/common.js
@@ -0,0 +1,266 @@
+
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ */
+
+function setup(env) {
+ createDebug.debug = createDebug;
+ createDebug.default = createDebug;
+ createDebug.coerce = coerce;
+ createDebug.disable = disable;
+ createDebug.enable = enable;
+ createDebug.enabled = enabled;
+ createDebug.humanize = require('ms');
+
+ Object.keys(env).forEach(key => {
+ createDebug[key] = env[key];
+ });
+
+ /**
+ * Active `debug` instances.
+ */
+ createDebug.instances = [];
+
+ /**
+ * The currently active debug mode names, and names to skip.
+ */
+
+ createDebug.names = [];
+ createDebug.skips = [];
+
+ /**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+ */
+ createDebug.formatters = {};
+
+ /**
+ * Selects a color for a debug namespace
+ * @param {String} namespace The namespace string for the for the debug instance to be colored
+ * @return {Number|String} An ANSI color code for the given namespace
+ * @api private
+ */
+ function selectColor(namespace) {
+ let hash = 0;
+
+ for (let i = 0; i < namespace.length; i++) {
+ hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
+ hash |= 0; // Convert to 32bit integer
+ }
+
+ return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
+ }
+ createDebug.selectColor = selectColor;
+
+ /**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+ function createDebug(namespace) {
+ let prevTime;
+
+ function debug(...args) {
+ // Disabled?
+ if (!debug.enabled) {
+ return;
+ }
+
+ const self = debug;
+
+ // Set `diff` timestamp
+ const curr = Number(new Date());
+ const ms = curr - (prevTime || curr);
+ self.diff = ms;
+ self.prev = prevTime;
+ self.curr = curr;
+ prevTime = curr;
+
+ args[0] = createDebug.coerce(args[0]);
+
+ if (typeof args[0] !== 'string') {
+ // Anything else let's inspect with %O
+ args.unshift('%O');
+ }
+
+ // Apply any `formatters` transformations
+ let index = 0;
+ args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
+ // If we encounter an escaped % then don't increase the array index
+ if (match === '%%') {
+ return match;
+ }
+ index++;
+ const formatter = createDebug.formatters[format];
+ if (typeof formatter === 'function') {
+ const val = args[index];
+ match = formatter.call(self, val);
+
+ // Now we need to remove `args[index]` since it's inlined in the `format`
+ args.splice(index, 1);
+ index--;
+ }
+ return match;
+ });
+
+ // Apply env-specific formatting (colors, etc.)
+ createDebug.formatArgs.call(self, args);
+
+ const logFn = self.log || createDebug.log;
+ logFn.apply(self, args);
+ }
+
+ debug.namespace = namespace;
+ debug.enabled = createDebug.enabled(namespace);
+ debug.useColors = createDebug.useColors();
+ debug.color = selectColor(namespace);
+ debug.destroy = destroy;
+ debug.extend = extend;
+ // Debug.formatArgs = formatArgs;
+ // debug.rawLog = rawLog;
+
+ // env-specific initialization logic for debug instances
+ if (typeof createDebug.init === 'function') {
+ createDebug.init(debug);
+ }
+
+ createDebug.instances.push(debug);
+
+ return debug;
+ }
+
+ function destroy() {
+ const index = createDebug.instances.indexOf(this);
+ if (index !== -1) {
+ createDebug.instances.splice(index, 1);
+ return true;
+ }
+ return false;
+ }
+
+ function extend(namespace, delimiter) {
+ const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
+ newDebug.log = this.log;
+ return newDebug;
+ }
+
+ /**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+ function enable(namespaces) {
+ createDebug.save(namespaces);
+
+ createDebug.names = [];
+ createDebug.skips = [];
+
+ let i;
+ const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+ const len = split.length;
+
+ for (i = 0; i < len; i++) {
+ if (!split[i]) {
+ // ignore empty strings
+ continue;
+ }
+
+ namespaces = split[i].replace(/\*/g, '.*?');
+
+ if (namespaces[0] === '-') {
+ createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+ } else {
+ createDebug.names.push(new RegExp('^' + namespaces + '$'));
+ }
+ }
+
+ for (i = 0; i < createDebug.instances.length; i++) {
+ const instance = createDebug.instances[i];
+ instance.enabled = createDebug.enabled(instance.namespace);
+ }
+ }
+
+ /**
+ * Disable debug output.
+ *
+ * @return {String} namespaces
+ * @api public
+ */
+ function disable() {
+ const namespaces = [
+ ...createDebug.names.map(toNamespace),
+ ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace)
+ ].join(',');
+ createDebug.enable('');
+ return namespaces;
+ }
+
+ /**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+ function enabled(name) {
+ if (name[name.length - 1] === '*') {
+ return true;
+ }
+
+ let i;
+ let len;
+
+ for (i = 0, len = createDebug.skips.length; i < len; i++) {
+ if (createDebug.skips[i].test(name)) {
+ return false;
+ }
+ }
+
+ for (i = 0, len = createDebug.names.length; i < len; i++) {
+ if (createDebug.names[i].test(name)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Convert regexp to namespace
+ *
+ * @param {RegExp} regxep
+ * @return {String} namespace
+ * @api private
+ */
+ function toNamespace(regexp) {
+ return regexp.toString()
+ .substring(2, regexp.toString().length - 2)
+ .replace(/\.\*\?$/, '*');
+ }
+
+ /**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+ function coerce(val) {
+ if (val instanceof Error) {
+ return val.stack || val.message;
+ }
+ return val;
+ }
+
+ createDebug.enable(createDebug.load());
+
+ return createDebug;
+}
+
+module.exports = setup;
diff --git a/node_modules/engine.io/node_modules/debug/src/debug.js b/node_modules/engine.io/node_modules/debug/src/debug.js
deleted file mode 100755
index 77e6384..0000000
--- a/node_modules/engine.io/node_modules/debug/src/debug.js
+++ /dev/null
@@ -1,225 +0,0 @@
-
-/**
- * This is the common logic for both the Node.js and web browser
- * implementations of `debug()`.
- *
- * Expose `debug()` as the module.
- */
-
-exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
-exports.coerce = coerce;
-exports.disable = disable;
-exports.enable = enable;
-exports.enabled = enabled;
-exports.humanize = require('ms');
-
-/**
- * Active `debug` instances.
- */
-exports.instances = [];
-
-/**
- * The currently active debug mode names, and names to skip.
- */
-
-exports.names = [];
-exports.skips = [];
-
-/**
- * Map of special "%n" handling functions, for the debug "format" argument.
- *
- * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
- */
-
-exports.formatters = {};
-
-/**
- * Select a color.
- * @param {String} namespace
- * @return {Number}
- * @api private
- */
-
-function selectColor(namespace) {
- var hash = 0, i;
-
- for (i in namespace) {
- hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
- hash |= 0; // Convert to 32bit integer
- }
-
- return exports.colors[Math.abs(hash) % exports.colors.length];
-}
-
-/**
- * Create a debugger with the given `namespace`.
- *
- * @param {String} namespace
- * @return {Function}
- * @api public
- */
-
-function createDebug(namespace) {
-
- var prevTime;
-
- function debug() {
- // disabled?
- if (!debug.enabled) return;
-
- var self = debug;
-
- // set `diff` timestamp
- var curr = +new Date();
- var ms = curr - (prevTime || curr);
- self.diff = ms;
- self.prev = prevTime;
- self.curr = curr;
- prevTime = curr;
-
- // turn the `arguments` into a proper Array
- var args = new Array(arguments.length);
- for (var i = 0; i < args.length; i++) {
- args[i] = arguments[i];
- }
-
- args[0] = exports.coerce(args[0]);
-
- if ('string' !== typeof args[0]) {
- // anything else let's inspect with %O
- args.unshift('%O');
- }
-
- // apply any `formatters` transformations
- var index = 0;
- args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
- // if we encounter an escaped % then don't increase the array index
- if (match === '%%') return match;
- index++;
- var formatter = exports.formatters[format];
- if ('function' === typeof formatter) {
- var val = args[index];
- match = formatter.call(self, val);
-
- // now we need to remove `args[index]` since it's inlined in the `format`
- args.splice(index, 1);
- index--;
- }
- return match;
- });
-
- // apply env-specific formatting (colors, etc.)
- exports.formatArgs.call(self, args);
-
- var logFn = debug.log || exports.log || console.log.bind(console);
- logFn.apply(self, args);
- }
-
- debug.namespace = namespace;
- debug.enabled = exports.enabled(namespace);
- debug.useColors = exports.useColors();
- debug.color = selectColor(namespace);
- debug.destroy = destroy;
-
- // env-specific initialization logic for debug instances
- if ('function' === typeof exports.init) {
- exports.init(debug);
- }
-
- exports.instances.push(debug);
-
- return debug;
-}
-
-function destroy () {
- var index = exports.instances.indexOf(this);
- if (index !== -1) {
- exports.instances.splice(index, 1);
- return true;
- } else {
- return false;
- }
-}
-
-/**
- * Enables a debug mode by namespaces. This can include modes
- * separated by a colon and wildcards.
- *
- * @param {String} namespaces
- * @api public
- */
-
-function enable(namespaces) {
- exports.save(namespaces);
-
- exports.names = [];
- exports.skips = [];
-
- var i;
- var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
- var len = split.length;
-
- for (i = 0; i < len; i++) {
- if (!split[i]) continue; // ignore empty strings
- namespaces = split[i].replace(/\*/g, '.*?');
- if (namespaces[0] === '-') {
- exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
- } else {
- exports.names.push(new RegExp('^' + namespaces + '$'));
- }
- }
-
- for (i = 0; i < exports.instances.length; i++) {
- var instance = exports.instances[i];
- instance.enabled = exports.enabled(instance.namespace);
- }
-}
-
-/**
- * Disable debug output.
- *
- * @api public
- */
-
-function disable() {
- exports.enable('');
-}
-
-/**
- * Returns true if the given mode name is enabled, false otherwise.
- *
- * @param {String} name
- * @return {Boolean}
- * @api public
- */
-
-function enabled(name) {
- if (name[name.length - 1] === '*') {
- return true;
- }
- var i, len;
- for (i = 0, len = exports.skips.length; i < len; i++) {
- if (exports.skips[i].test(name)) {
- return false;
- }
- }
- for (i = 0, len = exports.names.length; i < len; i++) {
- if (exports.names[i].test(name)) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Coerce `val`.
- *
- * @param {Mixed} val
- * @return {Mixed}
- * @api private
- */
-
-function coerce(val) {
- if (val instanceof Error) return val.stack || val.message;
- return val;
-}
diff --git a/node_modules/engine.io/node_modules/debug/src/index.js b/node_modules/engine.io/node_modules/debug/src/index.js
index cabcbcd..bf4c57f 100755
--- a/node_modules/engine.io/node_modules/debug/src/index.js
+++ b/node_modules/engine.io/node_modules/debug/src/index.js
@@ -1,10 +1,10 @@
/**
- * Detect Electron renderer process, which is node, but we should
+ * Detect Electron renderer / nwjs process, which is node, but we should
* treat as a browser.
*/
-if (typeof process === 'undefined' || process.type === 'renderer') {
- module.exports = require('./browser.js');
+if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
+ module.exports = require('./browser.js');
} else {
- module.exports = require('./node.js');
+ module.exports = require('./node.js');
}
diff --git a/node_modules/engine.io/node_modules/debug/src/node.js b/node_modules/engine.io/node_modules/debug/src/node.js
index d666fb9..5e1f154 100755
--- a/node_modules/engine.io/node_modules/debug/src/node.js
+++ b/node_modules/engine.io/node_modules/debug/src/node.js
@@ -2,16 +2,13 @@
* Module dependencies.
*/
-var tty = require('tty');
-var util = require('util');
+const tty = require('tty');
+const util = require('util');
/**
* This is the Node.js implementation of `debug()`.
- *
- * Expose `debug()` as the module.
*/
-exports = module.exports = require('./debug');
exports.init = init;
exports.log = log;
exports.formatArgs = formatArgs;
@@ -23,21 +20,95 @@ exports.useColors = useColors;
* Colors.
*/
-exports.colors = [ 6, 2, 3, 4, 5, 1 ];
+exports.colors = [6, 2, 3, 4, 5, 1];
try {
- var supportsColor = require('supports-color');
- if (supportsColor && supportsColor.level >= 2) {
- exports.colors = [
- 20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68,
- 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134,
- 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
- 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204,
- 205, 206, 207, 208, 209, 214, 215, 220, 221
- ];
- }
-} catch (err) {
- // swallow - we only care if `supports-color` is available; it doesn't have to be.
+ // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
+ // eslint-disable-next-line import/no-extraneous-dependencies
+ const supportsColor = require('supports-color');
+
+ if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
+ exports.colors = [
+ 20,
+ 21,
+ 26,
+ 27,
+ 32,
+ 33,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 56,
+ 57,
+ 62,
+ 63,
+ 68,
+ 69,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 92,
+ 93,
+ 98,
+ 99,
+ 112,
+ 113,
+ 128,
+ 129,
+ 134,
+ 135,
+ 148,
+ 149,
+ 160,
+ 161,
+ 162,
+ 163,
+ 164,
+ 165,
+ 166,
+ 167,
+ 168,
+ 169,
+ 170,
+ 171,
+ 172,
+ 173,
+ 178,
+ 179,
+ 184,
+ 185,
+ 196,
+ 197,
+ 198,
+ 199,
+ 200,
+ 201,
+ 202,
+ 203,
+ 204,
+ 205,
+ 206,
+ 207,
+ 208,
+ 209,
+ 214,
+ 215,
+ 220,
+ 221
+ ];
+ }
+} catch (error) {
+ // Swallow - we only care if `supports-color` is available; it doesn't have to be.
}
/**
@@ -46,24 +117,31 @@ try {
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
*/
-exports.inspectOpts = Object.keys(process.env).filter(function (key) {
- return /^debug_/i.test(key);
-}).reduce(function (obj, key) {
- // camel-case
- var prop = key
- .substring(6)
- .toLowerCase()
- .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
-
- // coerce string value into JS value
- var val = process.env[key];
- if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
- else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
- else if (val === 'null') val = null;
- else val = Number(val);
-
- obj[prop] = val;
- return obj;
+exports.inspectOpts = Object.keys(process.env).filter(key => {
+ return /^debug_/i.test(key);
+}).reduce((obj, key) => {
+ // Camel-case
+ const prop = key
+ .substring(6)
+ .toLowerCase()
+ .replace(/_([a-z])/g, (_, k) => {
+ return k.toUpperCase();
+ });
+
+ // Coerce string value into JS value
+ let val = process.env[key];
+ if (/^(yes|on|true|enabled)$/i.test(val)) {
+ val = true;
+ } else if (/^(no|off|false|disabled)$/i.test(val)) {
+ val = false;
+ } else if (val === 'null') {
+ val = null;
+ } else {
+ val = Number(val);
+ }
+
+ obj[prop] = val;
+ return obj;
}, {});
/**
@@ -71,32 +149,11 @@ exports.inspectOpts = Object.keys(process.env).filter(function (key) {
*/
function useColors() {
- return 'colors' in exports.inspectOpts
- ? Boolean(exports.inspectOpts.colors)
- : tty.isatty(process.stderr.fd);
+ return 'colors' in exports.inspectOpts ?
+ Boolean(exports.inspectOpts.colors) :
+ tty.isatty(process.stderr.fd);
}
-/**
- * Map %o to `util.inspect()`, all on a single line.
- */
-
-exports.formatters.o = function(v) {
- this.inspectOpts.colors = this.useColors;
- return util.inspect(v, this.inspectOpts)
- .split('\n').map(function(str) {
- return str.trim()
- }).join(' ');
-};
-
-/**
- * Map %o to `util.inspect()`, allowing multiple lines if needed.
- */
-
-exports.formatters.O = function(v) {
- this.inspectOpts.colors = this.useColors;
- return util.inspect(v, this.inspectOpts);
-};
-
/**
* Adds ANSI color escape codes if enabled.
*
@@ -104,35 +161,33 @@ exports.formatters.O = function(v) {
*/
function formatArgs(args) {
- var name = this.namespace;
- var useColors = this.useColors;
-
- if (useColors) {
- var c = this.color;
- var colorCode = '\u001b[3' + (c < 8 ? c : '8;5;' + c);
- var prefix = ' ' + colorCode + ';1m' + name + ' ' + '\u001b[0m';
-
- args[0] = prefix + args[0].split('\n').join('\n' + prefix);
- args.push(colorCode + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
- } else {
- args[0] = getDate() + name + ' ' + args[0];
- }
+ const {namespace: name, useColors} = this;
+
+ if (useColors) {
+ const c = this.color;
+ const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
+ const prefix = ` ${colorCode};1m${name} \u001B[0m`;
+
+ args[0] = prefix + args[0].split('\n').join('\n' + prefix);
+ args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m');
+ } else {
+ args[0] = getDate() + name + ' ' + args[0];
+ }
}
function getDate() {
- if (exports.inspectOpts.hideDate) {
- return '';
- } else {
- return new Date().toISOString() + ' ';
- }
+ if (exports.inspectOpts.hideDate) {
+ return '';
+ }
+ return new Date().toISOString() + ' ';
}
/**
* Invokes `util.format()` with the specified arguments and writes to stderr.
*/
-function log() {
- return process.stderr.write(util.format.apply(util, arguments) + '\n');
+function log(...args) {
+ return process.stderr.write(util.format(...args) + '\n');
}
/**
@@ -141,15 +196,14 @@ function log() {
* @param {String} namespaces
* @api private
*/
-
function save(namespaces) {
- if (null == namespaces) {
- // If you set a process.env field to null or undefined, it gets cast to the
- // string 'null' or 'undefined'. Just delete instead.
- delete process.env.DEBUG;
- } else {
- process.env.DEBUG = namespaces;
- }
+ if (namespaces) {
+ process.env.DEBUG = namespaces;
+ } else {
+ // If you set a process.env field to null or undefined, it gets cast to the
+ // string 'null' or 'undefined'. Just delete instead.
+ delete process.env.DEBUG;
+ }
}
/**
@@ -160,7 +214,7 @@ function save(namespaces) {
*/
function load() {
- return process.env.DEBUG;
+ return process.env.DEBUG;
}
/**
@@ -170,17 +224,34 @@ function load() {
* differently for a particular `debug` instance.
*/
-function init (debug) {
- debug.inspectOpts = {};
+function init(debug) {
+ debug.inspectOpts = {};
- var keys = Object.keys(exports.inspectOpts);
- for (var i = 0; i < keys.length; i++) {
- debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
- }
+ const keys = Object.keys(exports.inspectOpts);
+ for (let i = 0; i < keys.length; i++) {
+ debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
+ }
}
+module.exports = require('./common')(exports);
+
+const {formatters} = module.exports;
+
/**
- * Enable namespaces listed in `process.env.DEBUG` initially.
+ * Map %o to `util.inspect()`, all on a single line.
*/
-exports.enable(load());
+formatters.o = function (v) {
+ this.inspectOpts.colors = this.useColors;
+ return util.inspect(v, this.inspectOpts)
+ .replace(/\s*\n\s*/g, ' ');
+};
+
+/**
+ * Map %O to `util.inspect()`, allowing multiple lines if needed.
+ */
+
+formatters.O = function (v) {
+ this.inspectOpts.colors = this.useColors;
+ return util.inspect(v, this.inspectOpts);
+};
diff --git a/node_modules/engine.io/node_modules/ms/index.js b/node_modules/engine.io/node_modules/ms/index.js
new file mode 100644
index 0000000..ea734fb
--- /dev/null
+++ b/node_modules/engine.io/node_modules/ms/index.js
@@ -0,0 +1,162 @@
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var w = d * 7;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ * - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function (val, options) {
+ options = options || {};
+ var type = typeof val;
+ if (type === 'string' && val.length > 0) {
+ return parse(val);
+ } else if (type === 'number' && isFinite(val)) {
+ return options.long ? fmtLong(val) : fmtShort(val);
+ }
+ throw new Error(
+ 'val is not a non-empty string or a valid number. val=' +
+ JSON.stringify(val)
+ );
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+ str = String(str);
+ if (str.length > 100) {
+ return;
+ }
+ var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
+ str
+ );
+ if (!match) {
+ return;
+ }
+ var n = parseFloat(match[1]);
+ var type = (match[2] || 'ms').toLowerCase();
+ switch (type) {
+ case 'years':
+ case 'year':
+ case 'yrs':
+ case 'yr':
+ case 'y':
+ return n * y;
+ case 'weeks':
+ case 'week':
+ case 'w':
+ return n * w;
+ case 'days':
+ case 'day':
+ case 'd':
+ return n * d;
+ case 'hours':
+ case 'hour':
+ case 'hrs':
+ case 'hr':
+ case 'h':
+ return n * h;
+ case 'minutes':
+ case 'minute':
+ case 'mins':
+ case 'min':
+ case 'm':
+ return n * m;
+ case 'seconds':
+ case 'second':
+ case 'secs':
+ case 'sec':
+ case 's':
+ return n * s;
+ case 'milliseconds':
+ case 'millisecond':
+ case 'msecs':
+ case 'msec':
+ case 'ms':
+ return n;
+ default:
+ return undefined;
+ }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtShort(ms) {
+ var msAbs = Math.abs(ms);
+ if (msAbs >= d) {
+ return Math.round(ms / d) + 'd';
+ }
+ if (msAbs >= h) {
+ return Math.round(ms / h) + 'h';
+ }
+ if (msAbs >= m) {
+ return Math.round(ms / m) + 'm';
+ }
+ if (msAbs >= s) {
+ return Math.round(ms / s) + 's';
+ }
+ return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtLong(ms) {
+ var msAbs = Math.abs(ms);
+ if (msAbs >= d) {
+ return plural(ms, msAbs, d, 'day');
+ }
+ if (msAbs >= h) {
+ return plural(ms, msAbs, h, 'hour');
+ }
+ if (msAbs >= m) {
+ return plural(ms, msAbs, m, 'minute');
+ }
+ if (msAbs >= s) {
+ return plural(ms, msAbs, s, 'second');
+ }
+ return ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, msAbs, n, name) {
+ var isPlural = msAbs >= n * 1.5;
+ return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
+}
diff --git a/node_modules/engine.io/node_modules/ms/license.md b/node_modules/engine.io/node_modules/ms/license.md
new file mode 100644
index 0000000..fa5d39b
--- /dev/null
+++ b/node_modules/engine.io/node_modules/ms/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2020 Vercel, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/engine.io/node_modules/ms/package.json b/node_modules/engine.io/node_modules/ms/package.json
new file mode 100644
index 0000000..35394e4
--- /dev/null
+++ b/node_modules/engine.io/node_modules/ms/package.json
@@ -0,0 +1,70 @@
+{
+ "_from": "ms@^2.1.1",
+ "_id": "ms@2.1.3",
+ "_inBundle": false,
+ "_integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "_location": "/engine.io/ms",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "range",
+ "registry": true,
+ "raw": "ms@^2.1.1",
+ "name": "ms",
+ "escapedName": "ms",
+ "rawSpec": "^2.1.1",
+ "saveSpec": null,
+ "fetchSpec": "^2.1.1"
+ },
+ "_requiredBy": [
+ "/engine.io/debug"
+ ],
+ "_resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "_shasum": "574c8138ce1d2b5861f0b44579dbadd60c6615b2",
+ "_spec": "ms@^2.1.1",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\engine.io\\node_modules\\debug",
+ "bugs": {
+ "url": "https://github.com/vercel/ms/issues"
+ },
+ "bundleDependencies": false,
+ "deprecated": false,
+ "description": "Tiny millisecond conversion utility",
+ "devDependencies": {
+ "eslint": "4.18.2",
+ "expect.js": "0.3.1",
+ "husky": "0.14.3",
+ "lint-staged": "5.0.0",
+ "mocha": "4.0.1",
+ "prettier": "2.0.5"
+ },
+ "eslintConfig": {
+ "extends": "eslint:recommended",
+ "env": {
+ "node": true,
+ "es6": true
+ }
+ },
+ "files": [
+ "index.js"
+ ],
+ "homepage": "https://github.com/vercel/ms#readme",
+ "license": "MIT",
+ "lint-staged": {
+ "*.js": [
+ "npm run lint",
+ "prettier --single-quote --write",
+ "git add"
+ ]
+ },
+ "main": "./index",
+ "name": "ms",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/vercel/ms.git"
+ },
+ "scripts": {
+ "lint": "eslint lib/* bin/*",
+ "precommit": "lint-staged",
+ "test": "mocha tests.js"
+ },
+ "version": "2.1.3"
+}
diff --git a/node_modules/engine.io/node_modules/ms/readme.md b/node_modules/engine.io/node_modules/ms/readme.md
new file mode 100644
index 0000000..0fc1abb
--- /dev/null
+++ b/node_modules/engine.io/node_modules/ms/readme.md
@@ -0,0 +1,59 @@
+# ms
+
+![CI](https://github.com/vercel/ms/workflows/CI/badge.svg)
+
+Use this package to easily convert various time formats to milliseconds.
+
+## Examples
+
+```js
+ms('2 days') // 172800000
+ms('1d') // 86400000
+ms('10h') // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h') // 7200000
+ms('1m') // 60000
+ms('5s') // 5000
+ms('1y') // 31557600000
+ms('100') // 100
+ms('-3 days') // -259200000
+ms('-1h') // -3600000
+ms('-200') // -200
+```
+
+### Convert from Milliseconds
+
+```js
+ms(60000) // "1m"
+ms(2 * 60000) // "2m"
+ms(-3 * 60000) // "-3m"
+ms(ms('10 hours')) // "10h"
+```
+
+### Time Format Written-Out
+
+```js
+ms(60000, { long: true }) // "1 minute"
+ms(2 * 60000, { long: true }) // "2 minutes"
+ms(-3 * 60000, { long: true }) // "-3 minutes"
+ms(ms('10 hours'), { long: true }) // "10 hours"
+```
+
+## Features
+
+- Works both in [Node.js](https://nodejs.org) and in the browser
+- If a number is supplied to `ms`, a string with a unit is returned
+- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`)
+- If you pass a string with a number and a valid unit, the number of equivalent milliseconds is returned
+
+## Related Packages
+
+- [ms.macro](https://github.com/knpwrs/ms.macro) - Run `ms` as a macro at build-time.
+
+## Caught a Bug?
+
+1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
+2. Link the package to the global module directory: `npm link`
+3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, Node.js will now use your clone of ms!
+
+As always, you can run the tests using: `npm test`
diff --git a/node_modules/engine.io/package.json b/node_modules/engine.io/package.json
index 8d7784a..fe746f5 100755
--- a/node_modules/engine.io/package.json
+++ b/node_modules/engine.io/package.json
@@ -1,29 +1,27 @@
{
- "_from": "engine.io@~3.3.1",
- "_id": "engine.io@3.3.2",
+ "_from": "engine.io@~3.5.0",
+ "_id": "engine.io@3.5.0",
"_inBundle": false,
- "_integrity": "sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w==",
+ "_integrity": "sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA==",
"_location": "/engine.io",
- "_phantomChildren": {
- "ms": "2.0.0"
- },
+ "_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
- "raw": "engine.io@~3.3.1",
+ "raw": "engine.io@~3.5.0",
"name": "engine.io",
"escapedName": "engine.io",
- "rawSpec": "~3.3.1",
+ "rawSpec": "~3.5.0",
"saveSpec": null,
- "fetchSpec": "~3.3.1"
+ "fetchSpec": "~3.5.0"
},
"_requiredBy": [
"/socket.io"
],
- "_resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.3.2.tgz",
- "_shasum": "18cbc8b6f36e9461c5c0f81df2b830de16058a59",
- "_spec": "engine.io@~3.3.1",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/socket.io",
+ "_resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.5.0.tgz",
+ "_shasum": "9d6b985c8a39b1fe87cd91eb014de0552259821b",
+ "_spec": "engine.io@~3.5.0",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\socket.io",
"author": {
"name": "Guillermo Rauch",
"email": "guillermo@learnboost.com"
@@ -52,18 +50,18 @@
],
"dependencies": {
"accepts": "~1.3.4",
- "base64id": "1.0.0",
- "cookie": "0.3.1",
- "debug": "~3.1.0",
- "engine.io-parser": "~2.1.0",
- "ws": "~6.1.0"
+ "base64id": "2.0.0",
+ "cookie": "~0.4.1",
+ "debug": "~4.1.0",
+ "engine.io-parser": "~2.2.0",
+ "ws": "~7.4.2"
},
"deprecated": false,
"description": "The realtime engine behind Socket.IO. Provides the foundation of a bidirectional connection between client and server",
"devDependencies": {
"babel-eslint": "^8.0.2",
"babel-preset-es2015": "^6.24.0",
- "engine.io-client": "3.3.1",
+ "engine.io-client": "3.5.0",
"eslint": "^4.5.0",
"eslint-config-standard": "^10.2.1",
"eslint-plugin-import": "^2.7.0",
@@ -76,6 +74,9 @@
"superagent": "^3.8.1",
"uws": "~9.14.0"
},
+ "engines": {
+ "node": ">=8.0.0"
+ },
"files": [
"lib/"
],
@@ -91,5 +92,5 @@
"lint": "eslint lib/ test/ *.js",
"test": "npm run lint && mocha && EIO_WS_ENGINE=uws mocha"
},
- "version": "3.3.2"
+ "version": "3.5.0"
}
diff --git a/node_modules/is-ci/LICENSE b/node_modules/is-ci/LICENSE
old mode 100755
new mode 100644
diff --git a/node_modules/is-ci/README.md b/node_modules/is-ci/README.md
old mode 100755
new mode 100644
diff --git a/node_modules/is-ci/index.js b/node_modules/is-ci/index.js
old mode 100755
new mode 100644
diff --git a/node_modules/is-ci/package.json b/node_modules/is-ci/package.json
old mode 100755
new mode 100644
index f420180..2d567b0
--- a/node_modules/is-ci/package.json
+++ b/node_modules/is-ci/package.json
@@ -1,53 +1,23 @@
{
- "_from": "is-ci@^1.0.10",
- "_id": "is-ci@1.2.1",
- "_inBundle": false,
- "_integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
- "_location": "/is-ci",
- "_phantomChildren": {},
- "_requested": {
- "type": "range",
- "registry": true,
- "raw": "is-ci@^1.0.10",
- "name": "is-ci",
- "escapedName": "is-ci",
- "rawSpec": "^1.0.10",
- "saveSpec": null,
- "fetchSpec": "^1.0.10"
- },
- "_requiredBy": [
- "/update-notifier"
- ],
- "_resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
- "_shasum": "e3779c8ee17fccf428488f6e281187f2e632841c",
- "_spec": "is-ci@^1.0.10",
- "_where": "/home/pi/Node Projects/x-chat/node_modules/update-notifier",
- "author": {
- "name": "Thomas Watson Steen",
- "email": "w@tson.dk",
- "url": "https://twitter.com/wa7son"
- },
- "bin": {
- "is-ci": "bin.js"
- },
- "bugs": {
- "url": "https://github.com/watson/is-ci/issues"
- },
- "bundleDependencies": false,
- "coordinates": [
- 55.778255,
- 12.593033
- ],
+ "name": "is-ci",
+ "version": "1.2.1",
+ "description": "Detect if the current environment is a CI server",
+ "bin": "bin.js",
+ "main": "index.js",
"dependencies": {
"ci-info": "^1.5.0"
},
- "deprecated": false,
- "description": "Detect if the current environment is a CI server",
"devDependencies": {
"clear-require": "^1.0.1",
"standard": "^11.0.1"
},
- "homepage": "https://github.com/watson/is-ci",
+ "scripts": {
+ "test": "standard && node test.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/watson/is-ci.git"
+ },
"keywords": [
"ci",
"continuous",
@@ -55,15 +25,14 @@
"test",
"detect"
],
+ "author": "Thomas Watson Steen (https://twitter.com/wa7son)",
"license": "MIT",
- "main": "index.js",
- "name": "is-ci",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/watson/is-ci.git"
- },
- "scripts": {
- "test": "standard && node test.js"
+ "bugs": {
+ "url": "https://github.com/watson/is-ci/issues"
},
- "version": "1.2.1"
+ "homepage": "https://github.com/watson/is-ci",
+ "coordinates": [
+ 55.778255,
+ 12.593033
+ ]
}
diff --git a/node_modules/mime/.npmignore b/node_modules/mime/.npmignore
old mode 100755
new mode 100644
diff --git a/node_modules/mime/CHANGELOG.md b/node_modules/mime/CHANGELOG.md
old mode 100755
new mode 100644
diff --git a/node_modules/mime/LICENSE b/node_modules/mime/LICENSE
old mode 100755
new mode 100644
diff --git a/node_modules/mime/README.md b/node_modules/mime/README.md
old mode 100755
new mode 100644
diff --git a/node_modules/mime/mime.js b/node_modules/mime/mime.js
old mode 100755
new mode 100644
diff --git a/node_modules/mime/package.json b/node_modules/mime/package.json
old mode 100755
new mode 100644
index 529909d..6bd24bc
--- a/node_modules/mime/package.json
+++ b/node_modules/mime/package.json
@@ -1,73 +1,44 @@
{
- "_from": "mime@1.6.0",
- "_id": "mime@1.6.0",
- "_inBundle": false,
- "_integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "_location": "/mime",
- "_phantomChildren": {},
- "_requested": {
- "type": "version",
- "registry": true,
- "raw": "mime@1.6.0",
- "name": "mime",
- "escapedName": "mime",
- "rawSpec": "1.6.0",
- "saveSpec": null,
- "fetchSpec": "1.6.0"
- },
- "_requiredBy": [
- "/send"
- ],
- "_resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "_shasum": "32cd9e5c64553bd58d19a568af452acff04981b1",
- "_spec": "mime@1.6.0",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/send",
"author": {
"name": "Robert Kieffer",
- "email": "robert@broofa.com",
- "url": "http://github.com/broofa"
+ "url": "http://github.com/broofa",
+ "email": "robert@broofa.com"
},
"bin": {
"mime": "cli.js"
},
- "bugs": {
- "url": "https://github.com/broofa/node-mime/issues"
+ "engines": {
+ "node": ">=4"
},
- "bundleDependencies": false,
"contributors": [
{
"name": "Benjamin Thomas",
- "email": "benjamin@benjaminthomas.org",
- "url": "http://github.com/bentomas"
+ "url": "http://github.com/bentomas",
+ "email": "benjamin@benjaminthomas.org"
}
],
- "dependencies": {},
- "deprecated": false,
"description": "A comprehensive library for mime-type mapping",
+ "license": "MIT",
+ "dependencies": {},
"devDependencies": {
"github-release-notes": "0.13.1",
"mime-db": "1.31.0",
"mime-score": "1.1.0"
},
- "engines": {
- "node": ">=4"
+ "scripts": {
+ "prepare": "node src/build.js",
+ "changelog": "gren changelog --tags=all --generate --override",
+ "test": "node src/test.js"
},
- "homepage": "https://github.com/broofa/node-mime#readme",
"keywords": [
"util",
"mime"
],
- "license": "MIT",
"main": "mime.js",
"name": "mime",
"repository": {
- "url": "git+https://github.com/broofa/node-mime.git",
+ "url": "https://github.com/broofa/node-mime",
"type": "git"
},
- "scripts": {
- "changelog": "gren changelog --tags=all --generate --override",
- "prepare": "node src/build.js",
- "test": "node src/test.js"
- },
"version": "1.6.0"
}
diff --git a/node_modules/mime/src/test.js b/node_modules/mime/src/test.js
old mode 100755
new mode 100644
diff --git a/node_modules/mime/types.json b/node_modules/mime/types.json
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/.jscsrc b/node_modules/nodemon/.jscsrc
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/.jshintrc b/node_modules/nodemon/.jshintrc
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/.travis.yml b/node_modules/nodemon/.travis.yml
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/README.md b/node_modules/nodemon/README.md
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/commitlint.config.js b/node_modules/nodemon/commitlint.config.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/doc/cli/authors.txt b/node_modules/nodemon/doc/cli/authors.txt
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/doc/cli/config.txt b/node_modules/nodemon/doc/cli/config.txt
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/doc/cli/help.txt b/node_modules/nodemon/doc/cli/help.txt
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/doc/cli/logo.txt b/node_modules/nodemon/doc/cli/logo.txt
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/doc/cli/options.txt b/node_modules/nodemon/doc/cli/options.txt
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/doc/cli/topics.txt b/node_modules/nodemon/doc/cli/topics.txt
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/doc/cli/usage.txt b/node_modules/nodemon/doc/cli/usage.txt
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/doc/cli/whoami.txt b/node_modules/nodemon/doc/cli/whoami.txt
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/cli/index.js b/node_modules/nodemon/lib/cli/index.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/cli/parse.js b/node_modules/nodemon/lib/cli/parse.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/config/command.js b/node_modules/nodemon/lib/config/command.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/config/defaults.js b/node_modules/nodemon/lib/config/defaults.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/config/exec.js b/node_modules/nodemon/lib/config/exec.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/config/index.js b/node_modules/nodemon/lib/config/index.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/config/load.js b/node_modules/nodemon/lib/config/load.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/help/index.js b/node_modules/nodemon/lib/help/index.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/index.js b/node_modules/nodemon/lib/index.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/monitor/index.js b/node_modules/nodemon/lib/monitor/index.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/monitor/match.js b/node_modules/nodemon/lib/monitor/match.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/monitor/run.js b/node_modules/nodemon/lib/monitor/run.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/monitor/signals.js b/node_modules/nodemon/lib/monitor/signals.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/monitor/watch.js b/node_modules/nodemon/lib/monitor/watch.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/nodemon.js b/node_modules/nodemon/lib/nodemon.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/rules/add.js b/node_modules/nodemon/lib/rules/add.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/rules/index.js b/node_modules/nodemon/lib/rules/index.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/rules/parse.js b/node_modules/nodemon/lib/rules/parse.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/spawn.js b/node_modules/nodemon/lib/spawn.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/utils/bus.js b/node_modules/nodemon/lib/utils/bus.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/utils/clone.js b/node_modules/nodemon/lib/utils/clone.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/utils/colour.js b/node_modules/nodemon/lib/utils/colour.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/utils/index.js b/node_modules/nodemon/lib/utils/index.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/utils/log.js b/node_modules/nodemon/lib/utils/log.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/utils/merge.js b/node_modules/nodemon/lib/utils/merge.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/lib/version.js b/node_modules/nodemon/lib/version.js
old mode 100755
new mode 100644
diff --git a/node_modules/nodemon/package.json b/node_modules/nodemon/package.json
old mode 100755
new mode 100644
index 67d38d4..d5c9c27
--- a/node_modules/nodemon/package.json
+++ b/node_modules/nodemon/package.json
@@ -1,99 +1 @@
-{
- "_from": "nodemon@^1.19.4",
- "_id": "nodemon@1.19.4",
- "_inBundle": false,
- "_integrity": "sha512-VGPaqQBNk193lrJFotBU8nvWZPqEZY2eIzymy2jjY0fJ9qIsxA0sxQ8ATPl0gZC645gijYEc1jtZvpS8QWzJGQ==",
- "_location": "/nodemon",
- "_phantomChildren": {},
- "_requested": {
- "type": "range",
- "registry": true,
- "raw": "nodemon@^1.19.4",
- "name": "nodemon",
- "escapedName": "nodemon",
- "rawSpec": "^1.19.4",
- "saveSpec": null,
- "fetchSpec": "^1.19.4"
- },
- "_requiredBy": [
- "#USER",
- "/"
- ],
- "_resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.4.tgz",
- "_shasum": "56db5c607408e0fdf8920d2b444819af1aae0971",
- "_spec": "nodemon@^1.19.4",
- "_where": "/home/pi/Node Projects/x-chat",
- "author": {
- "name": "Remy Sharp",
- "url": "http://github.com/remy"
- },
- "bin": {
- "nodemon": "./bin/nodemon.js"
- },
- "bugs": {
- "url": "https://github.com/remy/nodemon/issues"
- },
- "bundleDependencies": false,
- "dependencies": {
- "chokidar": "^2.1.8",
- "debug": "^3.2.6",
- "ignore-by-default": "^1.0.1",
- "minimatch": "^3.0.4",
- "pstree.remy": "^1.1.7",
- "semver": "^5.7.1",
- "supports-color": "^5.5.0",
- "touch": "^3.1.0",
- "undefsafe": "^2.0.2",
- "update-notifier": "^2.5.0"
- },
- "deprecated": false,
- "description": "Simple monitor script for use during development of a node.js app.",
- "devDependencies": {
- "@commitlint/cli": "^3.1.3",
- "@commitlint/config-angular": "^3.1.1",
- "async": "1.4.2",
- "coffee-script": "~1.7.1",
- "husky": "^0.14.3",
- "istanbul": "^0.4.5",
- "jscs": "^3.0.7",
- "mocha": "^2.5.3",
- "proxyquire": "^1.8.0",
- "semantic-release": "^8.2.3",
- "should": "~4.0.0"
- },
- "engines": {
- "node": ">=4"
- },
- "homepage": "http://nodemon.io",
- "keywords": [
- "monitor",
- "development",
- "restart",
- "autoload",
- "reload",
- "terminal"
- ],
- "license": "MIT",
- "main": "./lib/nodemon",
- "name": "nodemon",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/remy/nodemon.git"
- },
- "scripts": {
- ":spec": "mocha --timeout 30000 --ui bdd test/**/*.test.js",
- "clean": "rm -rf test/fixtures/test*.js test/fixtures/test*.md",
- "commitmsg": "commitlint -e",
- "coverage": "istanbul cover _mocha -- --timeout 30000 --ui bdd --reporter list test/**/*.test.js",
- "killall": "ps auxww | grep node | grep -v grep | awk '{ print $2 }' | xargs kill -9",
- "lint": "jscs lib/**/*.js -v",
- "postinstall": "node bin/postinstall || exit 0",
- "postspec": "npm run clean",
- "prepush": "npm run lint",
- "semantic-release": "semantic-release pre && npm publish && semantic-release post",
- "spec": "for FILE in test/**/*.test.js; do echo $FILE; TEST=1 mocha --exit --timeout 30000 $FILE; if [ $? -ne 0 ]; then exit 1; fi; sleep 1; done",
- "test": "npm run lint && npm run spec",
- "web": "node web"
- },
- "version": "1.19.4"
-}
+{"name":"nodemon","homepage":"http://nodemon.io","author":{"name":"Remy Sharp","url":"http://github.com/remy"},"bin":{"nodemon":"./bin/nodemon.js"},"engines":{"node":">=4"},"repository":{"type":"git","url":"https://github.com/remy/nodemon.git"},"description":"Simple monitor script for use during development of a node.js app.","keywords":["monitor","development","restart","autoload","reload","terminal"],"license":"MIT","main":"./lib/nodemon","scripts":{"commitmsg":"commitlint -e","coverage":"istanbul cover _mocha -- --timeout 30000 --ui bdd --reporter list test/**/*.test.js","lint":"jscs lib/**/*.js -v",":spec":"node_modules/.bin/mocha --timeout 30000 --ui bdd test/**/*.test.js","test":"npm run lint && npm run spec","spec":"for FILE in test/**/*.test.js; do echo $FILE; TEST=1 mocha --exit --timeout 30000 $FILE; if [ $? -ne 0 ]; then exit 1; fi; sleep 1; done","postspec":"npm run clean","clean":"rm -rf test/fixtures/test*.js test/fixtures/test*.md","web":"node web","semantic-release":"semantic-release pre && npm publish && semantic-release post","prepush":"npm run lint","killall":"ps auxww | grep node | grep -v grep | awk '{ print $2 }' | xargs kill -9","postinstall":"node bin/postinstall || exit 0"},"devDependencies":{"@commitlint/cli":"^3.1.3","@commitlint/config-angular":"^3.1.1","async":"1.4.2","coffee-script":"~1.7.1","husky":"^0.14.3","istanbul":"^0.4.5","jscs":"^3.0.7","mocha":"^2.5.3","proxyquire":"^1.8.0","semantic-release":"^8.2.3","should":"~4.0.0"},"dependencies":{"chokidar":"^2.1.8","debug":"^3.2.6","ignore-by-default":"^1.0.1","minimatch":"^3.0.4","pstree.remy":"^1.1.7","semver":"^5.7.1","supports-color":"^5.5.0","touch":"^3.1.0","undefsafe":"^2.0.2","update-notifier":"^2.5.0"},"version":"1.19.4"}
diff --git a/node_modules/nopt/.npmignore b/node_modules/nopt/.npmignore
old mode 100755
new mode 100644
diff --git a/node_modules/nopt/LICENSE b/node_modules/nopt/LICENSE
old mode 100755
new mode 100644
diff --git a/node_modules/nopt/README.md b/node_modules/nopt/README.md
old mode 100755
new mode 100644
diff --git a/node_modules/nopt/lib/nopt.js b/node_modules/nopt/lib/nopt.js
old mode 100755
new mode 100644
diff --git a/node_modules/nopt/package.json b/node_modules/nopt/package.json
old mode 100755
new mode 100644
index e205e7c..d1118e3
--- a/node_modules/nopt/package.json
+++ b/node_modules/nopt/package.json
@@ -1,60 +1,12 @@
-{
- "_from": "nopt@~1.0.10",
- "_id": "nopt@1.0.10",
- "_inBundle": false,
- "_integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
- "_location": "/nopt",
- "_phantomChildren": {},
- "_requested": {
- "type": "range",
- "registry": true,
- "raw": "nopt@~1.0.10",
- "name": "nopt",
- "escapedName": "nopt",
- "rawSpec": "~1.0.10",
- "saveSpec": null,
- "fetchSpec": "~1.0.10"
- },
- "_requiredBy": [
- "/touch"
- ],
- "_resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
- "_shasum": "6ddd21bd2a31417b92727dd585f8a6f37608ebee",
- "_spec": "nopt@~1.0.10",
- "_where": "/home/pi/Node Projects/x-chat/node_modules/touch",
- "author": {
- "name": "Isaac Z. Schlueter",
- "email": "i@izs.me",
- "url": "http://blog.izs.me/"
- },
- "bin": {
- "nopt": "./bin/nopt.js"
- },
- "bugs": {
- "url": "https://github.com/isaacs/nopt/issues"
- },
- "bundleDependencies": false,
- "dependencies": {
- "abbrev": "1"
- },
- "deprecated": false,
- "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.",
- "engines": {
- "node": "*"
- },
- "homepage": "https://github.com/isaacs/nopt#readme",
- "license": {
- "type": "MIT",
- "url": "https://github.com/isaacs/nopt/raw/master/LICENSE"
- },
- "main": "lib/nopt.js",
- "name": "nopt",
- "repository": {
- "type": "git",
- "url": "git+ssh://git@github.com/isaacs/nopt.git"
- },
- "scripts": {
- "test": "node lib/nopt.js"
- },
- "version": "1.0.10"
-}
+{ "name" : "nopt"
+, "version" : "1.0.10"
+, "description" : "Option parsing for Node, supporting types, shorthands, etc. Used by npm."
+, "author" : "Isaac Z. Schlueter (http://blog.izs.me/)"
+, "main" : "lib/nopt.js"
+, "scripts" : { "test" : "node lib/nopt.js" }
+, "repository" : "http://github.com/isaacs/nopt"
+, "bin" : "./bin/nopt.js"
+, "license" :
+ { "type" : "MIT"
+ , "url" : "https://github.com/isaacs/nopt/raw/master/LICENSE" }
+, "dependencies" : { "abbrev" : "1" }}
diff --git a/node_modules/object-component/.npmignore b/node_modules/object-component/.npmignore
deleted file mode 100755
index 665aa21..0000000
--- a/node_modules/object-component/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-components
-build
-node_modules
diff --git a/node_modules/object-component/History.md b/node_modules/object-component/History.md
deleted file mode 100755
index 15e0ee0..0000000
--- a/node_modules/object-component/History.md
+++ /dev/null
@@ -1,10 +0,0 @@
-
-0.0.3 / 2012-10-15
-==================
-
- * package: added `component` namespace (fixes #1)
-
-0.0.2 / 2012-09-20
-==================
-
- * add code smell to `.merge()`
diff --git a/node_modules/object-component/Makefile b/node_modules/object-component/Makefile
deleted file mode 100755
index b6b9850..0000000
--- a/node_modules/object-component/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-
-build: components index.js
- @component build
-
-components:
- @Component install
-
-clean:
- rm -fr build components template.js
-
-test:
- @./node_modules/.bin/mocha \
- --require should \
- --reporter spec
-
-.PHONY: clean test
diff --git a/node_modules/object-component/Readme.md b/node_modules/object-component/Readme.md
deleted file mode 100755
index 2c1f2d6..0000000
--- a/node_modules/object-component/Readme.md
+++ /dev/null
@@ -1,31 +0,0 @@
-
-# object
-
- Object utils.
-
-## API
-
-### .keys(obj)
-
- Return the keys for `obj`.
-
-### .values(obj)
-
- Return the values for `obj`.
-
-### .length(obj)
-
- Return the number of keys for `obj`.
-
-### .isEmpty(obj)
-
- Check if `obj` is empty.
-
-### .merge(a, b)
-
- Merge object `b` into `a`, returns `a`.
- Precedence is given to `b`.
-
-## License
-
- MIT
\ No newline at end of file
diff --git a/node_modules/object-component/component.json b/node_modules/object-component/component.json
deleted file mode 100755
index eebc82a..0000000
--- a/node_modules/object-component/component.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "object",
- "description": "Object keys / values / length",
- "version": "0.0.3",
- "keywords": ["object", "keys", "utility"],
- "dependencies": {},
- "scripts": [
- "index.js"
- ]
-}
\ No newline at end of file
diff --git a/node_modules/object-component/index.js b/node_modules/object-component/index.js
deleted file mode 100755
index dba9eeb..0000000
--- a/node_modules/object-component/index.js
+++ /dev/null
@@ -1,84 +0,0 @@
-
-/**
- * HOP ref.
- */
-
-var has = Object.prototype.hasOwnProperty;
-
-/**
- * Return own keys in `obj`.
- *
- * @param {Object} obj
- * @return {Array}
- * @api public
- */
-
-exports.keys = Object.keys || function(obj){
- var keys = [];
- for (var key in obj) {
- if (has.call(obj, key)) {
- keys.push(key);
- }
- }
- return keys;
-};
-
-/**
- * Return own values in `obj`.
- *
- * @param {Object} obj
- * @return {Array}
- * @api public
- */
-
-exports.values = function(obj){
- var vals = [];
- for (var key in obj) {
- if (has.call(obj, key)) {
- vals.push(obj[key]);
- }
- }
- return vals;
-};
-
-/**
- * Merge `b` into `a`.
- *
- * @param {Object} a
- * @param {Object} b
- * @return {Object} a
- * @api public
- */
-
-exports.merge = function(a, b){
- for (var key in b) {
- if (has.call(b, key)) {
- a[key] = b[key];
- }
- }
- return a;
-};
-
-/**
- * Return length of `obj`.
- *
- * @param {Object} obj
- * @return {Number}
- * @api public
- */
-
-exports.length = function(obj){
- return exports.keys(obj).length;
-};
-
-/**
- * Check if `obj` is empty.
- *
- * @param {Object} obj
- * @return {Boolean}
- * @api public
- */
-
-exports.isEmpty = function(obj){
- return 0 == exports.length(obj);
-};
\ No newline at end of file
diff --git a/node_modules/object-component/package.json b/node_modules/object-component/package.json
deleted file mode 100755
index cae29b0..0000000
--- a/node_modules/object-component/package.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "_from": "object-component@0.0.3",
- "_id": "object-component@0.0.3",
- "_inBundle": false,
- "_integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
- "_location": "/object-component",
- "_phantomChildren": {},
- "_requested": {
- "type": "version",
- "registry": true,
- "raw": "object-component@0.0.3",
- "name": "object-component",
- "escapedName": "object-component",
- "rawSpec": "0.0.3",
- "saveSpec": null,
- "fetchSpec": "0.0.3"
- },
- "_requiredBy": [
- "/socket.io-client"
- ],
- "_resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
- "_shasum": "f0c69aa50efc95b866c186f400a33769cb2f1291",
- "_spec": "object-component@0.0.3",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/socket.io-client",
- "bundleDependencies": false,
- "component": {
- "scripts": {
- "object/index.js": "index.js"
- }
- },
- "deprecated": false,
- "description": "Object utils.",
- "devDependencies": {
- "mocha": "*",
- "should": "*"
- },
- "name": "object-component",
- "version": "0.0.3"
-}
diff --git a/node_modules/object-component/test/object.js b/node_modules/object-component/test/object.js
deleted file mode 100755
index 23a7423..0000000
--- a/node_modules/object-component/test/object.js
+++ /dev/null
@@ -1,48 +0,0 @@
-
-/**
- * Module dependencies.
- */
-
-var object = require('..');
-
-describe('.keys(obj)', function(){
- it('should return the keys of an object', function(){
- var obj = { name: 'tobi', age: 1 };
- object.keys(obj).should.eql(['name', 'age']);
- })
-})
-
-describe('.values(obj)', function(){
- it('should return the values of an object', function(){
- var obj = { name: 'tobi', age: 1 };
- object.values(obj).should.eql(['tobi', 1]);
- })
-})
-
-describe('.length(obj)', function(){
- it('should return key count', function(){
- var obj = { name: 'tobi', age: 1 };
- object.length(obj).should.equal(2);
- })
-})
-
-describe('.merge(a, b)', function(){
- it('should merge two objects', function(){
- var a = { foo: 'bar' };
- var b = { bar: 'baz' };
- object.merge(a, b).should.eql({ foo: 'bar', bar: 'baz' });
- })
-
- it('should give precedence to b', function(){
- var a = { foo: 'bar' };
- var b = { foo: 'baz' };
- object.merge(a, b).should.eql({ foo: 'baz' });
- })
-})
-
-describe('.isEmpty()', function(){
- it('should check if the object is empty', function(){
- object.isEmpty({}).should.be.true;
- object.isEmpty({ foo: 'bar' }).should.be.false;
- })
-})
\ No newline at end of file
diff --git a/node_modules/parseqs/.npmignore b/node_modules/parseqs/.npmignore
deleted file mode 100755
index 0c3454b..0000000
--- a/node_modules/parseqs/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-.DS_Store
-node_modules
-npm-debug.log
\ No newline at end of file
diff --git a/node_modules/parseqs/package.json b/node_modules/parseqs/package.json
index b3cf597..0acb2ea 100755
--- a/node_modules/parseqs/package.json
+++ b/node_modules/parseqs/package.json
@@ -1,28 +1,28 @@
{
- "_from": "parseqs@0.0.5",
- "_id": "parseqs@0.0.5",
+ "_from": "parseqs@0.0.6",
+ "_id": "parseqs@0.0.6",
"_inBundle": false,
- "_integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
+ "_integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==",
"_location": "/parseqs",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
- "raw": "parseqs@0.0.5",
+ "raw": "parseqs@0.0.6",
"name": "parseqs",
"escapedName": "parseqs",
- "rawSpec": "0.0.5",
+ "rawSpec": "0.0.6",
"saveSpec": null,
- "fetchSpec": "0.0.5"
+ "fetchSpec": "0.0.6"
},
"_requiredBy": [
"/engine.io-client",
"/socket.io-client"
],
- "_resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
- "_shasum": "d5208a3738e46766e291ba2ea173684921a8b89d",
- "_spec": "parseqs@0.0.5",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/socket.io-client",
+ "_resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
+ "_shasum": "8e4bb5a19d1cdc844a08ac974d34e273afa670d5",
+ "_spec": "parseqs@0.0.6",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\socket.io-client",
"author": {
"name": "Gal Koren"
},
@@ -30,9 +30,6 @@
"url": "https://github.com/get/querystring/issues"
},
"bundleDependencies": false,
- "dependencies": {
- "better-assert": "~1.0.0"
- },
"deprecated": false,
"description": "Provides methods for parsing a query string into an object, and vice versa.",
"devDependencies": {
@@ -49,5 +46,5 @@
"scripts": {
"test": "make test"
},
- "version": "0.0.5"
+ "version": "0.0.6"
}
diff --git a/node_modules/parseuri/.npmignore b/node_modules/parseuri/.npmignore
deleted file mode 100755
index 4da89cf..0000000
--- a/node_modules/parseuri/.npmignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.DS_Store
-.node_modules/*
\ No newline at end of file
diff --git a/node_modules/parseuri/index.js b/node_modules/parseuri/index.js
index 438d6e6..d4704b4 100755
--- a/node_modules/parseuri/index.js
+++ b/node_modules/parseuri/index.js
@@ -35,5 +35,34 @@ module.exports = function parseuri(str) {
uri.ipv6uri = true;
}
+ uri.pathNames = pathNames(uri, uri['path']);
+ uri.queryKey = queryKey(uri, uri['query']);
+
return uri;
};
+
+function pathNames(obj, path) {
+ var regx = /\/{2,9}/g,
+ names = path.replace(regx, "/").split("/");
+
+ if (path.substr(0, 1) == '/' || path.length === 0) {
+ names.splice(0, 1);
+ }
+ if (path.substr(path.length - 1, 1) == '/') {
+ names.splice(names.length - 1, 1);
+ }
+
+ return names;
+}
+
+function queryKey(uri, query) {
+ var data = {};
+
+ query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {
+ if ($1) {
+ data[$1] = $2;
+ }
+ });
+
+ return data;
+}
diff --git a/node_modules/parseuri/package.json b/node_modules/parseuri/package.json
index 069fbbc..94d794c 100755
--- a/node_modules/parseuri/package.json
+++ b/node_modules/parseuri/package.json
@@ -1,40 +1,40 @@
{
- "_from": "parseuri@0.0.5",
- "_id": "parseuri@0.0.5",
+ "_from": "parseuri@0.0.6",
+ "_id": "parseuri@0.0.6",
"_inBundle": false,
- "_integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
+ "_integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==",
"_location": "/parseuri",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
- "raw": "parseuri@0.0.5",
+ "raw": "parseuri@0.0.6",
"name": "parseuri",
"escapedName": "parseuri",
- "rawSpec": "0.0.5",
+ "rawSpec": "0.0.6",
"saveSpec": null,
- "fetchSpec": "0.0.5"
+ "fetchSpec": "0.0.6"
},
"_requiredBy": [
"/engine.io-client",
"/socket.io-client"
],
- "_resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
- "_shasum": "80204a50d4dbb779bfdc6ebe2778d90e4bce320a",
- "_spec": "parseuri@0.0.5",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/socket.io-client",
- "author": "",
+ "_resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
+ "_shasum": "e1496e829e3ac2ff47f39a4dd044b32823c4a25a",
+ "_spec": "parseuri@0.0.6",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\socket.io-client",
+ "author": {
+ "name": "Gal Koren"
+ },
"bugs": {
"url": "https://github.com/get/parseuri/issues"
},
"bundleDependencies": false,
- "dependencies": {
- "better-assert": "~1.0.0"
- },
"deprecated": false,
"description": "Method that parses a URI and returns an array of its components",
"devDependencies": {
- "better-assert": "1.0.0",
+ "better-assert": "~1.0.0",
+ "expect.js": "^0.3.1",
"mocha": "1.17.1"
},
"homepage": "https://github.com/get/parseuri",
@@ -47,5 +47,5 @@
"scripts": {
"test": "make test"
},
- "version": "0.0.5"
+ "version": "0.0.6"
}
diff --git a/node_modules/parseuri/test.js b/node_modules/parseuri/test.js
index 50a361d..be447df 100755
--- a/node_modules/parseuri/test.js
+++ b/node_modules/parseuri/test.js
@@ -25,6 +25,9 @@ describe('my suite', function(){
expect(query.query).to.be('foo=bar');
expect(query.path).to.be('/foo/bar');
expect(query.relative).to.be('/foo/bar?foo=bar');
+ expect(query.queryKey.foo).to.be('bar');
+ expect(query.pathNames[0]).to.be('foo');
+ expect(query.pathNames[1]).to.be('bar');
expect(localhost.protocol).to.be('');
expect(localhost.host).to.be('localhost');
expect(localhost.port).to.be('8080');
diff --git a/node_modules/rc/LICENSE.APACHE2 b/node_modules/rc/LICENSE.APACHE2
old mode 100755
new mode 100644
diff --git a/node_modules/rc/LICENSE.BSD b/node_modules/rc/LICENSE.BSD
old mode 100755
new mode 100644
diff --git a/node_modules/rc/LICENSE.MIT b/node_modules/rc/LICENSE.MIT
old mode 100755
new mode 100644
diff --git a/node_modules/rc/README.md b/node_modules/rc/README.md
old mode 100755
new mode 100644
diff --git a/node_modules/rc/browser.js b/node_modules/rc/browser.js
old mode 100755
new mode 100644
diff --git a/node_modules/rc/lib/utils.js b/node_modules/rc/lib/utils.js
old mode 100755
new mode 100644
diff --git a/node_modules/rc/package.json b/node_modules/rc/package.json
old mode 100755
new mode 100644
index 52dee8c..887238f
--- a/node_modules/rc/package.json
+++ b/node_modules/rc/package.json
@@ -1,65 +1,29 @@
{
- "_from": "rc@^1.1.6",
- "_id": "rc@1.2.8",
- "_inBundle": false,
- "_integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "_location": "/rc",
- "_phantomChildren": {},
- "_requested": {
- "type": "range",
- "registry": true,
- "raw": "rc@^1.1.6",
- "name": "rc",
- "escapedName": "rc",
- "rawSpec": "^1.1.6",
- "saveSpec": null,
- "fetchSpec": "^1.1.6"
- },
- "_requiredBy": [
- "/registry-auth-token",
- "/registry-url"
- ],
- "_resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "_shasum": "cd924bf5200a075b83c188cd6b9e211b7fc0d3ed",
- "_spec": "rc@^1.1.6",
- "_where": "/home/pi/Node Projects/x-chat/node_modules/registry-auth-token",
- "author": {
- "name": "Dominic Tarr",
- "email": "dominic.tarr@gmail.com",
- "url": "dominictarr.com"
- },
- "bin": {
- "rc": "./cli.js"
- },
+ "name": "rc",
+ "version": "1.2.8",
+ "description": "hardwired configuration loader",
+ "main": "index.js",
"browser": "browser.js",
- "bugs": {
- "url": "https://github.com/dominictarr/rc/issues"
+ "scripts": {
+ "test": "set -e; node test/test.js; node test/ini.js; node test/nested-env-vars.js"
},
- "bundleDependencies": false,
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/dominictarr/rc.git"
},
- "deprecated": false,
- "description": "hardwired configuration loader",
- "homepage": "https://github.com/dominictarr/rc#readme",
+ "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
"keywords": [
"config",
"rc",
"unix",
"defaults"
],
- "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
- "main": "index.js",
- "name": "rc",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/dominictarr/rc.git"
- },
- "scripts": {
- "test": "set -e; node test/test.js; node test/ini.js; node test/nested-env-vars.js"
- },
- "version": "1.2.8"
+ "bin": "./cli.js",
+ "author": "Dominic Tarr (dominictarr.com)",
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ }
}
diff --git a/node_modules/rc/test/ini.js b/node_modules/rc/test/ini.js
old mode 100755
new mode 100644
diff --git a/node_modules/rc/test/nested-env-vars.js b/node_modules/rc/test/nested-env-vars.js
old mode 100755
new mode 100644
diff --git a/node_modules/rc/test/test.js b/node_modules/rc/test/test.js
old mode 100755
new mode 100644
diff --git a/node_modules/redis-parser/.npmignore b/node_modules/redis-parser/.npmignore
old mode 100755
new mode 100644
diff --git a/node_modules/redis-parser/LICENSE b/node_modules/redis-parser/LICENSE
old mode 100755
new mode 100644
diff --git a/node_modules/redis-parser/README.md b/node_modules/redis-parser/README.md
old mode 100755
new mode 100644
index ff448f0..1d9c27d
--- a/node_modules/redis-parser/README.md
+++ b/node_modules/redis-parser/README.md
@@ -15,9 +15,9 @@ Install with [NPM](https://npmjs.org/):
## Usage
```js
-var Parser = require('redis-parser');
+const Parser = require('redis-parser');
-var myParser = new Parser(options);
+const myParser = new Parser(options);
```
### Options
@@ -31,8 +31,8 @@ var myParser = new Parser(options);
### Functions
* `reset()`: reset the parser to it's initial state
-* `setReturnBuffers(boolean)`: (JSParser only) set the returnBuffers option on/off without resetting the parser
-* `setStringNumbers(boolean)`: (JSParser only) set the stringNumbers option on/off without resetting the parser
+* `setReturnBuffers(boolean)`: set the returnBuffers option on/off without resetting the parser
+* `setStringNumbers(boolean)`: set the stringNumbers option on/off without resetting the parser
### Error classes
@@ -41,40 +41,43 @@ var myParser = new Parser(options);
* `ParserError` sub class of RedisError
All Redis errors will be returned as `ReplyErrors` while a parser error is returned as `ParserError`.
-All error classes are exported by the parser.
+All error classes can be imported by the npm `redis-errors` package.
### Example
```js
-var Parser = require("redis-parser");
-
-function Library () {}
-
-Library.prototype.returnReply = function (reply) { ... }
-Library.prototype.returnError = function (err) { ... }
-Library.prototype.returnFatalError = function (err) { ... }
-
-var lib = new Library();
-
-var parser = new Parser({
- returnReply: function(reply) {
- lib.returnReply(reply);
- },
- returnError: function(err) {
- lib.returnError(err);
- },
- returnFatalError: function (err) {
- lib.returnFatalError(err);
- }
-});
-
-Library.prototype.streamHandler = function () {
- this.stream.on('data', function (buffer) {
- // Here the data (e.g. `new Buffer('$5\r\nHello\r\n'`)) is passed to the parser and the result is passed to either function depending on the provided data.
- parser.execute(buffer);
+const Parser = require("redis-parser");
+
+class Library {
+ returnReply(reply) { /* ... */ }
+ returnError(err) { /* ... */ }
+ returnFatalError(err) { /* ... */ }
+
+ streamHandler() {
+ this.stream.on('data', (buffer) => {
+ // Here the data (e.g. `Buffer.from('$5\r\nHello\r\n'`))
+ // is passed to the parser and the result is passed to
+ // either function depending on the provided data.
+ parser.execute(buffer);
});
-};
+ }
+}
+
+const lib = new Library();
+
+const parser = new Parser({
+ returnReply(reply) {
+ lib.returnReply(reply);
+ },
+ returnError(err) {
+ lib.returnError(err);
+ },
+ returnFatalError(err) {
+ lib.returnFatalError(err);
+ }
+});
```
+
You do not have to use the returnFatalError function. Fatal errors will be returned in the normal error function in that case.
And if you want to return buffers instead of strings, you can do this by adding the `returnBuffers` option.
@@ -84,15 +87,15 @@ If you handle with big numbers that are to large for JS (Number.MAX_SAFE_INTEGER
```js
// Same functions as in the first example
-var parser = new Parser({
- returnReply: function(reply) {
- lib.returnReply(reply);
- },
- returnError: function(err) {
- lib.returnError(err);
- },
- returnBuffers: true, // All strings are returned as Buffer e.g.
- stringNumbers: true // All numbers are returned as String
+const parser = new Parser({
+ returnReply(reply) {
+ lib.returnReply(reply);
+ },
+ returnError(err) {
+ lib.returnError(err);
+ },
+ returnBuffers: true, // All strings are returned as Buffer e.g.
+ stringNumbers: true // All numbers are returned as String
});
// The streamHandler as above
@@ -112,50 +115,50 @@ The parser is highly optimized but there may still be further optimizations poss
Currently the benchmark compares the performance against the hiredis parser:
- HIREDIS: $ multiple chunks in a bulk string x 859,880 ops/sec ±1.22% (82 runs sampled)
- HIREDIS BUF: $ multiple chunks in a bulk string x 608,869 ops/sec ±1.72% (85 runs sampled)
- JS PARSER: $ multiple chunks in a bulk string x 910,590 ops/sec ±0.87% (89 runs sampled)
- JS PARSER BUF: $ multiple chunks in a bulk string x 1,299,507 ops/sec ±2.18% (84 runs sampled)
+ HIREDIS: $ multiple chunks in a bulk string x 994,387 ops/sec ±0.22% (554 runs sampled)
+ JS PARSER: $ multiple chunks in a bulk string x 1,010,728 ops/sec ±0.28% (559 runs sampled)
+ HIREDIS BUF: $ multiple chunks in a bulk string x 648,742 ops/sec ±0.80% (526 runs sampled)
+ JS PARSER BUF: $ multiple chunks in a bulk string x 1,728,849 ops/sec ±0.41% (555 runs sampled)
- HIREDIS: + multiple chunks in a string x 1,787,203 ops/sec ±0.58% (96 runs sampled)
- HIREDIS BUF: + multiple chunks in a string x 943,584 ops/sec ±1.62% (87 runs sampled)
- JS PARSER: + multiple chunks in a string x 2,008,264 ops/sec ±1.01% (91 runs sampled)
- JS PARSER BUF: + multiple chunks in a string x 2,045,546 ops/sec ±0.78% (91 runs sampled)
+ HIREDIS: + multiple chunks in a string x 1,861,132 ops/sec ±0.18% (564 runs sampled)
+ JS PARSER: + multiple chunks in a string x 2,131,892 ops/sec ±0.31% (558 runs sampled)
+ HIREDIS BUF: + multiple chunks in a string x 965,132 ops/sec ±0.58% (521 runs sampled)
+ JS PARSER BUF: + multiple chunks in a string x 2,304,482 ops/sec ±0.31% (559 runs sampled)
- HIREDIS: $ 4mb bulk string x 310 ops/sec ±1.58% (75 runs sampled)
- HIREDIS BUF: $ 4mb bulk string x 471 ops/sec ±2.28% (78 runs sampled)
- JS PARSER: $ 4mb bulk string x 747 ops/sec ±2.43% (85 runs sampled)
- JS PARSER BUF: $ 4mb bulk string x 846 ops/sec ±5.52% (72 runs sampled)
+ HIREDIS: $ 4mb bulk string x 269 ops/sec ±0.56% (452 runs sampled)
+ JS PARSER: $ 4mb bulk string x 763 ops/sec ±0.25% (466 runs sampled)
+ HIREDIS BUF: $ 4mb bulk string x 336 ops/sec ±0.59% (459 runs sampled)
+ JS PARSER BUF: $ 4mb bulk string x 994 ops/sec ±0.36% (482 runs sampled)
- HIREDIS: + simple string x 2,324,866 ops/sec ±1.61% (90 runs sampled)
- HIREDIS BUF: + simple string x 1,085,823 ops/sec ±2.47% (82 runs sampled)
- JS PARSER: + simple string x 4,567,358 ops/sec ±1.97% (81 runs sampled)
- JS PARSER BUF: + simple string x 5,433,901 ops/sec ±0.66% (93 runs sampled)
+ HIREDIS: + simple string x 2,504,305 ops/sec ±0.19% (563 runs sampled)
+ JS PARSER: + simple string x 5,121,952 ops/sec ±0.30% (560 runs sampled)
+ HIREDIS BUF: + simple string x 1,122,899 ops/sec ±0.52% (516 runs sampled)
+ JS PARSER BUF: + simple string x 5,907,323 ops/sec ±0.23% (562 runs sampled)
- HIREDIS: : integer x 2,332,946 ops/sec ±0.47% (93 runs sampled)
- JS PARSER: : integer x 17,730,449 ops/sec ±0.73% (91 runs sampled)
- JS PARSER STR: : integer x 12,942,037 ops/sec ±0.51% (92 runs sampled)
+ HIREDIS: : integer x 2,461,376 ops/sec ±0.14% (561 runs sampled)
+ JS PARSER: : integer x 18,543,688 ops/sec ±0.19% (539 runs sampled)
+ JS PARSER STR: : integer x 14,149,305 ops/sec ±0.24% (561 runs sampled)
- HIREDIS: : big integer x 2,012,572 ops/sec ±0.33% (93 runs sampled)
- JS PARSER: : big integer x 10,210,923 ops/sec ±0.94% (94 runs sampled)
- JS PARSER STR: : big integer x 4,453,320 ops/sec ±0.52% (94 runs sampled)
+ HIREDIS: : big integer x 2,114,270 ops/sec ±0.15% (561 runs sampled)
+ JS PARSER: : big integer x 10,794,439 ops/sec ±0.25% (560 runs sampled)
+ JS PARSER STR: : big integer x 4,594,807 ops/sec ±0.24% (558 runs sampled)
- HIREDIS: * array x 44,479 ops/sec ±0.55% (94 runs sampled)
- HIREDIS BUF: * array x 14,391 ops/sec ±1.04% (86 runs sampled)
- JS PARSER: * array x 53,796 ops/sec ±2.08% (79 runs sampled)
- JS PARSER BUF: * array x 72,428 ops/sec ±0.72% (93 runs sampled)
+ HIREDIS: * array x 45,597 ops/sec ±0.23% (565 runs sampled)
+ JS PARSER: * array x 68,396 ops/sec ±0.30% (563 runs sampled)
+ HIREDIS BUF: * array x 14,726 ops/sec ±0.39% (498 runs sampled)
+ JS PARSER BUF: * array x 80,961 ops/sec ±0.25% (561 runs sampled)
- HIREDIS: * big nested array x 217 ops/sec ±0.97% (83 runs sampled)
- HIREDIS BUF: * big nested array x 255 ops/sec ±2.28% (77 runs sampled)
- JS PARSER: * big nested array x 242 ops/sec ±1.10% (85 runs sampled)
- JS PARSER BUF: * big nested array x 375 ops/sec ±1.21% (88 runs sampled)
+ HIREDIS: * big nested array x 212 ops/sec ±0.17% (511 runs sampled)
+ JS PARSER: * big nested array x 243 ops/sec ±0.21% (496 runs sampled)
+ HIREDIS BUF: * big nested array x 207 ops/sec ±0.37% (430 runs sampled)
+ JS PARSER BUF: * big nested array x 297 ops/sec ±1.10% (421 runs sampled)
- HIREDIS: - error x 78,821 ops/sec ±0.80% (93 runs sampled)
- JS PARSER: - error x 143,382 ops/sec ±0.75% (92 runs sampled)
+ HIREDIS: - error x 168,761 ops/sec ±0.28% (559 runs sampled)
+ JS PARSER: - error x 424,257 ops/sec ±0.28% (557 runs sampled)
Platform info:
- Ubuntu 16.10
- Node.js 7.4.0
+ Ubuntu 17.04
+ Node.js 7.10.0
Intel(R) Core(TM) i7-5600U CPU
## License
diff --git a/node_modules/redis-parser/changelog.md b/node_modules/redis-parser/changelog.md
old mode 100755
new mode 100644
index 5cd9470..551b9b5
--- a/node_modules/redis-parser/changelog.md
+++ b/node_modules/redis-parser/changelog.md
@@ -1,45 +1,63 @@
+# Changelog
+
+## v.3.0.0 - 25 May, 2017
+
+Breaking Changes
+
+- Drop support for Node.js < 4
+- Removed support for hiredis completely
+
+Internals
+
+- Due to the changes to ES6 the error performance improved by factor 2-3x
+- Improved length calculation performance (bulk strings + arrays)
+
+Features
+
+- The parser now handles weird input graceful
+
## v.2.6.0 - 03 Apr, 2017
Internals
-- Use Buffer.allocUnsafe instead of new Buffer() with modern Node.js versions
+- Use Buffer.allocUnsafe instead of new Buffer() with modern Node.js versions
## v.2.5.0 - 11 Mar, 2017
Features
-- Added a `ParserError` class to differentiate them to ReplyErrors. The class is also exported
+- Added a `ParserError` class to differentiate them to ReplyErrors. The class is also exported
Bugfixes
-- All errors now show their error message again next to the error name in the stack trace
-- ParserErrors now show the offset and buffer attributes while being logged
+- All errors now show their error message again next to the error name in the stack trace
+- ParserErrors now show the offset and buffer attributes while being logged
## v.2.4.1 - 05 Feb, 2017
Bugfixes
-- Fixed minimal memory consumption overhead for chunked buffers
+- Fixed minimal memory consumption overhead for chunked buffers
## v.2.4.0 - 25 Jan, 2017
Features
-- Added `reset` function to reset the parser to it's initial values
-- Added `setReturnBuffers` function to reset the returnBuffers option (Only for the JSParser)
-- Added `setStringNumbers` function to reset the stringNumbers option (Only for the JSParser)
-- All Errors are now of sub classes of the new `RedisError` class. It is also exported.
-- Improved bulk string chunked data handling performance
+- Added `reset` function to reset the parser to it's initial values
+- Added `setReturnBuffers` function to reset the returnBuffers option (Only for the JSParser)
+- Added `setStringNumbers` function to reset the stringNumbers option (Only for the JSParser)
+- All Errors are now of sub classes of the new `RedisError` class. It is also exported.
+- Improved bulk string chunked data handling performance
Bugfixes
-- Parsing time for big nested arrays is now linear
+- Parsing time for big nested arrays is now linear
## v.2.3.0 - 25 Nov, 2016
Features
-- Parsing time for big arrays (e.g. 4mb+) is now linear and works well for arbitrary array sizes
+- Parsing time for big arrays (e.g. 4mb+) is now linear and works well for arbitrary array sizes
This case is a magnitude faster than before
@@ -54,49 +72,49 @@ This case is a magnitude faster than before
Features
-- Improve `stringNumbers` parsing performance by up to 100%
+- Improve `stringNumbers` parsing performance by up to 100%
Bugfixes
-- Do not unref the interval anymore due to issues with NodeJS
+- Do not unref the interval anymore due to issues with NodeJS
## v.2.1.1 - 31 Oct, 2016
Bugfixes
-- Remove erroneously added const to support Node.js 0.10
+- Remove erroneously added const to support Node.js 0.10
## v.2.1.0 - 30 Oct, 2016
Features
-- Improve parser errors by adding more detailed information to them
-- Accept manipulated Object.prototypes
-- Unref the interval if used
+- Improve parser errors by adding more detailed information to them
+- Accept manipulated Object.prototypes
+- Unref the interval if used
## v.2.0.4 - 21 Jul, 2016
Bugfixes
-- Fixed multi byte characters getting corrupted
+- Fixed multi byte characters getting corrupted
## v.2.0.3 - 17 Jun, 2016
Bugfixes
-- Fixed parser not working with huge buffers (e.g. 300 MB)
+- Fixed parser not working with huge buffers (e.g. 300 MB)
## v.2.0.2 - 08 Jun, 2016
Bugfixes
-- Fixed parser with returnBuffers option returning corrupted data
+- Fixed parser with returnBuffers option returning corrupted data
## v.2.0.1 - 04 Jun, 2016
Bugfixes
-- Fixed multiple parsers working concurrently resulting in faulty data in some cases
+- Fixed multiple parsers working concurrently resulting in faulty data in some cases
## v.2.0.0 - 29 May, 2016
@@ -107,32 +125,32 @@ All Errors returned by the parser are from now on of class ReplyError
Features
-- Improved performance by up to 15x as fast as before
-- Improved options validation
-- Added ReplyError Class
-- Added parser benchmark
-- Switched default parser from hiredis to JS, no matter if hiredis is installed or not
+- Improved performance by up to 15x as fast as before
+- Improved options validation
+- Added ReplyError Class
+- Added parser benchmark
+- Switched default parser from hiredis to JS, no matter if hiredis is installed or not
Removed
-- Deprecated hiredis support
+- Deprecated hiredis support
## v.1.3.0 - 27 Mar, 2016
Features
-- Added `auto` as parser name option to check what parser is available
-- Non existing requested parsers falls back into auto mode instead of always choosing the JS parser
+- Added `auto` as parser name option to check what parser is available
+- Non existing requested parsers falls back into auto mode instead of always choosing the JS parser
## v.1.2.0 - 27 Mar, 2016
Features
-- Added `stringNumbers` option to make sure all numbers are returned as string instead of a js number for precision
-- The parser is from now on going to print warnings if a parser is explicitly requested that does not exist and gracefully chooses the JS parser
+- Added `stringNumbers` option to make sure all numbers are returned as string instead of a js number for precision
+- The parser is from now on going to print warnings if a parser is explicitly requested that does not exist and gracefully chooses the JS parser
## v.1.1.0 - 26 Jan, 2016
Features
-- The parser is from now on going to reset itself on protocol errors
+- The parser is from now on going to reset itself on protocol errors
diff --git a/node_modules/redis-parser/index.js b/node_modules/redis-parser/index.js
old mode 100755
new mode 100644
index a0c777d..f5de376
--- a/node_modules/redis-parser/index.js
+++ b/node_modules/redis-parser/index.js
@@ -1,6 +1,3 @@
'use strict'
module.exports = require('./lib/parser')
-module.exports.ReplyError = require('./lib/replyError')
-module.exports.RedisError = require('./lib/redisError')
-module.exports.ParserError = require('./lib/redisError')
diff --git a/node_modules/redis-parser/lib/parser.js b/node_modules/redis-parser/lib/parser.js
old mode 100755
new mode 100644
index 4ba6a18..5d2532a
--- a/node_modules/redis-parser/lib/parser.js
+++ b/node_modules/redis-parser/lib/parser.js
@@ -1,34 +1,25 @@
'use strict'
-var StringDecoder = require('string_decoder').StringDecoder
-var decoder = new StringDecoder()
-var ReplyError = require('./replyError')
-var ParserError = require('./parserError')
-var bufferPool = bufferAlloc(32 * 1024)
+const Buffer = require('buffer').Buffer
+const StringDecoder = require('string_decoder').StringDecoder
+const decoder = new StringDecoder()
+const errors = require('redis-errors')
+const ReplyError = errors.ReplyError
+const ParserError = errors.ParserError
+var bufferPool = Buffer.allocUnsafe(32 * 1024)
var bufferOffset = 0
var interval = null
var counter = 0
var notDecreased = 0
-var isModern = typeof Buffer.allocUnsafe === 'function'
/**
- * For backwards compatibility
- * @param len
- * @returns {Buffer}
- */
-
-function bufferAlloc (len) {
- return isModern ? Buffer.allocUnsafe(len) : new Buffer(len)
-}
-
-/**
- * Used for lengths and numbers only, faster perf on arrays / bulks
- * @param parser
- * @returns {*}
+ * Used for integer numbers only
+ * @param {JavascriptRedisParser} parser
+ * @returns {undefined|number}
*/
function parseSimpleNumbers (parser) {
+ const length = parser.buffer.length - 1
var offset = parser.offset
- var length = parser.buffer.length - 1
var number = 0
var sign = 1
@@ -38,7 +29,7 @@ function parseSimpleNumbers (parser) {
}
while (offset < length) {
- var c1 = parser.buffer[offset++]
+ const c1 = parser.buffer[offset++]
if (c1 === 13) { // \r\n
parser.offset = offset + 1
return sign * number
@@ -50,15 +41,15 @@ function parseSimpleNumbers (parser) {
/**
* Used for integer numbers in case of the returnNumbers option
*
- * The maximimum possible integer to use is: Math.floor(Number.MAX_SAFE_INTEGER / 10)
- * Staying in a SMI Math.floor((Math.pow(2, 32) / 10) - 1) is even more efficient though
+ * Reading the string as parts of n SMI is more efficient than
+ * using a string directly.
*
- * @param parser
- * @returns {*}
+ * @param {JavascriptRedisParser} parser
+ * @returns {undefined|string}
*/
function parseStringNumbers (parser) {
+ const length = parser.buffer.length - 1
var offset = parser.offset
- var length = parser.buffer.length - 1
var number = 0
var res = ''
@@ -86,54 +77,46 @@ function parseStringNumbers (parser) {
}
}
-/**
- * Returns a string or buffer of the provided offset start and
- * end ranges. Checks `optionReturnBuffers`.
- *
- * If returnBuffers is active, all return values are returned as buffers besides numbers and errors
- *
- * @param parser
- * @param start
- * @param end
- * @returns {*}
- */
-function convertBufferRange (parser, start, end) {
- parser.offset = end + 2
- if (parser.optionReturnBuffers === true) {
- return parser.buffer.slice(start, end)
- }
-
- return parser.buffer.toString('utf-8', start, end)
-}
-
/**
* Parse a '+' redis simple string response but forward the offsets
* onto convertBufferRange to generate a string.
- * @param parser
- * @returns {*}
+ * @param {JavascriptRedisParser} parser
+ * @returns {undefined|string|Buffer}
*/
function parseSimpleString (parser) {
- var start = parser.offset
+ const start = parser.offset
+ const buffer = parser.buffer
+ const length = buffer.length - 1
var offset = start
- var buffer = parser.buffer
- var length = buffer.length - 1
while (offset < length) {
if (buffer[offset++] === 13) { // \r\n
- return convertBufferRange(parser, start, offset - 1)
+ parser.offset = offset + 1
+ if (parser.optionReturnBuffers === true) {
+ return parser.buffer.slice(start, offset - 1)
+ }
+ return parser.buffer.toString('utf8', start, offset - 1)
}
}
}
/**
- * Returns the string length via parseSimpleNumbers
- * @param parser
- * @returns {*}
+ * Returns the read length
+ * @param {JavascriptRedisParser} parser
+ * @returns {undefined|number}
*/
function parseLength (parser) {
- var string = parseSimpleNumbers(parser)
- if (string !== undefined) {
- return string
+ const length = parser.buffer.length - 1
+ var offset = parser.offset
+ var number = 0
+
+ while (offset < length) {
+ const c1 = parser.buffer[offset++]
+ if (c1 === 13) {
+ parser.offset = offset + 1
+ return number
+ }
+ number = (number * 10) + (c1 - 48)
}
}
@@ -144,11 +127,11 @@ function parseLength (parser) {
* This is important for big numbers (number > Math.pow(2, 53)) as js numbers
* are 64bit floating point numbers with reduced precision
*
- * @param parser
- * @returns {*}
+ * @param {JavascriptRedisParser} parser
+ * @returns {undefined|number|string}
*/
function parseInteger (parser) {
- if (parser.optionStringNumbers) {
+ if (parser.optionStringNumbers === true) {
return parseStringNumbers(parser)
}
return parseSimpleNumbers(parser)
@@ -156,33 +139,36 @@ function parseInteger (parser) {
/**
* Parse a '$' redis bulk string response
- * @param parser
- * @returns {*}
+ * @param {JavascriptRedisParser} parser
+ * @returns {undefined|null|string}
*/
function parseBulkString (parser) {
- var length = parseLength(parser)
+ const length = parseLength(parser)
if (length === undefined) {
return
}
- if (length === -1) {
+ if (length < 0) {
return null
}
- var offsetEnd = parser.offset + length
- if (offsetEnd + 2 > parser.buffer.length) {
- parser.bigStrSize = offsetEnd + 2
- parser.bigOffset = parser.offset
+ const offset = parser.offset + length
+ if (offset + 2 > parser.buffer.length) {
+ parser.bigStrSize = offset + 2
parser.totalChunkSize = parser.buffer.length
parser.bufferCache.push(parser.buffer)
return
}
-
- return convertBufferRange(parser, parser.offset, offsetEnd)
+ const start = parser.offset
+ parser.offset = offset + 2
+ if (parser.optionReturnBuffers === true) {
+ return parser.buffer.slice(start, offset)
+ }
+ return parser.buffer.toString('utf8', start, offset)
}
/**
* Parse a '-' redis error response
- * @param parser
- * @returns {Error}
+ * @param {JavascriptRedisParser} parser
+ * @returns {ReplyError}
*/
function parseError (parser) {
var string = parseSimpleString(parser)
@@ -196,55 +182,61 @@ function parseError (parser) {
/**
* Parsing error handler, resets parser buffer
- * @param parser
- * @param error
+ * @param {JavascriptRedisParser} parser
+ * @param {number} type
+ * @returns {undefined}
*/
-function handleError (parser, error) {
+function handleError (parser, type) {
+ const err = new ParserError(
+ 'Protocol error, got ' + JSON.stringify(String.fromCharCode(type)) + ' as reply type byte',
+ JSON.stringify(parser.buffer),
+ parser.offset
+ )
parser.buffer = null
- parser.returnFatalError(error)
+ parser.returnFatalError(err)
}
/**
* Parse a '*' redis array response
- * @param parser
- * @returns {*}
+ * @param {JavascriptRedisParser} parser
+ * @returns {undefined|null|any[]}
*/
function parseArray (parser) {
- var length = parseLength(parser)
+ const length = parseLength(parser)
if (length === undefined) {
return
}
- if (length === -1) {
+ if (length < 0) {
return null
}
- var responses = new Array(length)
+ const responses = new Array(length)
return parseArrayElements(parser, responses, 0)
}
/**
* Push a partly parsed array to the stack
*
- * @param parser
- * @param elem
- * @param i
+ * @param {JavascriptRedisParser} parser
+ * @param {any[]} array
+ * @param {number} pos
* @returns {undefined}
*/
-function pushArrayCache (parser, elem, pos) {
- parser.arrayCache.push(elem)
+function pushArrayCache (parser, array, pos) {
+ parser.arrayCache.push(array)
parser.arrayPos.push(pos)
}
/**
* Parse chunked redis array response
- * @param parser
- * @returns {*}
+ * @param {JavascriptRedisParser} parser
+ * @returns {undefined|any[]}
*/
function parseArrayChunks (parser) {
- var tmp = parser.arrayCache.pop()
+ const tmp = parser.arrayCache.pop()
var pos = parser.arrayPos.pop()
if (parser.arrayCache.length) {
- var res = parseArrayChunks(parser)
- if (!res) {
+ const res = parseArrayChunks(parser)
+ if (res === undefined) {
pushArrayCache(parser, tmp, pos)
return
}
@@ -255,22 +247,22 @@ function parseArrayChunks (parser) {
/**
* Parse redis array response elements
- * @param parser
- * @param responses
- * @param i
- * @returns {*}
+ * @param {JavascriptRedisParser} parser
+ * @param {Array} responses
+ * @param {number} i
+ * @returns {undefined|null|any[]}
*/
function parseArrayElements (parser, responses, i) {
- var bufferLength = parser.buffer.length
+ const bufferLength = parser.buffer.length
while (i < responses.length) {
- var offset = parser.offset
+ const offset = parser.offset
if (parser.offset >= bufferLength) {
pushArrayCache(parser, responses, i)
return
}
- var response = parseType(parser, parser.buffer[parser.offset++])
+ const response = parseType(parser, parser.buffer[parser.offset++])
if (response === undefined) {
- if (!parser.arrayCache.length) {
+ if (!(parser.arrayCache.length || parser.bufferCache.length)) {
parser.offset = offset
}
pushArrayCache(parser, responses, i)
@@ -285,135 +277,49 @@ function parseArrayElements (parser, responses, i) {
/**
* Called the appropriate parser for the specified type.
- * @param parser
- * @param type
+ *
+ * 36: $
+ * 43: +
+ * 42: *
+ * 58: :
+ * 45: -
+ *
+ * @param {JavascriptRedisParser} parser
+ * @param {number} type
* @returns {*}
*/
function parseType (parser, type) {
switch (type) {
- case 36: // $
+ case 36:
return parseBulkString(parser)
- case 58: // :
- return parseInteger(parser)
- case 43: // +
+ case 43:
return parseSimpleString(parser)
- case 42: // *
+ case 42:
return parseArray(parser)
- case 45: // -
+ case 58:
+ return parseInteger(parser)
+ case 45:
return parseError(parser)
default:
- return handleError(parser, new ParserError(
- 'Protocol error, got ' + JSON.stringify(String.fromCharCode(type)) + ' as reply type byte',
- JSON.stringify(parser.buffer),
- parser.offset
- ))
- }
-}
-
-// All allowed options including their typeof value
-var optionTypes = {
- returnError: 'function',
- returnFatalError: 'function',
- returnReply: 'function',
- returnBuffers: 'boolean',
- stringNumbers: 'boolean',
- name: 'string'
-}
-
-/**
- * Javascript Redis Parser
- * @param options
- * @constructor
- */
-function JavascriptRedisParser (options) {
- if (!(this instanceof JavascriptRedisParser)) {
- return new JavascriptRedisParser(options)
- }
- if (!options || !options.returnError || !options.returnReply) {
- throw new TypeError('Please provide all return functions while initiating the parser')
- }
- for (var key in options) {
- // eslint-disable-next-line valid-typeof
- if (optionTypes.hasOwnProperty(key) && typeof options[key] !== optionTypes[key]) {
- throw new TypeError('The options argument contains the property "' + key + '" that is either unknown or of a wrong type')
- }
- }
- if (options.name === 'hiredis') {
- /* istanbul ignore next: hiredis is only supported for legacy usage */
- try {
- var Hiredis = require('./hiredis')
- console.error(new TypeError('Using hiredis is discouraged. Please use the faster JS parser by removing the name option.').stack.replace('Error', 'Warning'))
- return new Hiredis(options)
- } catch (e) {
- console.error(new TypeError('Hiredis is not installed. Please remove the `name` option. The (faster) JS parser is used instead.').stack.replace('Error', 'Warning'))
- }
- }
- this.optionReturnBuffers = !!options.returnBuffers
- this.optionStringNumbers = !!options.stringNumbers
- this.returnError = options.returnError
- this.returnFatalError = options.returnFatalError || options.returnError
- this.returnReply = options.returnReply
- this.name = 'javascript'
- this.reset()
-}
-
-/**
- * Reset the parser values to the initial state
- *
- * @returns {undefined}
- */
-JavascriptRedisParser.prototype.reset = function () {
- this.offset = 0
- this.buffer = null
- this.bigStrSize = 0
- this.bigOffset = 0
- this.totalChunkSize = 0
- this.bufferCache = []
- this.arrayCache = []
- this.arrayPos = []
-}
-
-/**
- * Set the returnBuffers option
- *
- * @param returnBuffers
- * @returns {undefined}
- */
-JavascriptRedisParser.prototype.setReturnBuffers = function (returnBuffers) {
- if (typeof returnBuffers !== 'boolean') {
- throw new TypeError('The returnBuffers argument has to be a boolean')
+ return handleError(parser, type)
}
- this.optionReturnBuffers = returnBuffers
-}
-
-/**
- * Set the stringNumbers option
- *
- * @param stringNumbers
- * @returns {undefined}
- */
-JavascriptRedisParser.prototype.setStringNumbers = function (stringNumbers) {
- if (typeof stringNumbers !== 'boolean') {
- throw new TypeError('The stringNumbers argument has to be a boolean')
- }
- this.optionStringNumbers = stringNumbers
}
/**
* Decrease the bufferPool size over time
+ *
+ * Balance between increasing and decreasing the bufferPool.
+ * Decrease the bufferPool by 10% by removing the first 10% of the current pool.
* @returns {undefined}
*/
function decreaseBufferPool () {
if (bufferPool.length > 50 * 1024) {
- // Balance between increasing and decreasing the bufferPool
if (counter === 1 || notDecreased > counter * 2) {
- // Decrease the bufferPool by 10% by removing the first 10% of the current pool
- var sliceLength = Math.floor(bufferPool.length / 10)
- if (bufferOffset <= sliceLength) {
- bufferOffset = 0
- } else {
- bufferOffset -= sliceLength
- }
+ const minSliceLen = Math.floor(bufferPool.length / 10)
+ const sliceLength = minSliceLen < bufferOffset
+ ? bufferOffset
+ : minSliceLen
+ bufferOffset = 0
bufferPool = bufferPool.slice(sliceLength, bufferPool.length)
} else {
notDecreased++
@@ -431,16 +337,16 @@ function decreaseBufferPool () {
* Check if the requested size fits in the current bufferPool.
* If it does not, reset and increase the bufferPool accordingly.
*
- * @param length
+ * @param {number} length
* @returns {undefined}
*/
function resizeBuffer (length) {
if (bufferPool.length < length + bufferOffset) {
- var multiplier = length > 1024 * 1024 * 75 ? 2 : 3
+ const multiplier = length > 1024 * 1024 * 75 ? 2 : 3
if (bufferOffset > 1024 * 1024 * 111) {
bufferOffset = 1024 * 1024 * 50
}
- bufferPool = bufferAlloc(length * multiplier + bufferOffset)
+ bufferPool = Buffer.allocUnsafe(length * multiplier + bufferOffset)
bufferOffset = 0
counter++
if (interval === null) {
@@ -456,22 +362,23 @@ function resizeBuffer (length) {
* 1) The first chunk might contain the whole bulk string including the \r
* 2) We are only safe to fully add up elements that are neither the first nor any of the last two elements
*
- * @param parser
+ * @param {JavascriptRedisParser} parser
* @returns {String}
*/
function concatBulkString (parser) {
- var list = parser.bufferCache
+ const list = parser.bufferCache
+ const oldOffset = parser.offset
var chunks = list.length
var offset = parser.bigStrSize - parser.totalChunkSize
parser.offset = offset
if (offset <= 2) {
if (chunks === 2) {
- return list[0].toString('utf8', parser.bigOffset, list[0].length + offset - 2)
+ return list[0].toString('utf8', oldOffset, list[0].length + offset - 2)
}
chunks--
offset = list[list.length - 2].length + offset
}
- var res = decoder.write(list[0].slice(parser.bigOffset))
+ var res = decoder.write(list[0].slice(oldOffset))
for (var i = 1; i < chunks - 1; i++) {
res += decoder.write(list[i])
}
@@ -484,26 +391,27 @@ function concatBulkString (parser) {
*
* Increases the bufferPool size beforehand if necessary.
*
- * @param parser
+ * @param {JavascriptRedisParser} parser
* @returns {Buffer}
*/
function concatBulkBuffer (parser) {
- var list = parser.bufferCache
+ const list = parser.bufferCache
+ const oldOffset = parser.offset
+ const length = parser.bigStrSize - oldOffset - 2
var chunks = list.length
- var length = parser.bigStrSize - parser.bigOffset - 2
var offset = parser.bigStrSize - parser.totalChunkSize
parser.offset = offset
if (offset <= 2) {
if (chunks === 2) {
- return list[0].slice(parser.bigOffset, list[0].length + offset - 2)
+ return list[0].slice(oldOffset, list[0].length + offset - 2)
}
chunks--
offset = list[list.length - 2].length + offset
}
resizeBuffer(length)
- var start = bufferOffset
- list[0].copy(bufferPool, start, parser.bigOffset, list[0].length)
- bufferOffset += list[0].length - parser.bigOffset
+ const start = bufferOffset
+ list[0].copy(bufferPool, start, oldOffset, list[0].length)
+ bufferOffset += list[0].length - oldOffset
for (var i = 1; i < chunks - 1; i++) {
list[i].copy(bufferPool, bufferOffset)
bufferOffset += list[i].length
@@ -513,69 +421,132 @@ function concatBulkBuffer (parser) {
return bufferPool.slice(start, bufferOffset)
}
-/**
- * Parse the redis buffer
- * @param buffer
- * @returns {undefined}
- */
-JavascriptRedisParser.prototype.execute = function execute (buffer) {
- if (this.buffer === null) {
- this.buffer = buffer
- this.offset = 0
- } else if (this.bigStrSize === 0) {
- var oldLength = this.buffer.length
- var remainingLength = oldLength - this.offset
- var newBuffer = bufferAlloc(remainingLength + buffer.length)
- this.buffer.copy(newBuffer, 0, this.offset, oldLength)
- buffer.copy(newBuffer, remainingLength, 0, buffer.length)
- this.buffer = newBuffer
- this.offset = 0
- if (this.arrayCache.length) {
- var arr = parseArrayChunks(this)
- if (!arr) {
- return
- }
- this.returnReply(arr)
+class JavascriptRedisParser {
+ /**
+ * Javascript Redis Parser constructor
+ * @param {{returnError: Function, returnReply: Function, returnFatalError?: Function, returnBuffers: boolean, stringNumbers: boolean }} options
+ * @constructor
+ */
+ constructor (options) {
+ if (!options) {
+ throw new TypeError('Options are mandatory.')
+ }
+ if (typeof options.returnError !== 'function' || typeof options.returnReply !== 'function') {
+ throw new TypeError('The returnReply and returnError options have to be functions.')
}
- } else if (this.totalChunkSize + buffer.length >= this.bigStrSize) {
- this.bufferCache.push(buffer)
- var tmp = this.optionReturnBuffers ? concatBulkBuffer(this) : concatBulkString(this)
+ this.setReturnBuffers(!!options.returnBuffers)
+ this.setStringNumbers(!!options.stringNumbers)
+ this.returnError = options.returnError
+ this.returnFatalError = options.returnFatalError || options.returnError
+ this.returnReply = options.returnReply
+ this.reset()
+ }
+
+ /**
+ * Reset the parser values to the initial state
+ *
+ * @returns {undefined}
+ */
+ reset () {
+ this.offset = 0
+ this.buffer = null
this.bigStrSize = 0
+ this.totalChunkSize = 0
this.bufferCache = []
- this.buffer = buffer
- if (this.arrayCache.length) {
- this.arrayCache[0][this.arrayPos[0]++] = tmp
- tmp = parseArrayChunks(this)
- if (!tmp) {
- return
- }
+ this.arrayCache = []
+ this.arrayPos = []
+ }
+
+ /**
+ * Set the returnBuffers option
+ *
+ * @param {boolean} returnBuffers
+ * @returns {undefined}
+ */
+ setReturnBuffers (returnBuffers) {
+ if (typeof returnBuffers !== 'boolean') {
+ throw new TypeError('The returnBuffers argument has to be a boolean')
}
- this.returnReply(tmp)
- } else {
- this.bufferCache.push(buffer)
- this.totalChunkSize += buffer.length
- return
+ this.optionReturnBuffers = returnBuffers
}
- while (this.offset < this.buffer.length) {
- var offset = this.offset
- var type = this.buffer[this.offset++]
- var response = parseType(this, type)
- if (response === undefined) {
- if (!this.arrayCache.length) {
- this.offset = offset
+ /**
+ * Set the stringNumbers option
+ *
+ * @param {boolean} stringNumbers
+ * @returns {undefined}
+ */
+ setStringNumbers (stringNumbers) {
+ if (typeof stringNumbers !== 'boolean') {
+ throw new TypeError('The stringNumbers argument has to be a boolean')
+ }
+ this.optionStringNumbers = stringNumbers
+ }
+
+ /**
+ * Parse the redis buffer
+ * @param {Buffer} buffer
+ * @returns {undefined}
+ */
+ execute (buffer) {
+ if (this.buffer === null) {
+ this.buffer = buffer
+ this.offset = 0
+ } else if (this.bigStrSize === 0) {
+ const oldLength = this.buffer.length
+ const remainingLength = oldLength - this.offset
+ const newBuffer = Buffer.allocUnsafe(remainingLength + buffer.length)
+ this.buffer.copy(newBuffer, 0, this.offset, oldLength)
+ buffer.copy(newBuffer, remainingLength, 0, buffer.length)
+ this.buffer = newBuffer
+ this.offset = 0
+ if (this.arrayCache.length) {
+ const arr = parseArrayChunks(this)
+ if (arr === undefined) {
+ return
+ }
+ this.returnReply(arr)
+ }
+ } else if (this.totalChunkSize + buffer.length >= this.bigStrSize) {
+ this.bufferCache.push(buffer)
+ var tmp = this.optionReturnBuffers ? concatBulkBuffer(this) : concatBulkString(this)
+ this.bigStrSize = 0
+ this.bufferCache = []
+ this.buffer = buffer
+ if (this.arrayCache.length) {
+ this.arrayCache[0][this.arrayPos[0]++] = tmp
+ tmp = parseArrayChunks(this)
+ if (tmp === undefined) {
+ return
+ }
}
+ this.returnReply(tmp)
+ } else {
+ this.bufferCache.push(buffer)
+ this.totalChunkSize += buffer.length
return
}
- if (type === 45) {
- this.returnError(response)
- } else {
- this.returnReply(response)
+ while (this.offset < this.buffer.length) {
+ const offset = this.offset
+ const type = this.buffer[this.offset++]
+ const response = parseType(this, type)
+ if (response === undefined) {
+ if (!(this.arrayCache.length || this.bufferCache.length)) {
+ this.offset = offset
+ }
+ return
+ }
+
+ if (type === 45) {
+ this.returnError(response)
+ } else {
+ this.returnReply(response)
+ }
}
- }
- this.buffer = null
+ this.buffer = null
+ }
}
module.exports = JavascriptRedisParser
diff --git a/node_modules/redis-parser/package.json b/node_modules/redis-parser/package.json
old mode 100755
new mode 100644
index 7f7311c..0c3287b
--- a/node_modules/redis-parser/package.json
+++ b/node_modules/redis-parser/package.json
@@ -1,53 +1,20 @@
{
- "_from": "redis-parser@^2.6.0",
- "_id": "redis-parser@2.6.0",
- "_inBundle": false,
- "_integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=",
- "_location": "/redis-parser",
- "_phantomChildren": {},
- "_requested": {
- "type": "range",
- "registry": true,
- "raw": "redis-parser@^2.6.0",
- "name": "redis-parser",
- "escapedName": "redis-parser",
- "rawSpec": "^2.6.0",
- "saveSpec": null,
- "fetchSpec": "^2.6.0"
- },
- "_requiredBy": [
- "/redis"
- ],
- "_resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz",
- "_shasum": "52ed09dacac108f1a631c07e9b69941e7a19504b",
- "_spec": "redis-parser@^2.6.0",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/redis",
- "author": {
- "name": "Ruben Bridgewater"
- },
- "bugs": {
- "url": "https://github.com/NodeRedis/node-redis-parser/issues"
- },
- "bundleDependencies": false,
- "deprecated": false,
+ "name": "redis-parser",
+ "version": "3.0.0",
"description": "Javascript Redis protocol (RESP) parser",
- "devDependencies": {
- "benchmark": "^2.1.0",
- "codeclimate-test-reporter": "^0.4.0",
- "hiredis": "^0.5.0",
- "intercept-stdout": "^0.1.2",
- "istanbul": "^0.4.0",
- "mocha": "^3.1.2",
- "standard": "^9.0.0"
- },
- "directories": {
- "test": "test",
- "lib": "lib"
+ "main": "index.js",
+ "scripts": {
+ "test": "npm run coverage",
+ "benchmark": "node ./benchmark",
+ "lint": "standard --fix",
+ "posttest": "npm run lint && npm run coverage:check",
+ "coverage": "node ./node_modules/istanbul/lib/cli.js cover --preserve-comments ./node_modules/mocha/bin/_mocha -- -R spec",
+ "coverage:check": "node ./node_modules/istanbul/lib/cli.js check-coverage --branch 100 --statement 100"
},
- "engines": {
- "node": ">=0.10.0"
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/NodeRedis/node-redis-parser.git"
},
- "homepage": "https://github.com/NodeRedis/node-redis-parser#readme",
"keywords": [
"redis",
"protocol",
@@ -59,20 +26,28 @@
"resp",
"hiredis"
],
- "license": "MIT",
- "main": "index.js",
- "name": "redis-parser",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/NodeRedis/node-redis-parser.git"
+ "engines": {
+ "node": ">=4"
},
- "scripts": {
- "benchmark": "node ./benchmark",
- "coverage": "node ./node_modules/istanbul/lib/cli.js cover --preserve-comments ./node_modules/mocha/bin/_mocha -- -R spec",
- "coverage:check": "node ./node_modules/istanbul/lib/cli.js check-coverage --branch 100 --statement 100",
- "lint": "standard --fix",
- "posttest": "npm run lint && npm run coverage:check",
- "test": "npm run coverage"
+ "dependencies": {
+ "redis-errors": "^1.0.0"
},
- "version": "2.6.0"
+ "devDependencies": {
+ "benchmark": "^2.1.0",
+ "codeclimate-test-reporter": "^0.4.0",
+ "hiredis": "^0.5.0",
+ "istanbul": "^0.4.0",
+ "mocha": "^3.1.2",
+ "standard": "^10.0.0"
+ },
+ "author": "Ruben Bridgewater",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/NodeRedis/node-redis-parser/issues"
+ },
+ "homepage": "https://github.com/NodeRedis/node-redis-parser#readme",
+ "directories": {
+ "test": "test",
+ "lib": "lib"
+ }
}
diff --git a/node_modules/redis/.deepsource.toml b/node_modules/redis/.deepsource.toml
new file mode 100644
index 0000000..34bfad2
--- /dev/null
+++ b/node_modules/redis/.deepsource.toml
@@ -0,0 +1,9 @@
+version = 1
+exclude_patterns = ["examples/**"]
+
+[[analyzers]]
+name = "javascript"
+enabled = true
+
+ [analyzers.meta]
+ environment = ["nodejs"]
diff --git a/node_modules/redis/LICENSE b/node_modules/redis/LICENSE
old mode 100755
new mode 100644
index 710407f..db86cc4
--- a/node_modules/redis/LICENSE
+++ b/node_modules/redis/LICENSE
@@ -1,6 +1,6 @@
-LICENSE - "MIT License"
+MIT License
-Copyright (c) 2016 by NodeRedis
+Copyright (c) 2016-present Node Redis contributors.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@@ -21,4 +21,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/redis/README.md b/node_modules/redis/README.md
old mode 100755
new mode 100644
index 205503b..10f0c04
--- a/node_modules/redis/README.md
+++ b/node_modules/redis/README.md
@@ -1,88 +1,66 @@
-redis - a node.js redis client
-===========================
-
-[![Build Status](https://travis-ci.org/NodeRedis/node_redis.svg?branch=master)](https://travis-ci.org/NodeRedis/node_redis)
-[![Coverage Status](https://coveralls.io/repos/NodeRedis/node_redis/badge.svg?branch=)](https://coveralls.io/r/NodeRedis/node_redis?branch=)
-[![Windows Tests](https://img.shields.io/appveyor/ci/BridgeAR/node-redis/master.svg?label=Windows%20Tests)](https://ci.appveyor.com/project/BridgeAR/node-redis/branch/master)
-[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/NodeRedis/node_redis?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
-
-This is a complete and feature rich Redis client for node.js. __It supports all
-Redis commands__ and focuses on high performance.
-
-Install with:
+
+
+---
+
+## Installation
+
+```bash
+npm install redis
+```
- npm install redis
+## Usage
-## Usage Example
+#### Example
```js
-var redis = require("redis"),
- client = redis.createClient();
-
-// if you'd like to select database 3, instead of 0 (default), call
-// client.select(3, function() { /* ... */ });
+const redis = require("redis");
+const client = redis.createClient();
-client.on("error", function (err) {
- console.log("Error " + err);
+client.on("error", function(error) {
+ console.error(error);
});
-client.set("string key", "string val", redis.print);
-client.hset("hash key", "hashtest 1", "some value", redis.print);
-client.hset(["hash key", "hashtest 2", "some other value"], redis.print);
-client.hkeys("hash key", function (err, replies) {
- console.log(replies.length + " replies:");
- replies.forEach(function (reply, i) {
- console.log(" " + i + ": " + reply);
- });
- client.quit();
-});
+client.set("key", "value", redis.print);
+client.get("key", redis.print);
```
-This will display:
-
- mjr:~/work/node_redis (master)$ node example.js
- Reply: OK
- Reply: 0
- Reply: 0
- 2 replies:
- 0: hashtest 1
- 1: hashtest 2
- mjr:~/work/node_redis (master)$
-
Note that the API is entirely asynchronous. To get data back from the server,
-you'll need to use a callback. From v.2.6 on the API supports camelCase and
-snake_case and all options / variables / events etc. can be used either way. It
-is recommended to use camelCase as this is the default for the Node.js
-landscape.
+you'll need to use a callback.
### Promises
-You can also use node_redis with promises by promisifying node_redis with
-[bluebird](https://github.com/petkaantonov/bluebird) as in:
+Node Redis currently doesn't natively support promises (this is coming in v4), however you can wrap the methods you
+want to use with promises using the built-in Node.js `util.promisify` method on Node.js >= v8;
```js
-var redis = require('redis');
-bluebird.promisifyAll(redis.RedisClient.prototype);
-bluebird.promisifyAll(redis.Multi.prototype);
-```
-
-It'll add a *Async* to all node_redis functions (e.g. return client.getAsync().then())
-
-```js
-// We expect a value 'foo': 'bar' to be present
-// So instead of writing client.get('foo', cb); you have to write:
-return client.getAsync('foo').then(function(res) {
- console.log(res); // => 'bar'
-});
-
-// Using multi with promises looks like:
+const { promisify } = require("util");
+const getAsync = promisify(client.get).bind(client);
-return client.multi().get('foo').execAsync().then(function(res) {
- console.log(res); // => 'bar'
-});
+getAsync.then(console.log).catch(console.error);
```
-### Sending Commands
+### Commands
+
+This library is a 1 to 1 mapping of the [Redis commands](https://redis.io/commands).
Each Redis command is exposed as a function on the `client` object.
All functions take either an `args` Array plus optional `callback` Function or
@@ -90,195 +68,175 @@ a variable number of individual arguments followed by an optional callback.
Examples:
```js
-client.hmset(["key", "test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {});
+client.hmset(["key", "foo", "bar"], function(err, res) {
+ // ...
+});
+
// Works the same as
-client.hmset("key", ["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {});
+client.hmset("key", ["foo", "bar"], function(err, res) {
+ // ...
+});
+
// Or
-client.hmset("key", "test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {});
+client.hmset("key", "foo", "bar", function(err, res) {
+ // ...
+});
```
+Care should be taken with user input if arrays are possible (via body-parser, query string or other method), as single arguments could be unintentionally interpreted as multiple args.
+
Note that in either form the `callback` is optional:
```js
-client.set("some key", "some val");
-client.set(["some other key", "some val"]);
+client.set("foo", "bar");
+client.set(["hello", "world"]);
```
If the key is missing, reply will be null. Only if the [Redis Command
Reference](http://redis.io/commands) states something else it will not be null.
```js
-client.get("missingkey", function(err, reply) {
- // reply is null when the key is missing
- console.log(reply);
+client.get("missing_key", function(err, reply) {
+ // reply is null when the key is missing
+ console.log(reply);
});
```
-For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands)
-
Minimal parsing is done on the replies. Commands that return a integer return
JavaScript Numbers, arrays return JavaScript Array. `HGETALL` returns an Object
keyed by the hash keys. All strings will either be returned as string or as
buffer depending on your setting. Please be aware that sending null, undefined
and Boolean values will result in the value coerced to a string!
-# Redis Commands
+## API
-This library is a 1 to 1 mapping to [Redis commands](https://redis.io/commands).
-It is not a cache library so please refer to Redis commands page for full usage
-details.
-
-Example setting key to auto expire using [SET command](https://redis.io/commands/set)
-
-```js
-// this key will expire after 10 seconds
-client.set('key', 'value!', 'EX', 10);
-```
-
-# API
-
-## Connection and other Events
+### Connection and other Events
`client` will emit some events about the state of the connection to the Redis server.
-### "ready"
+#### `"ready"`
`client` will emit `ready` once a connection is established. Commands issued
before the `ready` event are queued, then replayed just before this event is
emitted.
-### "connect"
+#### `"connect"`
`client` will emit `connect` as soon as the stream is connected to the server.
-### "reconnecting"
+#### `"reconnecting"`
`client` will emit `reconnecting` when trying to reconnect to the Redis server
after losing the connection. Listeners are passed an object containing `delay`
-(in ms) and `attempt` (the attempt #) attributes.
+(in ms from the previous try) and `attempt` (the attempt #) attributes.
-### "error"
+#### `"error"`
`client` will emit `error` when encountering an error connecting to the Redis
-server or when any other in node_redis occurs. If you use a command without
+server or when any other in Node Redis occurs. If you use a command without
callback and encounter a ReplyError it is going to be emitted to the error
listener.
-So please attach the error listener to node_redis.
+So please attach the error listener to Node Redis.
-### "end"
+#### `"end"`
`client` will emit `end` when an established Redis server connection has closed.
-### "drain" (deprecated)
-
-`client` will emit `drain` when the TCP connection to the Redis server has been
-buffering, but is now writable. This event can be used to stream commands in to
-Redis and adapt to backpressure.
-
-If the stream is buffering `client.should_buffer` is set to true. Otherwise the
-variable is always set to false. That way you can decide when to reduce your
-send rate and resume sending commands when you get `drain`.
-
-You can also check the return value of each command as it will also return the
-backpressure indicator (deprecated). If false is returned the stream had to
-buffer.
-
-### "warning"
+#### `"warning"`
`client` will emit `warning` when password was set but none is needed and if a
deprecated option / function / similar is used.
-### "idle" (deprecated)
+### redis.createClient()
-`client` will emit `idle` when there are no outstanding commands that are
-awaiting a response.
-
-## redis.createClient()
If you have `redis-server` running on the same machine as node, then the
defaults for port and host are probably fine and you don't need to supply any
arguments. `createClient()` returns a `RedisClient` object. Otherwise,
`createClient()` accepts these arguments:
-* `redis.createClient([options])`
-* `redis.createClient(unix_socket[, options])`
-* `redis.createClient(redis_url[, options])`
-* `redis.createClient(port[, host][, options])`
+- `redis.createClient([options])`
+- `redis.createClient(unix_socket[, options])`
+- `redis.createClient(redis_url[, options])`
+- `redis.createClient(port[, host][, options])`
-__Tip:__ If the Redis server runs on the same machine as the client consider
+**Tip:** If the Redis server runs on the same machine as the client consider
using unix sockets if possible to increase throughput.
+**Note:** Using `'rediss://...` for the protocol in a `redis_url` will enable a TLS socket connection. However, additional TLS options will need to be passed in `options`, if required.
+
#### `options` object properties
-| Property | Default | Description |
-|-----------|-----------|-------------|
-| host | 127.0.0.1 | IP address of the Redis server |
-| port | 6379 | Port of the Redis server |
-| path | null | The UNIX socket string of the Redis server |
-| url | null | The URL of the Redis server. Format: `[redis:]//[[user][:password@]][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]` (More info avaliable at [IANA](http://www.iana.org/assignments/uri-schemes/prov/redis)). |
-| parser | javascript | __Deprecated__ Use either the built-in JS parser [`javascript`]() or the native [`hiredis`]() parser. __Note__ `node_redis` < 2.6 uses hiredis as default if installed. This changed in v.2.6.0. |
-| string_numbers | null | Set to `true`, `node_redis` will return Redis number values as Strings instead of javascript Numbers. Useful if you need to handle big numbers (above `Number.MAX_SAFE_INTEGER === 2^53`). Hiredis is incapable of this behavior, so setting this option to `true` will result in the built-in javascript parser being used no matter the value of the `parser` option. |
-| return_buffers | false | If set to `true`, then all replies will be sent to callbacks as Buffers instead of Strings. |
-| detect_buffers | false | If set to `true`, then replies will be sent to callbacks as Buffers. This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to every command on a client. __Note__: This doesn't work properly with the pubsub mode. A subscriber has to either always return Strings or Buffers. |
-| socket_keepalive | true | If set to `true`, the keep-alive functionality is enabled on the underlying socket. |
-| no_ready_check | false | When a connection is established to the Redis server, the server might still be loading the database from disk. While loading, the server will not respond to any commands. To work around this, `node_redis` has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. Setting `no_ready_check` to `true` will inhibit this check. |
-| enable_offline_queue | true | By default, if there is no active connection to the Redis server, commands are added to a queue and are executed once the connection has been established. Setting `enable_offline_queue` to `false` will disable this feature and the callback will be executed immediately with an error, or an error will be emitted if no callback is specified. |
-| retry_max_delay | null | __Deprecated__ _Please use `retry_strategy` instead._ By default, every time the client tries to connect and fails, the reconnection delay almost doubles. This delay normally grows infinitely, but setting `retry_max_delay` limits it to the maximum value provided in milliseconds. |
-| connect_timeout | 3600000 | __Deprecated__ _Please use `retry_strategy` instead._ Setting `connect_timeout` limits the total time for the client to connect and reconnect. The value is provided in milliseconds and is counted from the moment a new client is created or from the time the connection is lost. The last retry is going to happen exactly at the timeout time. Default is to try connecting until the default system socket timeout has been exceeded and to try reconnecting until 1h has elapsed. |
-| max_attempts | 0 | __Deprecated__ _Please use `retry_strategy` instead._ By default, a client will try reconnecting until connected. Setting `max_attempts` limits total amount of connection attempts. Setting this to 1 will prevent any reconnect attempt. |
-| retry_unfulfilled_commands | false | If set to `true`, all commands that were unfulfilled while the connection is lost will be retried after the connection has been reestablished. Use this with caution if you use state altering commands (e.g. `incr`). This is especially useful if you use blocking commands. |
-| password | null | If set, client will run Redis auth command on connect. Alias `auth_pass` __Note__ `node_redis` < 2.5 must use `auth_pass` |
-| db | null | If set, client will run Redis `select` command on connect. |
-| family | IPv4 | You can force using IPv6 if you set the family to 'IPv6'. See Node.js [net](https://nodejs.org/api/net.html) or [dns](https://nodejs.org/api/dns.html) modules on how to use the family type. |
-| disable_resubscribing | false | If set to `true`, a client won't resubscribe after disconnecting. |
-| rename_commands | null | Passing an object with renamed commands to use instead of the original functions. For example, if you renamed the command KEYS to "DO-NOT-USE" then the rename_commands object would be: `{ KEYS : "DO-NOT-USE" }` . See the [Redis security topics](http://redis.io/topics/security) for more info. |
-| tls | null | An object containing options to pass to [tls.connect](http://nodejs.org/api/tls.html#tls_tls_connect_port_host_options_callback) to set up a TLS connection to Redis (if, for example, it is set up to be accessible via a tunnel). |
-| prefix | null | A string used to prefix all used keys (e.g. `namespace:test`). Please be aware that the `keys` command will not be prefixed. The `keys` command has a "pattern" as argument and no key and it would be impossible to determine the existing keys in Redis if this would be prefixed. |
-| retry_strategy | function | A function that receives an options object as parameter including the retry `attempt`, the `total_retry_time` indicating how much time passed since the last time connected, the `error` why the connection was lost and the number of `times_connected` in total. If you return a number from this function, the retry will happen exactly after that time in milliseconds. If you return a non-number, no further retry will happen and all offline commands are flushed with errors. Return an error to return that specific error to all offline commands. Example below. |
+
+| Property | Default | Description |
+| -------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| host | 127.0.0.1 | IP address of the Redis server |
+| port | 6379 | Port of the Redis server |
+| path | null | The UNIX socket string of the Redis server |
+| url | null | The URL of the Redis server. Format: `[redis[s]:]//[[user][:password@]][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]` (More info avaliable at [IANA](http://www.iana.org/assignments/uri-schemes/prov/redis)). |
+| string_numbers | null | Set to `true`, Node Redis will return Redis number values as Strings instead of javascript Numbers. Useful if you need to handle big numbers (above `Number.MAX_SAFE_INTEGER === 2^53`). Hiredis is incapable of this behavior, so setting this option to `true` will result in the built-in javascript parser being used no matter the value of the `parser` option. |
+| return_buffers | false | If set to `true`, then all replies will be sent to callbacks as Buffers instead of Strings. |
+| detect_buffers | false | If set to `true`, then replies will be sent to callbacks as Buffers. This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to every command on a client. **Note**: This doesn't work properly with the pubsub mode. A subscriber has to either always return Strings or Buffers. |
+| socket_keepalive | true | If set to `true`, the keep-alive functionality is enabled on the underlying socket. |
+| socket_initial_delay | 0 | Initial Delay in milliseconds, and this will also behave the interval keep alive message sending to Redis. |
+| no_ready_check | false | When a connection is established to the Redis server, the server might still be loading the database from disk. While loading, the server will not respond to any commands. To work around this, Node Redis has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. Setting `no_ready_check` to `true` will inhibit this check. |
+| enable_offline_queue | true | By default, if there is no active connection to the Redis server, commands are added to a queue and are executed once the connection has been established. Setting `enable_offline_queue` to `false` will disable this feature and the callback will be executed immediately with an error, or an error will be emitted if no callback is specified. |
+| retry_unfulfilled_commands | false | If set to `true`, all commands that were unfulfilled while the connection is lost will be retried after the connection has been reestablished. Use this with caution if you use state altering commands (e.g. `incr`). This is especially useful if you use blocking commands. |
+| password | null | If set, client will run Redis auth command on connect. Alias `auth_pass` **Note** Node Redis < 2.5 must use `auth_pass` |
+| user | null | The ACL user (only valid when `password` is set) |
+| db | null | If set, client will run Redis `select` command on connect. |
+| family | IPv4 | You can force using IPv6 if you set the family to 'IPv6'. See Node.js [net](https://nodejs.org/api/net.html) or [dns](https://nodejs.org/api/dns.html) modules on how to use the family type. |
+| disable_resubscribing | false | If set to `true`, a client won't resubscribe after disconnecting. |
+| rename_commands | null | Passing an object with renamed commands to use instead of the original functions. For example, if you renamed the command KEYS to "DO-NOT-USE" then the rename_commands object would be: `{ KEYS : "DO-NOT-USE" }` . See the [Redis security topics](http://redis.io/topics/security) for more info. |
+| tls | null | An object containing options to pass to [tls.connect](http://nodejs.org/api/tls.html#tls_tls_connect_port_host_options_callback) to set up a TLS connection to Redis (if, for example, it is set up to be accessible via a tunnel). |
+| prefix | null | A string used to prefix all used keys (e.g. `namespace:test`). Please be aware that the `keys` command will not be prefixed. The `keys` command has a "pattern" as argument and no key and it would be impossible to determine the existing keys in Redis if this would be prefixed. |
+| retry_strategy | function | A function that receives an options object as parameter including the retry `attempt`, the `total_retry_time` indicating how much time passed since the last time connected, the `error` why the connection was lost and the number of `times_connected` in total. If you return a number from this function, the retry will happen exactly after that time in milliseconds. If you return a non-number, no further retry will happen and all offline commands are flushed with errors. Return an error to return that specific error to all offline commands. Example below. |
+| connect_timeout | 3600000 | In milliseconds. This should only be the timeout for connecting to redis, but for now it interferes with `retry_strategy` and stops it from reconnecting after this timeout. |
+
+**`detect_buffers` example:**
```js
-var redis = require("redis");
-var client = redis.createClient({detect_buffers: true});
+const redis = require("redis");
+const client = redis.createClient({ detect_buffers: true });
client.set("foo_rand000000000000", "OK");
// This will return a JavaScript String
-client.get("foo_rand000000000000", function (err, reply) {
- console.log(reply.toString()); // Will print `OK`
+client.get("foo_rand000000000000", function(err, reply) {
+ console.log(reply.toString()); // Will print `OK`
});
// This will return a Buffer since original key is specified as a Buffer
-client.get(new Buffer("foo_rand000000000000"), function (err, reply) {
- console.log(reply.toString()); // Will print ``
+client.get(new Buffer("foo_rand000000000000"), function(err, reply) {
+ console.log(reply.toString()); // Will print ``
});
-client.quit();
```
-retry_strategy example
+**`retry_strategy` example:**
```js
-var client = redis.createClient({
- retry_strategy: function (options) {
- if (options.error && options.error.code === 'ECONNREFUSED') {
- // End reconnecting on a specific error and flush all commands with
- // a individual error
- return new Error('The server refused the connection');
- }
- if (options.total_retry_time > 1000 * 60 * 60) {
- // End reconnecting after a specific timeout and flush all commands
- // with a individual error
- return new Error('Retry time exhausted');
- }
- if (options.attempt > 10) {
- // End reconnecting with built in error
- return undefined;
- }
- // reconnect after
- return Math.min(options.attempt * 100, 3000);
+const client = redis.createClient({
+ retry_strategy: function(options) {
+ if (options.error && options.error.code === "ECONNREFUSED") {
+ // End reconnecting on a specific error and flush all commands with
+ // a individual error
+ return new Error("The server refused the connection");
+ }
+ if (options.total_retry_time > 1000 * 60 * 60) {
+ // End reconnecting after a specific timeout and flush all commands
+ // with a individual error
+ return new Error("Retry time exhausted");
}
+ if (options.attempt > 10) {
+ // End reconnecting with built in error
+ return undefined;
+ }
+ // reconnect after
+ return Math.min(options.attempt * 100, 3000);
+ },
});
```
-## client.auth(password[, callback])
+### client.auth(password[, callback])
When connecting to a Redis server that requires authentication, the `AUTH`
command must be sent as the first command after connecting. This can be tricky
@@ -290,19 +248,7 @@ NOTE: Your call to `client.auth()` should not be inside the ready handler. If
you are doing this wrong, `client` will emit an error that looks
something like this `Error: Ready check failed: ERR operation not permitted`.
-## backpressure
-
-### stream
-
-The client exposed the used [stream](https://nodejs.org/api/stream.html) in
-`client.stream` and if the stream or client had to
-[buffer](https://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback)
-the command in `client.should_buffer`. In combination this can be used to
-implement backpressure by checking the buffer state before sending a command and
-listening to the stream
-[drain](https://nodejs.org/api/stream.html#stream_event_drain) event.
-
-## client.quit()
+### client.quit(callback)
This sends the quit command to the redis server and ends cleanly right after all
running commands were properly handled. If this is called while reconnecting
@@ -310,7 +256,7 @@ running commands were properly handled. If this is called while reconnecting
connection right away instead of resulting in further reconnections! All offline
commands are going to be flushed with an error in that case.
-## client.end(flush)
+### client.end(flush)
Forcibly close the connection to the Redis server. Note that this does not wait
until all replies have been parsed. If you want to exit cleanly, call
@@ -324,318 +270,321 @@ This example closes the connection to the Redis server before the replies have
been read. You probably don't want to do this:
```js
-var redis = require("redis"),
- client = redis.createClient();
+const redis = require("redis");
+const client = redis.createClient();
-client.set("foo_rand000000000000", "some fantastic value", function (err, reply) {
- // This will either result in an error (flush parameter is set to true)
- // or will silently fail and this callback will not be called at all (flush set to false)
- console.log(err);
+client.set("hello", "world", function(err) {
+ // This will either result in an error (flush parameter is set to true)
+ // or will silently fail and this callback will not be called at all (flush set to false)
+ console.error(err);
});
-client.end(true); // No further commands will be processed
-client.get("foo_rand000000000000", function (err, reply) {
- console.log(err); // => 'The connection has already been closed.'
+
+// No further commands will be processed
+client.end(true);
+
+client.get("hello", function(err) {
+ console.error(err); // => 'The connection has already been closed.'
});
```
`client.end()` without the flush parameter set to true should NOT be used in production!
-## Error handling (>= v.2.6)
+### Error Handling
-Currently the following error subclasses exist:
+Currently the following `Error` subclasses exist:
-* `RedisError`: _All errors_ returned by the client
-* `ReplyError` subclass of `RedisError`: All errors returned by __Redis__ itself
-* `AbortError` subclass of `RedisError`: All commands that could not finish due
+- `RedisError`: _All errors_ returned by the client
+- `ReplyError` subclass of `RedisError`: All errors returned by **Redis** itself
+- `AbortError` subclass of `RedisError`: All commands that could not finish due
to what ever reason
-* `ParserError` subclass of `RedisError`: Returned in case of a parser error
+- `ParserError` subclass of `RedisError`: Returned in case of a parser error
(this should not happen)
-* `AggregateError` subclass of `AbortError`: Emitted in case multiple unresolved
+- `AggregateError` subclass of `AbortError`: Emitted in case multiple unresolved
commands without callback got rejected in debug_mode instead of lots of
`AbortError`s.
All error classes are exported by the module.
-Example:
+#### Example
+
```js
-var redis = require('./');
-var assert = require('assert');
-var client = redis.createClient();
-
-client.on('error', function (err) {
- assert(err instanceof Error);
- assert(err instanceof redis.AbortError);
- assert(err instanceof redis.AggregateError);
- // The set and get get aggregated in here
- assert.strictEqual(err.errors.length, 2);
- assert.strictEqual(err.code, 'NR_CLOSED');
-});
-client.set('foo', 123, 'bar', function (err, res) { // Too many arguments
- assert(err instanceof redis.ReplyError); // => true
- assert.strictEqual(err.command, 'SET');
- assert.deepStrictEqual(err.args, ['foo', 123, 'bar']);
-
- redis.debug_mode = true;
- client.set('foo', 'bar');
- client.get('foo');
- process.nextTick(function () {
- // Force closing the connection while the command did not yet return
- client.end(true);
- redis.debug_mode = false;
- });
+const assert = require("assert");
+
+const redis = require("redis");
+const { AbortError, AggregateError, ReplyError } = require("redis");
+
+const client = redis.createClient();
+
+client.on("error", function(err) {
+ assert(err instanceof Error);
+ assert(err instanceof AbortError);
+ assert(err instanceof AggregateError);
+
+ // The set and get are aggregated in here
+ assert.strictEqual(err.errors.length, 2);
+ assert.strictEqual(err.code, "NR_CLOSED");
});
+client.set("foo", "bar", "baz", function(err, res) {
+ // Too many arguments
+ assert(err instanceof ReplyError); // => true
+ assert.strictEqual(err.command, "SET");
+ assert.deepStrictEqual(err.args, ["foo", 123, "bar"]);
+
+ redis.debug_mode = true;
+
+ client.set("foo", "bar");
+ client.get("foo");
+
+ process.nextTick(function() {
+ // Force closing the connection while the command did not yet return
+ client.end(true);
+ redis.debug_mode = false;
+ });
+});
```
Every `ReplyError` contains the `command` name in all-caps and the arguments (`args`).
-If node_redis emits a library error because of another error, the triggering
+If Node Redis emits a library error because of another error, the triggering
error is added to the returned error as `origin` attribute.
-___Error codes___
+**_Error codes_**
-node_redis returns a `NR_CLOSED` error code if the clients connection dropped.
+Node Redis returns a `NR_CLOSED` error code if the clients connection dropped.
If a command unresolved command got rejected a `UNCERTAIN_STATE` code is
-returned. A `CONNECTION_BROKEN` error code is used in case node_redis gives up
+returned. A `CONNECTION_BROKEN` error code is used in case Node Redis gives up
to reconnect.
-## client.unref()
+### client.unref()
Call `unref()` on the underlying socket connection to the Redis server, allowing
the program to exit once no more commands are pending.
This is an **experimental** feature, and only supports a subset of the Redis
protocol. Any commands where client state is saved on the Redis server, e.g.
-`*SUBSCRIBE` or the blocking `BL*` commands will *NOT* work with `.unref()`.
+`*SUBSCRIBE` or the blocking `BL*` commands will _NOT_ work with `.unref()`.
```js
-var redis = require("redis")
-var client = redis.createClient()
+const redis = require("redis");
+const client = redis.createClient();
/*
- Calling unref() will allow this program to exit immediately after the get
- command finishes. Otherwise the client would hang as long as the
- client-server connection is alive.
-*/
-client.unref()
-client.get("foo", function (err, value){
- if (err) throw(err)
- console.log(value)
-})
+ * Calling unref() will allow this program to exit immediately after the get
+ * command finishes. Otherwise the client would hang as long as the
+ * client-server connection is alive.
+ */
+client.unref();
+
+client.get("foo", function(err, value) {
+ if (err) throw err;
+ console.log(value);
+});
```
-## Friendlier hash commands
+### Hash Commands
Most Redis commands take a single String or an Array of Strings as arguments,
and replies are sent back as a single String or an Array of Strings. When
dealing with hash values, there are a couple of useful exceptions to this.
-### client.hgetall(hash, callback)
+#### client.hgetall(hash, callback)
-The reply from an HGETALL command will be converted into a JavaScript Object by
-`node_redis`. That way you can interact with the responses using JavaScript
-syntax.
+The reply from an `HGETALL` command will be converted into a JavaScript Object. That way you can interact with the
+responses using JavaScript syntax.
-Example:
+**Example:**
```js
-client.hmset("hosts", "mjr", "1", "another", "23", "home", "1234");
-client.hgetall("hosts", function (err, obj) {
- console.dir(obj);
+client.hmset("key", "foo", "bar", "hello", "world");
+
+client.hgetall("key", function(err, value) {
+ console.log(value.foo); // > "bar"
+ console.log(value.hello); // > "world"
});
```
-Output:
-
-```js
-{ mjr: '1', another: '23', home: '1234' }
-```
+#### client.hmset(hash, key1, val1, ...keyN, valN, [callback])
-### client.hmset(hash, obj[, callback])
+Multiple values may also be set by supplying more arguments.
-Multiple values in a hash can be set by supplying an object:
+**Example:**
```js
-client.HMSET(key2, {
- "0123456789": "abcdefghij", // NOTE: key and value will be coerced to strings
- "some manner of key": "a type of value"
-});
+// key
+// 1) foo => bar
+// 2) hello => world
+client.HMSET("key", "foo", "bar", "hello", "world");
```
-The properties and values of this Object will be set as keys and values in the
-Redis hash.
+### PubSub
-### client.hmset(hash, key1, val1, ... keyn, valn, [callback])
+#### Example
-Multiple values may also be set by supplying a list:
+This example opens two client connections, subscribes to a channel on one of them, and publishes to that
+channel on the other.
```js
-client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value");
-```
+const redis = require("redis");
-## Publish / Subscribe
+const subscriber = redis.createClient();
+const publisher = redis.createClient();
-Example of the publish / subscribe API. This program opens two
-client connections, subscribes to a channel on one of them, and publishes to that
-channel on the other:
+let messageCount = 0;
-```js
-var redis = require("redis");
-var sub = redis.createClient(), pub = redis.createClient();
-var msg_count = 0;
-
-sub.on("subscribe", function (channel, count) {
- pub.publish("a nice channel", "I am sending a message.");
- pub.publish("a nice channel", "I am sending a second message.");
- pub.publish("a nice channel", "I am sending my last message.");
+subscriber.on("subscribe", function(channel, count) {
+ publisher.publish("a channel", "a message");
+ publisher.publish("a channel", "another message");
});
-sub.on("message", function (channel, message) {
- console.log("sub channel " + channel + ": " + message);
- msg_count += 1;
- if (msg_count === 3) {
- sub.unsubscribe();
- sub.quit();
- pub.quit();
- }
+subscriber.on("message", function(channel, message) {
+ messageCount += 1;
+
+ console.log("Subscriber received message in channel '" + channel + "': " + message);
+
+ if (messageCount === 2) {
+ subscriber.unsubscribe();
+ subscriber.quit();
+ publisher.quit();
+ }
});
-sub.subscribe("a nice channel");
+subscriber.subscribe("a channel");
```
When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into
-a "subscriber" mode. At that point, only commands that modify the subscription
-set are valid and quit (and depending on the redis version ping as well). When
+a `"subscriber"` mode. At that point, the only valid commands are those that modify the subscription
+set, and quit (also ping on some redis versions). When
the subscription set is empty, the connection is put back into regular mode.
If you need to send regular commands to Redis while in subscriber mode, just
-open another connection with a new client (hint: use `client.duplicate()`).
+open another connection with a new client (use `client.duplicate()` to quickly duplicate an existing client).
-## Subscriber Events
+#### Subscriber Events
If a client has subscriptions active, it may emit these events:
-### "message" (channel, message)
+**"message" (channel, message)**:
Client will emit `message` for every message received that matches an active subscription.
Listeners are passed the channel name as `channel` and the message as `message`.
-### "pmessage" (pattern, channel, message)
+**"pmessage" (pattern, channel, message)**:
Client will emit `pmessage` for every message received that matches an active
subscription pattern. Listeners are passed the original pattern used with
`PSUBSCRIBE` as `pattern`, the sending channel name as `channel`, and the
message as `message`.
-### "message_buffer" (channel, message)
+**"message_buffer" (channel, message)**:
This is the same as the `message` event with the exception, that it is always
going to emit a buffer. If you listen to the `message` event at the same time as
the `message_buffer`, it is always going to emit a string.
-### "pmessage_buffer" (pattern, channel, message)
+**"pmessage_buffer" (pattern, channel, message)**:
This is the same as the `pmessage` event with the exception, that it is always
going to emit a buffer. If you listen to the `pmessage` event at the same time
as the `pmessage_buffer`, it is always going to emit a string.
-### "subscribe" (channel, count)
+**"subscribe" (channel, count)**:
Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are
passed the channel name as `channel` and the new count of subscriptions for this
client as `count`.
-### "psubscribe" (pattern, count)
+**"psubscribe" (pattern, count)**:
Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners
are passed the original pattern as `pattern`, and the new count of subscriptions
for this client as `count`.
-### "unsubscribe" (channel, count)
+**"unsubscribe" (channel, count)**:
Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners
are passed the channel name as `channel` and the new count of subscriptions for
this client as `count`. When `count` is 0, this client has left subscriber mode
and no more subscriber events will be emitted.
-### "punsubscribe" (pattern, count)
+**"punsubscribe" (pattern, count)**:
Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command.
Listeners are passed the channel name as `channel` and the new count of
subscriptions for this client as `count`. When `count` is 0, this client has
left subscriber mode and no more subscriber events will be emitted.
-## client.multi([commands])
+### client.multi([commands])
`MULTI` commands are queued up until an `EXEC` is issued, and then all commands
-are run atomically by Redis. The interface in `node_redis` is to return an
+are run atomically by Redis. The interface returns an
individual `Multi` object by calling `client.multi()`. If any command fails to
queue, all commands are rolled back and none is going to be executed (For
-further information look at
-[transactions](http://redis.io/topics/transactions)).
+further information see the [Redis transactions](http://redis.io/topics/transactions) documentation).
```js
-var redis = require("./index"),
- client = redis.createClient(), set_size = 20;
+const redis = require("redis");
+const client = redis.createClient();
+
+let setSize = 20;
-client.sadd("bigset", "a member");
-client.sadd("bigset", "another member");
+client.sadd("key", "member1");
+client.sadd("key", "member2");
-while (set_size > 0) {
- client.sadd("bigset", "member " + set_size);
- set_size -= 1;
+while (setSize > 0) {
+ client.sadd("key", "member" + setSize);
+ setSize -= 1;
}
-// multi chain with an individual callback
-client.multi()
- .scard("bigset")
- .smembers("bigset")
- .keys("*", function (err, replies) {
- // NOTE: code in this callback is NOT atomic
- // this only happens after the the .exec call finishes.
- client.mget(replies, redis.print);
- })
- .dbsize()
- .exec(function (err, replies) {
- console.log("MULTI got " + replies.length + " replies");
- replies.forEach(function (reply, index) {
- console.log("Reply " + index + ": " + reply.toString());
- });
+// chain commands
+client
+ .multi()
+ .scard("key")
+ .smembers("key")
+ .keys("*")
+ .dbsize()
+ .exec(function(err, replies) {
+ console.log("MULTI got " + replies.length + " replies");
+ replies.forEach(function(reply, index) {
+ console.log("REPLY @ index " + index + ": " + reply.toString());
});
+ });
```
-### Multi.exec([callback])
+#### Multi.exec([callback])
`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects
share all of the same command methods as `client` objects do. Commands are
queued up inside the `Multi` object until `Multi.exec()` is invoked.
-If your code contains an syntax error an EXECABORT error is going to be thrown
+If your code contains an syntax error an `EXECABORT` error is going to be thrown
and all commands are going to be aborted. That error contains a `.errors`
property that contains the concrete errors.
If all commands were queued successfully and an error is thrown by redis while
processing the commands that error is going to be returned in the result array!
-No other command is going to be aborted though than the onces failing.
+No other command is going to be aborted though than the ones failing.
You can either chain together `MULTI` commands as in the above example, or you
can queue individual commands while still sending regular client command as in
this example:
```js
-var redis = require("redis"),
- client = redis.createClient(), multi;
+const redis = require("redis");
+const client = redis.createClient();
// start a separate multi command queue
-multi = client.multi();
-multi.incr("incr thing", redis.print);
-multi.incr("incr other thing", redis.print);
+const multi = client.multi();
-// runs immediately
-client.mset("incr thing", 100, "incr other thing", 1, redis.print);
+// add some commands to the queue
+multi.incr("count_cats", redis.print);
+multi.incr("count_dogs", redis.print);
-// drains multi queue and runs atomically
-multi.exec(function (err, replies) {
- console.log(replies); // 101, 2
+// runs a command immediately outside of the `multi` instance
+client.mset("count_cats", 100, "count_dogs", 50, redis.print);
+
+// drains the multi queue and runs each command atomically
+multi.exec(function(err, replies) {
+ console.log(replies); // 101, 51
});
```
@@ -643,30 +592,161 @@ In addition to adding commands to the `MULTI` queue individually, you can also
pass an array of commands and arguments to the constructor:
```js
-var redis = require("redis"),
- client = redis.createClient(), multi;
-
-client.multi([
- ["mget", "multifoo", "multibar", redis.print],
- ["incr", "multifoo"],
- ["incr", "multibar"]
-]).exec(function (err, replies) {
+const redis = require("redis");
+
+const client = redis.createClient();
+
+client
+ .multi([
+ ["mget", "foo", "bar", redis.print],
+ ["incr", "hello"],
+ ])
+ .exec(function(err, replies) {
console.log(replies);
-});
+ });
```
-### Multi.exec_atomic([callback])
+#### Multi.exec_atomic([callback])
Identical to Multi.exec but with the difference that executing a single command
will not use transactions.
-## client.batch([commands])
+#### Optimistic Locks
+
+Using `multi` you can make sure your modifications run as a transaction, but you
+can't be sure you got there first. What if another client modified a key while
+you were working with it's data?
+
+To solve this, Redis supports the [WATCH](https://redis.io/topics/transactions)
+command, which is meant to be used with MULTI:
+
+```js
+const redis = require("redis");
+
+const client = redis.createClient();
+
+client.watch("foo", function(watchError) {
+ if (watchError) throw watchError;
+
+ client.get("foo", function(getError, result) {
+ if (getError) throw getError;
+
+ // Process result
+ // Heavy and time consuming operation here to generate "bar"
+
+ client
+ .multi()
+ .set("foo", "bar")
+ .exec(function(execError, results) {
+ /**
+ * If err is null, it means Redis successfully attempted
+ * the operation.
+ */
+ if (execError) throw execError;
+
+ /**
+ * If results === null, it means that a concurrent client
+ * changed the key while we were processing it and thus
+ * the execution of the MULTI command was not performed.
+ *
+ * NOTICE: Failing an execution of MULTI is not considered
+ * an error. So you will have err === null and results === null
+ */
+ });
+ });
+});
+```
+
+The above snippet shows the correct usage of `watch` with `multi`. Every time a
+watched key is changed before the execution of a `multi` command, the execution
+will return `null`. On a normal situation, the execution will return an array of
+values with the results of the operations.
+
+As stated in the snippet, failing the execution of a `multi` command being watched
+is not considered an error. The execution may return an error if, for example, the
+client cannot connect to Redis.
+
+An example where we can see the execution of a `multi` command fail is as follows:
+
+```js
+const clients = {
+ watcher: redis.createClient(),
+ modifier: redis.createClient(),
+};
+
+clients.watcher.watch("foo", function(watchError) {
+ if (watchError) throw watchError;
+
+ // if you comment out the next line, the transaction will work
+ clients.modifier.set("foo", Math.random(), setError => {
+ if (setError) throw setError;
+ });
+
+ // using a setTimeout here to ensure that the MULTI/EXEC will come after the SET.
+ // Normally, you would use a callback to ensure order, but I want the above SET command
+ // to be easily comment-out-able.
+ setTimeout(function() {
+ clients.watcher
+ .multi()
+ .set("foo", "bar")
+ .set("hello", "world")
+ .exec((multiExecError, results) => {
+ if (multiExecError) throw multiExecError;
+
+ if (results === null) {
+ console.log("transaction aborted because results were null");
+ } else {
+ console.log("transaction worked and returned", results);
+ }
+
+ clients.watcher.quit();
+ clients.modifier.quit();
+ });
+ }, 1000);
+});
+```
+
+#### `WATCH` limitations
+
+Redis WATCH works only on _whole_ key values. For example, with WATCH you can
+watch a hash for modifications, but you cannot watch a specific field of a hash.
+
+The following example would watch the keys `foo` and `hello`, not the field `hello`
+of hash `foo`:
+
+```js
+const redis = require("redis");
+
+const client = redis.createClient();
+
+client.hget("foo", "hello", function(hashGetError, result) {
+ if (hashGetError) throw hashGetError;
+
+ //Do some processing with the value from this field and watch it after
+
+ client.watch("foo", "hello", function(watchError) {
+ if (watchError) throw watchError;
+
+ /**
+ * This is now watching the keys 'foo' and 'hello'. It is not
+ * watching the field 'hello' of hash 'foo'. Because the key 'foo'
+ * refers to a hash, this command is now watching the entire hash
+ * for modifications.
+ */
+ });
+});
+```
+
+This limitation also applies to sets (you can not watch individual set members)
+and any other collections.
+
+### client.batch([commands])
-Identical to .multi without transactions. This is recommended if you want to
-execute many commands at once but don't have to rely on transactions.
+Identical to `.multi()` without transactions. This is recommended if you want to
+execute many commands at once but don't need to rely on transactions.
`BATCH` commands are queued up until an `EXEC` is issued, and then all commands
-are run atomically by Redis. The interface in `node_redis` is to return an
+are run atomically by Redis. The interface returns an
individual `Batch` object by calling `client.batch()`. The only difference
between .batch and .multi is that no transaction is going to be used.
Be aware that the errors are - just like in multi statements - in the result.
@@ -677,7 +757,7 @@ significantly compared to firing the same commands in a loop without waiting for
the result! See the benchmarks for further comparison. Please remember that all
commands are kept in memory until they are fired.
-## Monitor mode
+### Monitor mode
Redis supports the `MONITOR` command, which lets you see all commands received
by the Redis server across all client connections, including from other client
@@ -688,25 +768,28 @@ connected to the server including the monitoring client itself. The callback for
the `monitor` event takes a timestamp from the Redis server, an array of command
arguments and the raw monitoring string.
-Example:
+#### Example:
```js
-var client = require("redis").createClient();
-client.monitor(function (err, res) {
- console.log("Entering monitoring mode.");
+const redis = require("redis");
+const client = redis.createClient();
+
+client.monitor(function(err, res) {
+ console.log("Entering monitoring mode.");
});
-client.set('foo', 'bar');
-client.on("monitor", function (time, args, raw_reply) {
- console.log(time + ": " + args); // 1458910076.446514:['set', 'foo', 'bar']
+client.set("foo", "bar");
+
+client.on("monitor", function(time, args, rawReply) {
+ console.log(time + ": " + args); // 1458910076.446514:['set', 'foo', 'bar']
});
```
-# Extras
+## Extras
-Some other things you might like to know about.
+Some other things you might find useful.
-## client.server_info
+### `client.server_info`
After the ready probe completes, the results from the INFO command are saved in
the `client.server_info` object.
@@ -714,42 +797,45 @@ the `client.server_info` object.
The `versions` key contains an array of the elements of the version string for
easy comparison.
- > client.server_info.redis_version
- '2.3.0'
- > client.server_info.versions
- [ 2, 3, 0 ]
+```
+> client.server_info.redis_version
+'2.3.0'
+> client.server_info.versions
+[ 2, 3, 0 ]
+```
-## redis.print()
+### `redis.print()`
A handy callback function for displaying return values when testing. Example:
```js
-var redis = require("redis"),
- client = redis.createClient();
+const redis = require("redis");
+const client = redis.createClient();
-client.on("connect", function () {
- client.set("foo_rand000000000000", "some fantastic value", redis.print);
- client.get("foo_rand000000000000", redis.print);
+client.on("connect", function() {
+ client.set("foo", "bar", redis.print); // => "Reply: OK"
+ client.get("foo", redis.print); // => "Reply: bar"
+ client.quit();
});
```
-This will print:
-
- Reply: OK
- Reply: some fantastic value
-
-Note that this program will not exit cleanly because the client is still connected.
-
-## Multi-word commands
+### Multi-word commands
To execute redis multi-word commands like `SCRIPT LOAD` or `CLIENT LIST` pass
the second word as first parameter:
- client.script('load', 'return 1');
- client.multi().script('load', 'return 1').exec(...);
- client.multi([['script', 'load', 'return 1']]).exec(...);
+```js
+client.script("load", "return 1");
+
+client
+ .multi()
+ .script("load", "return 1")
+ .exec();
+
+client.multi([["script", "load", "return 1"]]).exec();
+```
-## client.duplicate([options][, callback])
+### `client.duplicate([options][, callback])`
Duplicate all current options and return a new redisClient instance. All options
passed to the duplicate function are going to replace the original option. If
@@ -758,59 +844,40 @@ returns it in the callback. If an error occurs in the meanwhile, that is going
to return an error instead in the callback.
One example of when to use duplicate() would be to accommodate the connection-
-blocking redis commands BRPOP, BLPOP, and BRPOPLPUSH. If these commands
-are used on the same redisClient instance as non-blocking commands, the
+blocking redis commands `BRPOP`, `BLPOP`, and `BRPOPLPUSH`. If these commands
+are used on the same Redis client instance as non-blocking commands, the
non-blocking ones may be queued up until after the blocking ones finish.
- var Redis=require('redis');
- var client = Redis.createClient();
- var clientBlocking = client.duplicate();
-
- var get = function() {
- console.log("get called");
- client.get("any_key",function() { console.log("get returned"); });
- setTimeout( get, 1000 );
- };
- var brpop = function() {
- console.log("brpop called");
- clientBlocking.brpop("nonexistent", 5, function() {
- console.log("brpop return");
- setTimeout( brpop, 1000 );
- });
- };
- get();
- brpop();
-
Another reason to use duplicate() is when multiple DBs on the same server are
-accessed via the redis SELECT command. Each DB could use its own connection.
+accessed via the redis SELECT command. Each DB could use its own connection.
-## client.send_command(command_name[, [args][, callback]])
+### `client.sendCommand(command_name[, [args][, callback]])`
All Redis commands have been added to the `client` object. However, if new
commands are introduced before this library is updated or if you want to add
-individual commands you can use `send_command()` to send arbitrary commands to
+individual commands you can use `sendCommand()` to send arbitrary commands to
Redis.
All commands are sent as multi-bulk commands. `args` can either be an Array of
arguments, or omitted / set to undefined.
-## client.add_command(command_name)
+### `redis.addCommand(command_name)`
-Calling add_command will add a new command to the prototype. The exact command
+Calling addCommand will add a new command to the prototype. The exact command
name will be used when calling using this new command. Using arbitrary arguments
is possible as with any other command.
-## client.connected
+### `client.connected`
Boolean tracking the state of the connection to the Redis server.
-## client.command_queue_length
+### `client.command_queue_length`
The number of commands that have been sent to the Redis server but not yet
replied to. You can use this to enforce some kind of maximum queue depth for
commands while connected.
-## client.offline_queue_length
+### `client.offline_queue_length`
The number of commands that have been queued up for a future connection. You can
use this to enforce some kind of maximum queue depth for pre-connection
@@ -818,82 +885,84 @@ commands.
### Commands with Optional and Keyword arguments
-This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset
-count]` in the [redis.io/commands](http://redis.io/commands) documentation.
+This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation.
-Example:
+#### Example
```js
-var args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ];
-client.zadd(args, function (err, response) {
- if (err) throw err;
- console.log('added '+response+' items.');
-
- // -Infinity and +Infinity also work
- var args1 = [ 'myzset', '+inf', '-inf' ];
- client.zrevrangebyscore(args1, function (err, response) {
- if (err) throw err;
- console.log('example1', response);
- // write your code here
- });
-
- var max = 3, min = 1, offset = 1, count = 2;
- var args2 = [ 'myzset', max, min, 'WITHSCORES', 'LIMIT', offset, count ];
- client.zrevrangebyscore(args2, function (err, response) {
- if (err) throw err;
- console.log('example2', response);
- // write your code here
- });
+const args = ["myzset", 1, "one", 2, "two", 3, "three", 99, "ninety-nine"];
+
+client.zadd(args, function(addError, addResponse) {
+ if (addError) throw addError;
+ console.log("added " + addResponse + " items.");
+
+ // -Infinity and +Infinity also work
+ const args1 = ["myzset", "+inf", "-inf"];
+ client.zrevrangebyscore(args1, function(rangeError, rangeResponse) {
+ if (rangeError) throw rangeError;
+ console.log("response1", rangeResponse);
+ // ...
+ });
+
+ const max = 3;
+ const min = 1;
+ const offset = 1;
+ const count = 2;
+ const args2 = ["myzset", max, min, "WITHSCORES", "LIMIT", offset, count];
+ client.zrevrangebyscore(args2, function(rangeError, rangeResponse) {
+ if (rangeError) throw rangeError;
+ console.log("response2", rangeResponse);
+ // ...
+ });
});
```
## Performance
-Much effort has been spent to make `node_redis` as fast as possible for common
-operations.
-
-```
-Lenovo T450s, i7-5600U and 12gb memory
-clients: 1, NodeJS: 6.2.0, Redis: 3.2.0, parser: javascript, connected by: tcp
- PING, 1/1 avg/max: 0.02/ 5.26 2501ms total, 46916 ops/sec
- PING, batch 50/1 avg/max: 0.06/ 4.35 2501ms total, 755178 ops/sec
- SET 4B str, 1/1 avg/max: 0.02/ 4.75 2501ms total, 40856 ops/sec
- SET 4B str, batch 50/1 avg/max: 0.11/ 1.51 2501ms total, 432727 ops/sec
- SET 4B buf, 1/1 avg/max: 0.05/ 2.76 2501ms total, 20659 ops/sec
- SET 4B buf, batch 50/1 avg/max: 0.25/ 1.76 2501ms total, 194962 ops/sec
- GET 4B str, 1/1 avg/max: 0.02/ 1.55 2501ms total, 45156 ops/sec
- GET 4B str, batch 50/1 avg/max: 0.09/ 3.15 2501ms total, 524110 ops/sec
- GET 4B buf, 1/1 avg/max: 0.02/ 3.07 2501ms total, 44563 ops/sec
- GET 4B buf, batch 50/1 avg/max: 0.10/ 3.18 2501ms total, 473171 ops/sec
- SET 4KiB str, 1/1 avg/max: 0.03/ 1.54 2501ms total, 32627 ops/sec
- SET 4KiB str, batch 50/1 avg/max: 0.34/ 1.89 2501ms total, 146861 ops/sec
- SET 4KiB buf, 1/1 avg/max: 0.05/ 2.85 2501ms total, 20688 ops/sec
- SET 4KiB buf, batch 50/1 avg/max: 0.36/ 1.83 2501ms total, 138165 ops/sec
- GET 4KiB str, 1/1 avg/max: 0.02/ 1.37 2501ms total, 39389 ops/sec
- GET 4KiB str, batch 50/1 avg/max: 0.24/ 1.81 2501ms total, 208157 ops/sec
- GET 4KiB buf, 1/1 avg/max: 0.02/ 2.63 2501ms total, 39918 ops/sec
- GET 4KiB buf, batch 50/1 avg/max: 0.31/ 8.56 2501ms total, 161575 ops/sec
- INCR, 1/1 avg/max: 0.02/ 4.69 2501ms total, 45685 ops/sec
- INCR, batch 50/1 avg/max: 0.09/ 3.06 2501ms total, 539964 ops/sec
- LPUSH, 1/1 avg/max: 0.02/ 3.04 2501ms total, 41253 ops/sec
- LPUSH, batch 50/1 avg/max: 0.12/ 1.94 2501ms total, 425090 ops/sec
- LRANGE 10, 1/1 avg/max: 0.02/ 2.28 2501ms total, 39850 ops/sec
- LRANGE 10, batch 50/1 avg/max: 0.25/ 1.85 2501ms total, 194302 ops/sec
- LRANGE 100, 1/1 avg/max: 0.05/ 2.93 2501ms total, 21026 ops/sec
- LRANGE 100, batch 50/1 avg/max: 1.52/ 2.89 2501ms total, 32767 ops/sec
- SET 4MiB str, 1/1 avg/max: 5.16/ 15.55 2502ms total, 193 ops/sec
- SET 4MiB str, batch 20/1 avg/max: 89.73/ 99.96 2513ms total, 223 ops/sec
- SET 4MiB buf, 1/1 avg/max: 2.23/ 8.35 2501ms total, 446 ops/sec
- SET 4MiB buf, batch 20/1 avg/max: 41.47/ 50.91 2530ms total, 482 ops/sec
- GET 4MiB str, 1/1 avg/max: 2.79/ 10.91 2502ms total, 358 ops/sec
- GET 4MiB str, batch 20/1 avg/max: 101.61/118.11 2541ms total, 197 ops/sec
- GET 4MiB buf, 1/1 avg/max: 2.32/ 14.93 2502ms total, 430 ops/sec
- GET 4MiB buf, batch 20/1 avg/max: 65.01/ 84.72 2536ms total, 308 ops/sec
- ```
+Much effort has been spent to make Node Redis as fast as possible for common operations.
+
+```
+Mac mini (2018), i7-3.2GHz and 32gb memory
+clients: 1, NodeJS: 12.15.0, Redis: 5.0.6, parser: javascript, connected by: tcp
+ PING, 1/1 avg/max: 0.03/ 3.28 2501ms total, 31926 ops/sec
+ PING, batch 50/1 avg/max: 0.08/ 3.35 2501ms total, 599460 ops/sec
+ SET 4B str, 1/1 avg/max: 0.03/ 3.54 2501ms total, 29483 ops/sec
+ SET 4B str, batch 50/1 avg/max: 0.10/ 1.39 2501ms total, 477689 ops/sec
+ SET 4B buf, 1/1 avg/max: 0.04/ 1.52 2501ms total, 23449 ops/sec
+ SET 4B buf, batch 50/1 avg/max: 0.20/ 2.09 2501ms total, 244382 ops/sec
+ GET 4B str, 1/1 avg/max: 0.03/ 1.35 2501ms total, 32205 ops/sec
+ GET 4B str, batch 50/1 avg/max: 0.09/ 2.02 2501ms total, 568992 ops/sec
+ GET 4B buf, 1/1 avg/max: 0.03/ 2.93 2501ms total, 32802 ops/sec
+ GET 4B buf, batch 50/1 avg/max: 0.08/ 1.03 2501ms total, 592863 ops/sec
+ SET 4KiB str, 1/1 avg/max: 0.03/ 0.76 2501ms total, 29287 ops/sec
+ SET 4KiB str, batch 50/1 avg/max: 0.35/ 2.97 2501ms total, 143163 ops/sec
+ SET 4KiB buf, 1/1 avg/max: 0.04/ 1.21 2501ms total, 23070 ops/sec
+ SET 4KiB buf, batch 50/1 avg/max: 0.28/ 2.34 2501ms total, 176809 ops/sec
+ GET 4KiB str, 1/1 avg/max: 0.03/ 1.54 2501ms total, 29555 ops/sec
+ GET 4KiB str, batch 50/1 avg/max: 0.18/ 1.59 2501ms total, 279188 ops/sec
+ GET 4KiB buf, 1/1 avg/max: 0.03/ 1.80 2501ms total, 30681 ops/sec
+ GET 4KiB buf, batch 50/1 avg/max: 0.17/ 5.00 2501ms total, 285886 ops/sec
+ INCR, 1/1 avg/max: 0.03/ 1.99 2501ms total, 32757 ops/sec
+ INCR, batch 50/1 avg/max: 0.09/ 2.54 2501ms total, 538964 ops/sec
+ LPUSH, 1/1 avg/max: 0.05/ 4.85 2501ms total, 19482 ops/sec
+ LPUSH, batch 50/1 avg/max: 0.12/ 9.52 2501ms total, 395562 ops/sec
+ LRANGE 10, 1/1 avg/max: 0.06/ 9.21 2501ms total, 17062 ops/sec
+ LRANGE 10, batch 50/1 avg/max: 0.22/ 1.03 2501ms total, 228269 ops/sec
+ LRANGE 100, 1/1 avg/max: 0.05/ 1.44 2501ms total, 19051 ops/sec
+ LRANGE 100, batch 50/1 avg/max: 0.99/ 3.46 2501ms total, 50480 ops/sec
+ SET 4MiB str, 1/1 avg/max: 4.11/ 13.96 2501ms total, 243 ops/sec
+ SET 4MiB str, batch 20/1 avg/max: 91.16/145.01 2553ms total, 219 ops/sec
+ SET 4MiB buf, 1/1 avg/max: 2.81/ 11.90 2502ms total, 354 ops/sec
+ SET 4MiB buf, batch 20/1 avg/max: 36.21/ 70.96 2535ms total, 552 ops/sec
+ GET 4MiB str, 1/1 avg/max: 2.82/ 19.10 2503ms total, 354 ops/sec
+ GET 4MiB str, batch 20/1 avg/max: 128.57/207.86 2572ms total, 156 ops/sec
+ GET 4MiB buf, 1/1 avg/max: 3.13/ 23.88 2501ms total, 318 ops/sec
+ GET 4MiB buf, batch 20/1 avg/max: 65.91/ 87.59 2572ms total, 303 ops/sec
+```
## Debugging
-To get debug output run your `node_redis` application with `NODE_DEBUG=redis`.
+To get debug output run your Node Redis application with `NODE_DEBUG=redis`.
This is also going to result in good stack traces opposed to useless ones
otherwise for any async operation.
@@ -903,14 +972,18 @@ application in development mode instead (`NODE_ENV=development`).
Good stack traces are only activated in development and debug mode as this
results in a significant performance penalty.
-___Comparison___:
-Useless stack trace:
+**_Comparison_**:
+
+Standard stack trace:
+
```
ReplyError: ERR wrong number of arguments for 'set' command
at parseError (/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:158:12)
at parseType (/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:219:14)
```
-Good stack trace:
+
+Debug stack trace:
+
```
ReplyError: ERR wrong number of arguments for 'set' command
at new Command (/home/ruben/repos/redis/lib/command.js:9:902)
@@ -927,39 +1000,10 @@ ReplyError: ERR wrong number of arguments for 'set' command
at processImmediate [as _immediateCallback] (timers.js:383:17)
```
-## How to Contribute
-- Open a pull request or an issue about what you want to implement / change. We're glad for any help!
- - Please be aware that we'll only accept fully tested code.
+## Contributing
-## Contributors
-
-The original author of node_redis is [Matthew Ranney](https://github.com/mranney)
-
-The current lead maintainer is [Ruben Bridgewater](https://github.com/BridgeAR)
-
-Many [others](https://github.com/NodeRedis/node_redis/graphs/contributors)
-contributed to `node_redis` too. Thanks to all of them!
+Please see the [contributing guide](CONTRIBUTING.md).
## License
-[MIT](LICENSE)
-
-### Consolidation: It's time for celebration
-
-Right now there are two great redis clients around and both have some advantages
-above each other. We speak about ioredis and node_redis. So after talking to
-each other about how we could improve in working together we (that is @luin and
-@BridgeAR) decided to work towards a single library on the long run. But step by
-step.
-
-First of all, we want to split small parts of our libraries into others so that
-we're both able to use the same code. Those libraries are going to be maintained
-under the NodeRedis organization. This is going to reduce the maintenance
-overhead, allows others to use the very same code, if they need it and it's way
-easyer for others to contribute to both libraries.
-
-We're very happy about this step towards working together as we both want to
-give you the best redis experience possible.
-
-If you want to join our cause by help maintaining something, please don't
-hesitate to contact either one of us.
+This repository is licensed under the "MIT" license. See [LICENSE](LICENSE).
diff --git a/node_modules/redis/changelog.md b/node_modules/redis/changelog.md
old mode 100755
new mode 100644
index d650f9b..186da33
--- a/node_modules/redis/changelog.md
+++ b/node_modules/redis/changelog.md
@@ -1,6 +1,36 @@
# Changelog
-## v.2.8.0 - 31 Jul, 2017
+## v3.0.0 - 09 Feb, 2020
+
+This version is mainly a release to distribute all the unreleased changes on master since 2017 and additionally removes
+a lot of old deprecated features and old internals in preparation for an upcoming modernization refactor (v4).
+
+### Breaking Changes
+
+- Dropped support for Node.js < 6
+- Dropped support for `hiredis` (no longer required)
+- Removed previously deprecated `drain` event
+- Removed previously deprecated `idle` event
+- Removed previously deprecated `parser` option
+- Removed previously deprecated `max_delay` option
+- Removed previously deprecated `max_attempts` option
+- Removed previously deprecated `socket_no_delay` option
+
+### Bug Fixes
+
+- Removed development files from published package (#1370)
+- Duplicate function now allows db param to be passed (#1311)
+
+### Features
+
+- Upgraded to latest `redis-commands` package
+- Upgraded to latest `redis-parser` package, v3.0.0, which brings performance improvements
+- Replaced `double-ended-queue` with `denque`, which brings performance improvements
+- Add timestamps to debug traces
+- Add `socket_initial_delay` option for `socket.setKeepAlive` (#1396)
+- Add support for `rediss` protocol in url (#1282)
+
+## v2.8.0 - 31 Jul, 2017
Features
@@ -13,13 +43,13 @@ Bugfixes
- Fixed emitting internal errors while reconnecting with auth
- Fixed crashing with invalid url option
-## v.2.7.1 - 14 Mar, 2017
+## v2.7.1 - 14 Mar, 2017
Bugfixes
- Fixed monitor mode not working in combination with IPv6 (2.6.0 regression)
-## v.2.7.0 - 11 Mar, 2017
+## v2.7.0 - 11 Mar, 2017
Features
@@ -30,160 +60,160 @@ Bugfixes
- Fixed rename_commands not accepting `null` as value
- Fixed `AbortError`s and `AggregateError`s not showing the error message in the stack trace
-## v.2.6.5 - 15 Jan, 2017
+## v2.6.5 - 15 Jan, 2017
Bugfixes
- Fixed parser not being reset in case the redis connection closed ASAP for overcoming of output buffer limits
- Fixed parser reset if (p)message_buffer listener is attached
-## v.2.6.4 - 12 Jan, 2017
+## v2.6.4 - 12 Jan, 2017
Bugfixes
- Fixed monitor mode not working in combination with IPv6, sockets or lua scripts (2.6.0 regression)
-## v.2.6.3 - 31 Oct, 2016
+## v2.6.3 - 31 Oct, 2016
Bugfixes
- Do not change the tls setting to camel_case
- Fix domain handling in combination with the offline queue (2.5.3 regression)
-## v.2.6.2 - 16 Jun, 2016
+## v2.6.2 - 16 Jun, 2016
Bugfixes
- Fixed individual callbacks of a transaction not being called (2.6.0 regression)
-## v.2.6.1 - 02 Jun, 2016
+## v2.6.1 - 02 Jun, 2016
Bugfixes
- Fixed invalid function name being exported
-## v.2.6.0 - 01 Jun, 2016
+## v2.6.0 - 01 Jun, 2016
In addition to the pre-releases the following changes exist in v.2.6.0:
Features
-- Updated [redis-parser](https://github.com/NodeRedis/node-redis-parser) dependency ([changelog](https://github.com/NodeRedis/node-redis-parser/releases/tag/v.2.0.0))
- - The JS parser is from now on the new default as it is a lot faster than the hiredis parser
- - This is no BC as there is no changed behavior for the user at all but just a performance improvement. Explicitly requireing the Hiredis parser is still possible.
-- Added name property to all Redis functions (Node.js >= 4.0)
-- Improved stack traces in development and debug mode
+- Updated [redis-parser](https://github.com/NodeRedis/node-redis-parser) dependency ([changelog](https://github.com/NodeRedis/node-redis-parser/releases/tag/v.2.0.0))
+- The JS parser is from now on the new default as it is a lot faster than the hiredis parser
+- This is no BC as there is no changed behavior for the user at all but just a performance improvement. Explicitly requireing the Hiredis parser is still possible.
+- Added name property to all Redis functions (Node.js >= 4.0)
+- Improved stack traces in development and debug mode
Bugfixes
-- Reverted support for `__proto__` (v.2.6.0-2) to prevent and breaking change
+- Reverted support for `__proto__` (v.2.6.0-2) to prevent and breaking change
Deprecations
-- The `parser` option is deprecated and should be removed. The built-in Javascript parser is a lot faster than the hiredis parser and has more features
+- The `parser` option is deprecated and should be removed. The built-in Javascript parser is a lot faster than the hiredis parser and has more features
-## v.2.6.0-2 - 29 Apr, 2016
+## v2.6.0-2 - 29 Apr, 2016
Features
-- Added support for the new [CLIENT REPLY ON|OFF|SKIP](http://redis.io/commands/client-reply) command (Redis v.3.2)
-- Added support for camelCase
- - The Node.js landscape default is to use camelCase. node_redis is a bit out of the box here
- but from now on it is possible to use both, just as you prefer!
- - If there's any documented variable missing as camelCased, please open a issue for it
-- Improve error handling significantly
- - Only emit an error if the error has not already been handled in a callback
- - Improved unspecific error messages e.g. "Connection gone from end / close event"
- - Added `args` to command errors to improve identification of the error
- - Added origin to errors if there's e.g. a connection error
- - Added ReplyError class. All Redis errors are from now on going to be of that class
- - Added AbortError class. A subclass of AbortError. All unresolved and by node_redis rejected commands are from now on of that class
- - Added AggregateError class. If a unresolved and by node_redis rejected command has no callback and
- this applies to more than a single command, the errors for the commands without callback are aggregated
- to a single error that is emitted in debug_mode in that case.
-- Added `message_buffer` / `pmessage_buffer` events. That event is always going to emit a buffer
- - Listening to the `message` event at the same time is always going to return the same message as string
-- Added callback option to the duplicate function
-- Added support for `__proto__` and other reserved keywords as hgetall field
-- Updated [redis-commands](https://github.com/NodeRedis/redis-commands) dependency ([changelog](https://github.com/NodeRedis/redis-commands/releases/tag/v.1.2.0))
+- Added support for the new [CLIENT REPLY ON|OFF|SKIP](http://redis.io/commands/client-reply) command (Redis v.3.2)
+- Added support for camelCase
+- The Node.js landscape default is to use camelCase. node_redis is a bit out of the box here
+ but from now on it is possible to use both, just as you prefer!
+- If there's any documented variable missing as camelCased, please open a issue for it
+- Improve error handling significantly
+- Only emit an error if the error has not already been handled in a callback
+- Improved unspecific error messages e.g. "Connection gone from end / close event"
+- Added `args` to command errors to improve identification of the error
+- Added origin to errors if there's e.g. a connection error
+- Added ReplyError class. All Redis errors are from now on going to be of that class
+- Added AbortError class. A subclass of AbortError. All unresolved and by node_redis rejected commands are from now on of that class
+- Added AggregateError class. If a unresolved and by node_redis rejected command has no callback and
+ this applies to more than a single command, the errors for the commands without callback are aggregated
+ to a single error that is emitted in debug_mode in that case.
+- Added `message_buffer` / `pmessage_buffer` events. That event is always going to emit a buffer
+- Listening to the `message` event at the same time is always going to return the same message as string
+- Added callback option to the duplicate function
+- Added support for `__proto__` and other reserved keywords as hgetall field
+- Updated [redis-commands](https://github.com/NodeRedis/redis-commands) dependency ([changelog](https://github.com/NodeRedis/redis-commands/releases/tag/v.1.2.0))
Bugfixes
-- Fixed v.2.5.0 auth command regression (under special circumstances a reconnect would not authenticate properly)
-- Fixed v.2.6.0-0 pub sub mode and quit command regressions:
- - Entering pub sub mode not working if a earlier called and still running command returned an error
- - Unsubscribe callback not called if unsubscribing from all channels and resubscribing right away
- - Quit command resulting in an error in some cases
-- Fixed special handled functions in batch and multi context not working the same as without (e.g. select and info)
- - Be aware that not all commands work in combination with transactions but they all work with batch
-- Fixed address always set to 127.0.0.1:6379 in case host / port is set in the `tls` options instead of the general options
+- Fixed v.2.5.0 auth command regression (under special circumstances a reconnect would not authenticate properly)
+- Fixed v.2.6.0-0 pub sub mode and quit command regressions:
+- Entering pub sub mode not working if a earlier called and still running command returned an error
+- Unsubscribe callback not called if unsubscribing from all channels and resubscribing right away
+- Quit command resulting in an error in some cases
+- Fixed special handled functions in batch and multi context not working the same as without (e.g. select and info)
+- Be aware that not all commands work in combination with transactions but they all work with batch
+- Fixed address always set to 127.0.0.1:6379 in case host / port is set in the `tls` options instead of the general options
-## v.2.6.0-1 - 01 Apr, 2016
+## v2.6.0-1 - 01 Apr, 2016
A second pre-release with further fixes. This is likely going to be released as 2.6.0 stable without further changes.
Features
-- Added type validations for client.send_command arguments
+- Added type validations for client.send_command arguments
Bugfixes
-- Fixed client.send_command not working properly with every command and every option
-- Fixed pub sub mode unsubscribing from all channels in combination with the new `string_numbers` option crashing
-- Fixed pub sub mode unsubscribing from all channels not respected while reconnecting
-- Fixed pub sub mode events in combination with the `string_numbers` option emitting the number of channels not as number
+- Fixed client.send_command not working properly with every command and every option
+- Fixed pub sub mode unsubscribing from all channels in combination with the new `string_numbers` option crashing
+- Fixed pub sub mode unsubscribing from all channels not respected while reconnecting
+- Fixed pub sub mode events in combination with the `string_numbers` option emitting the number of channels not as number
-## v.2.6.0-0 - 27 Mar, 2016
+## v2.6.0-0 - 27 Mar, 2016
This is mainly a very important bug fix release with some smaller features.
Features
-- Monitor and pub sub mode now work together with the offline queue
- - All commands that were send after a connection loss are now going to be send after reconnecting
-- Activating monitor mode does now work together with arbitrary commands including pub sub mode
-- Pub sub mode is completely rewritten and all known issues fixed
-- Added `string_numbers` option to get back strings instead of numbers
-- Quit command is from now on always going to end the connection properly
+- Monitor and pub sub mode now work together with the offline queue
+- All commands that were send after a connection loss are now going to be send after reconnecting
+- Activating monitor mode does now work together with arbitrary commands including pub sub mode
+- Pub sub mode is completely rewritten and all known issues fixed
+- Added `string_numbers` option to get back strings instead of numbers
+- Quit command is from now on always going to end the connection properly
Bugfixes
-- Fixed calling monitor command while other commands are still running
-- Fixed monitor and pub sub mode not working together
-- Fixed monitor mode not working in combination with the offline queue
-- Fixed pub sub mode not working in combination with the offline queue
-- Fixed pub sub mode resubscribing not working with non utf8 buffer channels
-- Fixed pub sub mode crashing if calling unsubscribe / subscribe in various combinations
-- Fixed pub sub mode emitting unsubscribe even if no channels were unsubscribed
-- Fixed pub sub mode emitting a message without a message published
-- Fixed quit command not ending the connection and resulting in further reconnection if called while reconnecting
+- Fixed calling monitor command while other commands are still running
+- Fixed monitor and pub sub mode not working together
+- Fixed monitor mode not working in combination with the offline queue
+- Fixed pub sub mode not working in combination with the offline queue
+- Fixed pub sub mode resubscribing not working with non utf8 buffer channels
+- Fixed pub sub mode crashing if calling unsubscribe / subscribe in various combinations
+- Fixed pub sub mode emitting unsubscribe even if no channels were unsubscribed
+- Fixed pub sub mode emitting a message without a message published
+- Fixed quit command not ending the connection and resulting in further reconnection if called while reconnecting
The quit command did not end connections earlier if the connection was down at that time and this could have
lead to strange situations, therefor this was fixed to end the connection right away in those cases.
-## v.2.5.3 - 21 Mar, 2016
+## v2.5.3 - 21 Mar, 2016
Bugfixes
-- Revert throwing on invalid data types and print a warning instead
+- Revert throwing on invalid data types and print a warning instead
-## v.2.5.2 - 16 Mar, 2016
+## v2.5.2 - 16 Mar, 2016
Bugfixes
-- Fixed breaking changes against Redis 2.4 introduced in 2.5.0 / 2.5.1
+- Fixed breaking changes against Redis 2.4 introduced in 2.5.0 / 2.5.1
-## v.2.5.1 - 15 Mar, 2016
+## v2.5.1 - 15 Mar, 2016
Bugfixes
-- Fixed info command not working anymore with optional section argument
+- Fixed info command not working anymore with optional section argument
-## v.2.5.0 - 15 Mar, 2016
+## v2.5.0 - 15 Mar, 2016
Same changelog as the pre-release
-## v.2.5.0-1 - 07 Mar, 2016
+## v2.5.0-1 - 07 Mar, 2016
This is a big release with some substantial underlining changes. Therefor this is released as a pre-release and I encourage anyone who's able to, to test this out.
@@ -193,173 +223,173 @@ This release is also going to deprecate a couple things to prepare for a future
Features
-- The parsers moved into the [redis-parser](https://github.com/NodeRedis/node-redis-parser) module and will be maintained in there from now on
- - Improve js parser speed significantly for big SUNION/SINTER/LRANGE/ZRANGE
-- Improve redis-url parsing to also accept the database-number and options as query parameters as suggested in [IANA](http://www.iana.org/assignments/uri-schemes/prov/redis)
-- Added a `retry_unfulfilled_commands` option
- - Setting this to 'true' results in retrying all commands that were not fulfilled on a connection loss after the reconnect. Use with caution
-- Added a `db` option to select the database while connecting (this is [not recommended](https://groups.google.com/forum/#!topic/redis-db/vS5wX8X4Cjg))
-- Added a `password` option as alias for auth_pass
-- The client.server_info is from now on updated while using the info command
-- Gracefuly handle redis protocol errors from now on
-- Added a `warning` emitter that receives node_redis warnings like auth not required and deprecation messages
-- Added a `retry_strategy` option that replaces all reconnect options
-- The reconnecting event from now on also receives:
- - The error message why the reconnect happened (params.error)
- - The amount of times the client was connected (params.times_connected)
- - The total reconnecting time since the last time connected (params.total_retry_time)
-- Always respect the command execution order no matter if the reply could be returned sync or not (former exceptions: [#937](https://github.com/NodeRedis/node_redis/issues/937#issuecomment-167525939))
-- redis.createClient is now checking input values stricter and detects more faulty input
-- Started refactoring internals into individual modules
-- Pipelining speed improvements
+- The parsers moved into the [redis-parser](https://github.com/NodeRedis/node-redis-parser) module and will be maintained in there from now on
+- Improve js parser speed significantly for big SUNION/SINTER/LRANGE/ZRANGE
+- Improve redis-url parsing to also accept the database-number and options as query parameters as suggested in [IANA](http://www.iana.org/assignments/uri-schemes/prov/redis)
+- Added a `retry_unfulfilled_commands` option
+- Setting this to 'true' results in retrying all commands that were not fulfilled on a connection loss after the reconnect. Use with caution
+- Added a `db` option to select the database while connecting (this is [not recommended](https://groups.google.com/forum/#!topic/redis-db/vS5wX8X4Cjg))
+- Added a `password` option as alias for auth_pass
+- The client.server_info is from now on updated while using the info command
+- Gracefuly handle redis protocol errors from now on
+- Added a `warning` emitter that receives node_redis warnings like auth not required and deprecation messages
+- Added a `retry_strategy` option that replaces all reconnect options
+- The reconnecting event from now on also receives:
+- The error message why the reconnect happened (params.error)
+- The amount of times the client was connected (params.times_connected)
+- The total reconnecting time since the last time connected (params.total_retry_time)
+- Always respect the command execution order no matter if the reply could be returned sync or not (former exceptions: [#937](https://github.com/NodeRedis/node_redis/issues/937#issuecomment-167525939))
+- redis.createClient is now checking input values stricter and detects more faulty input
+- Started refactoring internals into individual modules
+- Pipelining speed improvements
Bugfixes
-- Fixed explicit undefined as a command callback in a multi context
-- Fixed hmset failing to detect the first key as buffer or date if the key is of that type
-- Fixed do not run toString on an array argument and throw a "invalid data" error instead
- - This is not considered as breaking change, as this is likely a error in your code and if you want to have such a behavior you should handle this beforehand
- - The same applies to Map / Set and individual Object types
-- Fixed redis url not accepting the protocol being omitted or protocols other than the redis protocol for convenience
-- Fixed parsing the db keyspace even if the first database does not begin with a zero
-- Fixed handling of errors occurring while receiving pub sub messages
-- Fixed huge string pipelines crashing NodeJS (Pipeline size above 256mb)
-- Fixed rename_commands and prefix option not working together
-- Fixed ready being emitted to early in case a slave is still syncing / master down
+- Fixed explicit undefined as a command callback in a multi context
+- Fixed hmset failing to detect the first key as buffer or date if the key is of that type
+- Fixed do not run toString on an array argument and throw a "invalid data" error instead
+- This is not considered as breaking change, as this is likely a error in your code and if you want to have such a behavior you should handle this beforehand
+- The same applies to Map / Set and individual Object types
+- Fixed redis url not accepting the protocol being omitted or protocols other than the redis protocol for convenience
+- Fixed parsing the db keyspace even if the first database does not begin with a zero
+- Fixed handling of errors occurring while receiving pub sub messages
+- Fixed huge string pipelines crashing NodeJS (Pipeline size above 256mb)
+- Fixed rename_commands and prefix option not working together
+- Fixed ready being emitted to early in case a slave is still syncing / master down
Deprecations
-- Using any command with a argument being set to null or undefined is deprecated
- - From v.3.0.0 on using a command with such an argument will return an error instead
- - If you want to keep the old behavior please use a precheck in your code that converts the arguments to a string.
- - Using SET or SETEX with a undefined or null value will from now on also result in converting the value to "null" / "undefined" to have a consistent behavior. This is not considered as breaking change, as it returned an error earlier.
-- Using .end(flush) without the flush parameter is deprecated and the flush parameter should explicitly be used
- - From v.3.0.0 on using .end without flush will result in an error
- - Using .end without flush means that any command that did not yet return is going to silently fail. Therefor this is considered harmful and you should explicitly silence such errors if you are sure you want this
-- Depending on the return value of a command to detect the backpressure is deprecated
- - From version 3.0.0 on node_redis might not return true / false as a return value anymore. Please rely on client.should_buffer instead
-- The `socket_nodelay` option is deprecated and will be removed in v.3.0.0
- - If you want to buffer commands you should use [.batch or .multi](./README.md) instead. This is necessary to reduce the amount of different options and this is very likely reducing your throughput if set to false.
- - If you are sure you want to activate the NAGLE algorithm you can still activate it by using client.stream.setNoDelay(false)
-- The `max_attempts` option is deprecated and will be removed in v.3.0.0. Please use the `retry_strategy` instead
-- The `retry_max_delay` option is deprecated and will be removed in v.3.0.0. Please use the `retry_strategy` instead
-- The drain event is deprecated and will be removed in v.3.0.0. Please listen to the stream drain event instead
-- The idle event is deprecated and will likely be removed in v.3.0.0. If you rely on this feature please open a new ticket in node_redis with your use case
-- Redis < v. 2.6 is not officially supported anymore and might not work in all cases. Please update to a newer redis version as it is not possible to test for these old versions
-- Removed non documented command syntax (adding the callback to an arguments array instead of passing it as individual argument)
-
-## v.2.4.2 - 27 Nov, 2015
+- Using any command with a argument being set to null or undefined is deprecated
+- From v.3.0.0 on using a command with such an argument will return an error instead
+- If you want to keep the old behavior please use a precheck in your code that converts the arguments to a string.
+- Using SET or SETEX with a undefined or null value will from now on also result in converting the value to "null" / "undefined" to have a consistent behavior. This is not considered as breaking change, as it returned an error earlier.
+- Using .end(flush) without the flush parameter is deprecated and the flush parameter should explicitly be used
+- From v.3.0.0 on using .end without flush will result in an error
+- Using .end without flush means that any command that did not yet return is going to silently fail. Therefor this is considered harmful and you should explicitly silence such errors if you are sure you want this
+- Depending on the return value of a command to detect the backpressure is deprecated
+- From version 3.0.0 on node_redis might not return true / false as a return value anymore. Please rely on client.should_buffer instead
+- The `socket_nodelay` option is deprecated and will be removed in v.3.0.0
+- If you want to buffer commands you should use [.batch or .multi](./README.md) instead. This is necessary to reduce the amount of different options and this is very likely reducing your throughput if set to false.
+- If you are sure you want to activate the NAGLE algorithm you can still activate it by using client.stream.setNoDelay(false)
+- The `max_attempts` option is deprecated and will be removed in v.3.0.0. Please use the `retry_strategy` instead
+- The `retry_max_delay` option is deprecated and will be removed in v.3.0.0. Please use the `retry_strategy` instead
+- The drain event is deprecated and will be removed in v.3.0.0. Please listen to the stream drain event instead
+- The idle event is deprecated and will likely be removed in v.3.0.0. If you rely on this feature please open a new ticket in node_redis with your use case
+- Redis < v. 2.6 is not officially supported anymore and might not work in all cases. Please update to a newer redis version as it is not possible to test for these old versions
+- Removed non documented command syntax (adding the callback to an arguments array instead of passing it as individual argument)
+
+## v2.4.2 - 27 Nov, 2015
Bugfixes
-- Fixed not emitting ready after reconnect with disable_resubscribing ([@maxgalbu](https://github.com/maxgalbu))
+- Fixed not emitting ready after reconnect with disable_resubscribing ([@maxgalbu](https://github.com/maxgalbu))
-## v.2.4.1 - 25 Nov, 2015
+## v2.4.1 - 25 Nov, 2015
Bugfixes
-- Fixed a js parser regression introduced in 2.4.0 ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed a js parser regression introduced in 2.4.0 ([@BridgeAR](https://github.com/BridgeAR))
-## v.2.4.0 - 25 Nov, 2015
+## v2.4.0 - 25 Nov, 2015
Features
-- Added `tls` option to initiate a connection to a redis server behind a TLS proxy. Thanks ([@paddybyers](https://github.com/paddybyers))
-- Added `prefix` option to auto key prefix any command with the provided prefix ([@luin](https://github.com/luin) & [@BridgeAR](https://github.com/BridgeAR))
-- Added `url` option to pass the connection url with the options object ([@BridgeAR](https://github.com/BridgeAR))
-- Added `client.duplicate([options])` to duplicate the current client and return a new one with the same options ([@BridgeAR](https://github.com/BridgeAR))
-- Improve performance by up to 20% on almost all use cases ([@BridgeAR](https://github.com/BridgeAR))
+- Added `tls` option to initiate a connection to a redis server behind a TLS proxy. Thanks ([@paddybyers](https://github.com/paddybyers))
+- Added `prefix` option to auto key prefix any command with the provided prefix ([@luin](https://github.com/luin) & [@BridgeAR](https://github.com/BridgeAR))
+- Added `url` option to pass the connection url with the options object ([@BridgeAR](https://github.com/BridgeAR))
+- Added `client.duplicate([options])` to duplicate the current client and return a new one with the same options ([@BridgeAR](https://github.com/BridgeAR))
+- Improve performance by up to 20% on almost all use cases ([@BridgeAR](https://github.com/BridgeAR))
Bugfixes
-- Fixed js parser handling big values slow ([@BridgeAR](https://github.com/BridgeAR))
- - The speed is now on par with the hiredis parser.
+- Fixed js parser handling big values slow ([@BridgeAR](https://github.com/BridgeAR))
+- The speed is now on par with the hiredis parser.
-## v.2.3.1 - 18 Nov, 2015
+## v2.3.1 - 18 Nov, 2015
Bugfixes
-- Fixed saving buffers with charsets other than utf-8 while using multi ([@BridgeAR](https://github.com/BridgeAR))
-- Fixed js parser handling big values very slow ([@BridgeAR](https://github.com/BridgeAR))
- - The speed is up to ~500% faster than before but still up to ~50% slower than the hiredis parser.
+- Fixed saving buffers with charsets other than utf-8 while using multi ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed js parser handling big values very slow ([@BridgeAR](https://github.com/BridgeAR))
+- The speed is up to ~500% faster than before but still up to ~50% slower than the hiredis parser.
-## v.2.3.0 - 30 Oct, 2015
+## v2.3.0 - 30 Oct, 2015
Features
-- Improve speed further for: ([@BridgeAR](https://github.com/BridgeAR))
- - saving big strings (up to +300%)
- - using .multi / .batch (up to +50% / on Node.js 0.10.x +300%)
- - saving small buffers
-- Increased coverage to 99% ([@BridgeAR](https://github.com/BridgeAR))
-- Refactored manual backpressure control ([@BridgeAR](https://github.com/BridgeAR))
- - Removed the high water mark and low water mark. Such a mechanism should be implemented by a user instead
- - The `drain` event is from now on only emitted if the stream really had to buffer
-- Reduced the default connect_timeout to be one hour instead of 24h ([@BridgeAR](https://github.com/BridgeAR))
-- Added .path to redis.createClient(options); ([@BridgeAR](https://github.com/BridgeAR))
-- Ignore info command, if not available on server ([@ivanB1975](https://github.com/ivanB1975))
+- Improve speed further for: ([@BridgeAR](https://github.com/BridgeAR))
+- saving big strings (up to +300%)
+- using .multi / .batch (up to +50% / on Node.js 0.10.x +300%)
+- saving small buffers
+- Increased coverage to 99% ([@BridgeAR](https://github.com/BridgeAR))
+- Refactored manual backpressure control ([@BridgeAR](https://github.com/BridgeAR))
+- Removed the high water mark and low water mark. Such a mechanism should be implemented by a user instead
+- The `drain` event is from now on only emitted if the stream really had to buffer
+- Reduced the default connect_timeout to be one hour instead of 24h ([@BridgeAR](https://github.com/BridgeAR))
+- Added .path to redis.createClient(options); ([@BridgeAR](https://github.com/BridgeAR))
+- Ignore info command, if not available on server ([@ivanB1975](https://github.com/ivanB1975))
Bugfixes
-- Fixed a js parser error that could result in a timeout ([@BridgeAR](https://github.com/BridgeAR))
-- Fixed .multi / .batch used with Node.js 0.10.x not working properly after a reconnect ([@BridgeAR](https://github.com/BridgeAR))
-- Fixed fired but not yet returned commands not being rejected after a connection loss ([@BridgeAR](https://github.com/BridgeAR))
-- Fixed connect_timeout not respected if no connection has ever been established ([@gagle](https://github.com/gagle) & [@benjie](https://github.com/benjie))
-- Fixed return_buffers in pub sub mode ([@komachi](https://github.com/komachi))
+- Fixed a js parser error that could result in a timeout ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed .multi / .batch used with Node.js 0.10.x not working properly after a reconnect ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed fired but not yet returned commands not being rejected after a connection loss ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed connect_timeout not respected if no connection has ever been established ([@gagle](https://github.com/gagle) & [@benjie](https://github.com/benjie))
+- Fixed return_buffers in pub sub mode ([@komachi](https://github.com/komachi))
-## v.2.2.5 - 18 Oct, 2015
+## v2.2.5 - 18 Oct, 2015
Bugfixes
-- Fixed undefined options passed to a new instance not accepted (possible with individual .createClient functions) ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed undefined options passed to a new instance not accepted (possible with individual .createClient functions) ([@BridgeAR](https://github.com/BridgeAR))
-## v.2.2.4 - 17 Oct, 2015
+## v2.2.4 - 17 Oct, 2015
Bugfixes
-- Fixed unspecific error message for unresolvable commands ([@BridgeAR](https://github.com/BridgeAR))
-- Fixed not allowed command error in pubsub mode not being returned in a provided callback ([@BridgeAR](https://github.com/BridgeAR))
-- Fixed to many commands forbidden in pub sub mode ([@BridgeAR](https://github.com/BridgeAR))
-- Fixed mutation of the arguments array passed to .multi / .batch constructor ([@BridgeAR](https://github.com/BridgeAR))
-- Fixed mutation of the options object passed to createClient ([@BridgeAR](https://github.com/BridgeAR))
-- Fixed error callback in .multi not called if connection in broken mode ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed unspecific error message for unresolvable commands ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed not allowed command error in pubsub mode not being returned in a provided callback ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed to many commands forbidden in pub sub mode ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed mutation of the arguments array passed to .multi / .batch constructor ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed mutation of the options object passed to createClient ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed error callback in .multi not called if connection in broken mode ([@BridgeAR](https://github.com/BridgeAR))
-## v.2.2.3 - 14 Oct, 2015
+## v2.2.3 - 14 Oct, 2015
Bugfixes
-- Fixed multi not being executed on Node 0.10.x if node_redis not yet ready ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed multi not being executed on Node 0.10.x if node_redis not yet ready ([@BridgeAR](https://github.com/BridgeAR))
-## v.2.2.2 - 14 Oct, 2015
+## v2.2.2 - 14 Oct, 2015
Bugfixes
-- Fixed regular commands not being executed after a .multi until .exec was called ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed regular commands not being executed after a .multi until .exec was called ([@BridgeAR](https://github.com/BridgeAR))
-## v.2.2.1 - 12 Oct, 2015
+## v2.2.1 - 12 Oct, 2015
No code change
-## v.2.2.0 - 12 Oct, 2015 - The peregrino falcon
+## v2.2.0 - 12 Oct, 2015 - The peregrino falcon
The peregrino falcon is the fasted bird on earth and this is what this release is all about: Increased performance for heavy usage by up to **400%** [sic!] and increased overall performance for any command as well. Please check the benchmarks in the [README.md](README.md) for further details.
Features
-- Added rename_commands options to handle renamed commands from the redis config ([@digmxl](https://github.com/digmxl) & [@BridgeAR](https://github.com/BridgeAR))
-- Added disable_resubscribing option to prevent a client from resubscribing after reconnecting ([@BridgeAR](https://github.com/BridgeAR))
-- Increased performance ([@BridgeAR](https://github.com/BridgeAR))
- - exchanging built in queue with [@petkaantonov](https://github.com/petkaantonov)'s [double-ended queue](https://github.com/petkaantonov/deque)
- - prevent polymorphism
- - optimize statements
-- Added *.batch* command, similar to .multi but without transaction ([@BridgeAR](https://github.com/BridgeAR))
-- Improved pipelining to minimize the [RTT](http://redis.io/topics/pipelining) further ([@BridgeAR](https://github.com/BridgeAR))
+- Added rename_commands options to handle renamed commands from the redis config ([@digmxl](https://github.com/digmxl) & [@BridgeAR](https://github.com/BridgeAR))
+- Added disable_resubscribing option to prevent a client from resubscribing after reconnecting ([@BridgeAR](https://github.com/BridgeAR))
+- Increased performance ([@BridgeAR](https://github.com/BridgeAR))
+- exchanging built in queue with [@petkaantonov](https://github.com/petkaantonov)'s [double-ended queue](https://github.com/petkaantonov/deque)
+- prevent polymorphism
+- optimize statements
+- Added _.batch_ command, similar to .multi but without transaction ([@BridgeAR](https://github.com/BridgeAR))
+- Improved pipelining to minimize the [RTT](http://redis.io/topics/pipelining) further ([@BridgeAR](https://github.com/BridgeAR))
Bugfixes
-- Fixed a javascript parser regression introduced in 2.0 that could result in timeouts on high load. ([@BridgeAR](https://github.com/BridgeAR))
- - I was not able to write a regression test for this, since the error seems to only occur under heavy load with special conditions. So please have a look for timeouts with the js parser, if you use it and report all issues and switch to the hiredis parser in the meanwhile. If you're able to come up with a reproducable test case, this would be even better :)
-- Fixed should_buffer boolean for .exec, .select and .auth commands not being returned and fix a couple special conditions ([@BridgeAR](https://github.com/BridgeAR))
+- Fixed a javascript parser regression introduced in 2.0 that could result in timeouts on high load. ([@BridgeAR](https://github.com/BridgeAR))
+- I was not able to write a regression test for this, since the error seems to only occur under heavy load with special conditions. So please have a look for timeouts with the js parser, if you use it and report all issues and switch to the hiredis parser in the meanwhile. If you're able to come up with a reproducable test case, this would be even better :)
+- Fixed should_buffer boolean for .exec, .select and .auth commands not being returned and fix a couple special conditions ([@BridgeAR](https://github.com/BridgeAR))
If you do not rely on transactions but want to reduce the RTT you can use .batch from now on. It'll behave just the same as .multi but it does not have any transaction and therefor won't roll back any failed commands.
Both .multi and .batch are from now on going to cache the commands and release them while calling .exec.
@@ -396,29 +426,29 @@ To conclude: we can proudly say that node_redis is very likely outperforming any
Known issues
-- The pub sub system has some flaws and those will be addressed in the next minor release
+- The pub sub system has some flaws and those will be addressed in the next minor release
## v2.1.0 - Oct 02, 2015
Features:
-- Addded optional flush parameter to `.end`. If set to true, commands fired after using .end are going to be rejected instead of being ignored. (@crispy1989)
-- Addded: host and port can now be provided in a single options object. E.g. redis.createClient({ host: 'localhost', port: 1337, max_attempts: 5 }); (@BridgeAR)
-- Speedup common cases (@BridgeAR)
+- Addded optional flush parameter to `.end`. If set to true, commands fired after using .end are going to be rejected instead of being ignored. (@crispy1989)
+- Addded: host and port can now be provided in a single options object. E.g. redis.createClient({ host: 'localhost', port: 1337, max_attempts: 5 }); (@BridgeAR)
+- Speedup common cases (@BridgeAR)
Bugfixes:
-- Fix argument mutation while using the array notation with the multi constructor (@BridgeAR)
-- Fix multi.hmset key not being type converted if used with an object and key not being a string (@BridgeAR)
-- Fix parser errors not being catched properly (@BridgeAR)
-- Fix a crash that could occur if a redis server does not return the info command as usual #541 (@BridgeAR)
-- Explicitly passing undefined as a callback statement will work again. E.g. client.publish('channel', 'message', undefined); (@BridgeAR)
+- Fix argument mutation while using the array notation with the multi constructor (@BridgeAR)
+- Fix multi.hmset key not being type converted if used with an object and key not being a string (@BridgeAR)
+- Fix parser errors not being catched properly (@BridgeAR)
+- Fix a crash that could occur if a redis server does not return the info command as usual #541 (@BridgeAR)
+- Explicitly passing undefined as a callback statement will work again. E.g. client.publish('channel', 'message', undefined); (@BridgeAR)
## v2.0.1 - Sep 24, 2015
Bugfixes:
-- Fix argument mutation while using the array notation in combination with keys / callbacks ([#866](.)). (@BridgeAR)
+- Fix argument mutation while using the array notation in combination with keys / callbacks ([#866](.)). (@BridgeAR)
## v2.0.0 - Sep 21, 2015
@@ -444,7 +474,7 @@ This is the biggest release that node_redis had since it was released in 2010. A
- Added: Network errors and other stream errors will from now on include the error code as `err.code` property (@BridgeAR)
- Added: Errors thrown by redis will now include the redis error code as `err.code` property. (@skeggse & @BridgeAR)
- Added: Errors thrown by node_redis will now include a `err.command` property for the command used (@BridgeAR)
-- Added new commands and drop support for deprecated *substr* (@BridgeAR)
+- Added new commands and drop support for deprecated _substr_ (@BridgeAR)
- Added new possibilities how to provide the command arguments (@BridgeAR)
- The entries in the keyspace of the server_info is now an object instead of a string. (@SinisterLight & @BridgeAR)
- Small speedup here and there (e.g. by not using .toLowerCase() anymore) (@BridgeAR)
@@ -453,7 +483,7 @@ This is the biggest release that node_redis had since it was released in 2010. A
- Remove dead code, clean up and refactor very old chunks (@BridgeAR)
- Don't flush the offline queue if reconnecting (@BridgeAR)
- Emit all errors insteaf of throwing sometimes and sometimes emitting them (@BridgeAR)
-- *auth_pass* passwords are now checked to be a valid password (@jcppman & @BridgeAR)
+- _auth_pass_ passwords are now checked to be a valid password (@jcppman & @BridgeAR)
## Bug fixes:
@@ -483,11 +513,13 @@ This is the biggest release that node_redis had since it was released in 2010. A
2. Error messages have changed quite a bit. If you depend on a specific wording please check your application carfully.
3. Errors are from now on always either returned if a callback is present or emitted. They won't be thrown (neither sync, nor async).
4. The Multi error handling has changed a lot!
- - All errors are from now on errors instead of strings (this only applied to the js parser).
- - If an error occurs while queueing the commands an EXECABORT error will be returned including the failed commands as `.errors` property instead of an array with errors.
- - If an error occurs while executing the commands and that command has a callback it'll return the error as first parameter (`err, undefined` instead of `null, undefined`).
- - All the errors occuring while executing the commands will stay in the result value as error instance (if you used the js parser before they would have been strings). Be aware that the transaction won't be aborted if those error occurr!
- - If `multi.exec` does not have a callback and an EXECABORT error occurrs, it'll emit that error instead.
+
+- All errors are from now on errors instead of strings (this only applied to the js parser).
+- If an error occurs while queueing the commands an EXECABORT error will be returned including the failed commands as `.errors` property instead of an array with errors.
+- If an error occurs while executing the commands and that command has a callback it'll return the error as first parameter (`err, undefined` instead of `null, undefined`).
+- All the errors occuring while executing the commands will stay in the result value as error instance (if you used the js parser before they would have been strings). Be aware that the transaction won't be aborted if those error occurr!
+- If `multi.exec` does not have a callback and an EXECABORT error occurrs, it'll emit that error instead.
+
5. If redis can't connect to your redis server it'll give up after a certain point of failures (either max connection attempts or connection timeout exceeded). If that is the case it'll emit an CONNECTION_BROKEN error. You'll have to initiate a new client to try again afterwards.
6. The offline queue is not flushed anymore on a reconnect. It'll stay until node_redis gives up trying to reach the server or until you close the connection.
7. Before this release node_redis catched user errors and threw them async back. This is not the case anymore! No user behavior of what so ever will be tracked or catched.
@@ -501,110 +533,113 @@ From now on we'll push new releases more frequently out and fix further long out
## v1.0.0 - Aug 30, 2015
-* Huge issue and pull-request cleanup. Thanks Blain! (@blainsmith)
-* [#658](https://github.com/NodeRedis/node_redis/pull/658) Client now parses URL-format connection strings (e.g., redis://foo:pass@127.0.0.1:8080) (@kuwabarahiroshi)
-* [#749](https://github.com/NodeRedis/node_redis/pull/749) Fix reconnection bug when client is in monitoring mode (@danielbprice)
-* [#786](https://github.com/NodeRedis/node_redis/pull/786) Refactor createClient. Fixes #651 (@BridgeAR)
-* [#793](https://github.com/NodeRedis/node_redis/pull/793) Refactor tests and improve test coverage (@erinspice, @bcoe)
-* [#733](https://github.com/NodeRedis/node_redis/pull/733) Fixes detect_buffers functionality in the context of exec. Fixes #732, #263 (@raydog)
-* [#785](https://github.com/NodeRedis/node_redis/pull/785) Tiny speedup by using 'use strict' (@BridgeAR)
-* Fix extraneous error output due to pubsub tests (Mikael Kohlmyr)
+- Huge issue and pull-request cleanup. Thanks Blain! (@blainsmith)
+- [#658](https://github.com/NodeRedis/node_redis/pull/658) Client now parses URL-format connection strings (e.g., redis://foo:pass@127.0.0.1:8080) (@kuwabarahiroshi)
+- [#749](https://github.com/NodeRedis/node_redis/pull/749) Fix reconnection bug when client is in monitoring mode (@danielbprice)
+- [#786](https://github.com/NodeRedis/node_redis/pull/786) Refactor createClient. Fixes #651 (@BridgeAR)
+- [#793](https://github.com/NodeRedis/node_redis/pull/793) Refactor tests and improve test coverage (@erinspice, @bcoe)
+- [#733](https://github.com/NodeRedis/node_redis/pull/733) Fixes detect_buffers functionality in the context of exec. Fixes #732, #263 (@raydog)
+- [#785](https://github.com/NodeRedis/node_redis/pull/785) Tiny speedup by using 'use strict' (@BridgeAR)
+- Fix extraneous error output due to pubsub tests (Mikael Kohlmyr)
## v0.12.1 - Aug 10, 2014
-* Fix IPv6/IPv4 family selection in node 0.11+ (Various)
+
+- Fix IPv6/IPv4 family selection in node 0.11+ (Various)
## v0.12.0 - Aug 9, 2014
-* Fix unix socket support (Jack Tang)
-* Improve createClient argument handling (Jack Tang)
+
+- Fix unix socket support (Jack Tang)
+- Improve createClient argument handling (Jack Tang)
## v0.11.0 - Jul 10, 2014
-* IPv6 Support. (Yann Stephan)
-* Revert error emitting and go back to throwing errors. (Bryce Baril)
-* Set socket_keepalive to prevent long-lived client timeouts. (mohit)
-* Correctly reset retry timer. (ouotuo)
-* Domains protection from bad user exit. (Jake Verbaten)
-* Fix reconnection socket logic to prevent misqueued entries. (Iain Proctor)
+- IPv6 Support. (Yann Stephan)
+- Revert error emitting and go back to throwing errors. (Bryce Baril)
+- Set socket_keepalive to prevent long-lived client timeouts. (mohit)
+- Correctly reset retry timer. (ouotuo)
+- Domains protection from bad user exit. (Jake Verbaten)
+- Fix reconnection socket logic to prevent misqueued entries. (Iain Proctor)
## v0.10.3 - May 22, 2014
-* Update command list to match Redis 2.8.9 (Charles Feng)
+- Update command list to match Redis 2.8.9 (Charles Feng)
## v0.10.2 - May 18, 2014
-* Better binary key handling for HGETALL. (Nick Apperson)
-* Fix test not resetting `error` handler. (CrypticSwarm)
-* Fix SELECT error semantics. (Bryan English)
+- Better binary key handling for HGETALL. (Nick Apperson)
+- Fix test not resetting `error` handler. (CrypticSwarm)
+- Fix SELECT error semantics. (Bryan English)
## v0.10.1 - February 17, 2014
-* Skip plucking redis version from the INFO stream if INFO results weren't provided. (Robert Sköld)
+- Skip plucking redis version from the INFO stream if INFO results weren't provided. (Robert Sköld)
## v0.10.0 - December 21, 2013
-* Instead of throwing errors asynchronously, emit errors on client. (Bryce Baril)
+- Instead of throwing errors asynchronously, emit errors on client. (Bryce Baril)
## v0.9.2 - December 15, 2013
-* Regenerate commands for new 2.8.x Redis commands. (Marek Ventur)
-* Correctly time reconnect counts when using 'auth'. (William Hockey)
+- Regenerate commands for new 2.8.x Redis commands. (Marek Ventur)
+- Correctly time reconnect counts when using 'auth'. (William Hockey)
## v0.9.1 - November 23, 2013
-* Allow hmset to accept numeric keys. (Alex Stokes)
-* Fix TypeError for multiple MULTI/EXEC errors. (Kwangsu Kim)
+- Allow hmset to accept numeric keys. (Alex Stokes)
+- Fix TypeError for multiple MULTI/EXEC errors. (Kwangsu Kim)
## v0.9.0 - October 17, 2013
-* Domains support. (Forrest L Norvell)
+- Domains support. (Forrest L Norvell)
## v0.8.6 - October 2, 2013
-* If error is already an Error, don't wrap it in another Error. (Mathieu M-Gosselin)
-* Fix retry delay logic (Ian Babrou)
-* Return Errors instead of strings where Errors are expected (Ian Babrou)
-* Add experimental `.unref()` method to RedisClient (Bryce Baril / Olivier Lalonde)
-* Strengthen checking of reply to prevent conflating "message" or "pmessage" fields with pub_sub replies. (Bryce Baril)
+- If error is already an Error, don't wrap it in another Error. (Mathieu M-Gosselin)
+- Fix retry delay logic (Ian Babrou)
+- Return Errors instead of strings where Errors are expected (Ian Babrou)
+- Add experimental `.unref()` method to RedisClient (Bryce Baril / Olivier Lalonde)
+- Strengthen checking of reply to prevent conflating "message" or "pmessage" fields with pub_sub replies. (Bryce Baril)
## v0.8.5 - September 26, 2013
-* Add `auth_pass` option to connect and immediately authenticate (Henrik Peinar)
+- Add `auth_pass` option to connect and immediately authenticate (Henrik Peinar)
## v0.8.4 - June 24, 2013
Many contributed features and fixes, including:
-* Ignore password set if not needed. (jbergknoff)
-* Improved compatibility with 0.10.X for tests and client.end() (Bryce Baril)
-* Protect connection retries from application exceptions. (Amos Barreto)
-* Better exception handling for Multi/Exec (Thanasis Polychronakis)
-* Renamed pubsub mode to subscriber mode (Luke Plaster)
-* Treat SREM like SADD when passed an array (Martin Ciparelli)
-* Fix empty unsub/punsub TypeError (Jeff Barczewski)
-* Only attempt to run a callback if it one was provided (jifeng)
+
+- Ignore password set if not needed. (jbergknoff)
+- Improved compatibility with 0.10.X for tests and client.end() (Bryce Baril)
+- Protect connection retries from application exceptions. (Amos Barreto)
+- Better exception handling for Multi/Exec (Thanasis Polychronakis)
+- Renamed pubsub mode to subscriber mode (Luke Plaster)
+- Treat SREM like SADD when passed an array (Martin Ciparelli)
+- Fix empty unsub/punsub TypeError (Jeff Barczewski)
+- Only attempt to run a callback if it one was provided (jifeng)
## v0.8.3 - April 09, 2013
Many contributed features and fixes, including:
-* Fix some tests for Node.js version 0.9.x+ changes (Roman Ivanilov)
-* Fix error when commands submitted after idle event handler (roamm)
-* Bypass Redis for no-op SET/SETEX commands (jifeng)
-* Fix HMGET + detect_buffers (Joffrey F)
-* Fix CLIENT LOAD functionality (Jonas Dohse)
-* Add percentage outputs to diff_multi_bench_output.js (Bryce Baril)
-* Add retry_max_delay option (Tomasz Durka)
-* Fix parser off-by-one errors with nested multi-bulk replies (Bryce Baril)
-* Prevent parser from sinking application-side exceptions (Bryce Baril)
-* Fix parser incorrect buffer skip when parsing multi-bulk errors (Bryce Baril)
-* Reverted previous change with throwing on non-string values with HMSET (David Trejo)
-* Fix command queue sync issue when using pubsub (Tom Leach)
-* Fix compatibility with two-word Redis commands (Jonas Dohse)
-* Add EVAL with array syntax (dmoena)
-* Fix tests due to Redis reply order changes in 2.6.5+ (Bryce Baril)
-* Added a test for the SLOWLOG command (Nitesh Sinha)
-* Fix SMEMBERS order dependency in test broken by Redis changes (Garrett Johnson)
-* Update commands for new Redis commands (David Trejo)
-* Prevent exception from SELECT on subscriber reconnection (roamm)
+- Fix some tests for Node.js version 0.9.x+ changes (Roman Ivanilov)
+- Fix error when commands submitted after idle event handler (roamm)
+- Bypass Redis for no-op SET/SETEX commands (jifeng)
+- Fix HMGET + detect_buffers (Joffrey F)
+- Fix CLIENT LOAD functionality (Jonas Dohse)
+- Add percentage outputs to diff_multi_bench_output.js (Bryce Baril)
+- Add retry_max_delay option (Tomasz Durka)
+- Fix parser off-by-one errors with nested multi-bulk replies (Bryce Baril)
+- Prevent parser from sinking application-side exceptions (Bryce Baril)
+- Fix parser incorrect buffer skip when parsing multi-bulk errors (Bryce Baril)
+- Reverted previous change with throwing on non-string values with HMSET (David Trejo)
+- Fix command queue sync issue when using pubsub (Tom Leach)
+- Fix compatibility with two-word Redis commands (Jonas Dohse)
+- Add EVAL with array syntax (dmoena)
+- Fix tests due to Redis reply order changes in 2.6.5+ (Bryce Baril)
+- Added a test for the SLOWLOG command (Nitesh Sinha)
+- Fix SMEMBERS order dependency in test broken by Redis changes (Garrett Johnson)
+- Update commands for new Redis commands (David Trejo)
+- Prevent exception from SELECT on subscriber reconnection (roamm)
## v0.8.2 - November 11, 2012
@@ -621,20 +656,20 @@ Important bug fix for null responses (Jerry Sievert)
Many contributed features and fixes, including:
-* Pure JavaScript reply parser that is usually faster than hiredis (Jerry Sievert)
-* Remove hiredis as optionalDependency from package.json. It still works if you want it.
-* Restore client state on reconnect, including select, subscribe, and monitor. (Ignacio Burgueño)
-* Fix idle event (Trae Robrock)
-* Many documentation improvements and bug fixes (David Trejo)
+- Pure JavaScript reply parser that is usually faster than hiredis (Jerry Sievert)
+- Remove hiredis as optionalDependency from package.json. It still works if you want it.
+- Restore client state on reconnect, including select, subscribe, and monitor. (Ignacio Burgueño)
+- Fix idle event (Trae Robrock)
+- Many documentation improvements and bug fixes (David Trejo)
## v0.7.2 - April 29, 2012
Many contributed fixes. Thank you, contributors.
-* [GH-190] - pub/sub mode fix (Brian Noguchi)
-* [GH-165] - parser selection fix (TEHEK)
-* numerous documentation and examples updates
-* auth errors emit Errors instead of Strings (David Trejo)
+- [GH-190] - pub/sub mode fix (Brian Noguchi)
+- [GH-165] - parser selection fix (TEHEK)
+- numerous documentation and examples updates
+- auth errors emit Errors instead of Strings (David Trejo)
## v0.7.1 - November 15, 2011
@@ -646,21 +681,21 @@ Very much need automated tests for reconnection and queue logic.
Many contributed fixes. Thanks everybody.
-* [GH-127] - properly re-initialize parser on reconnect
-* [GH-136] - handle passing undefined as callback (Ian Babrou)
-* [GH-139] - properly handle exceptions thrown in pub/sub event handlers (Felix Geisendörfer)
-* [GH-141] - detect closing state on stream error (Felix Geisendörfer)
-* [GH-142] - re-select database on reconnection (Jean-Hugues Pinson)
-* [GH-146] - add sort example (Maksim Lin)
+- [GH-127] - properly re-initialize parser on reconnect
+- [GH-136] - handle passing undefined as callback (Ian Babrou)
+- [GH-139] - properly handle exceptions thrown in pub/sub event handlers (Felix Geisendörfer)
+- [GH-141] - detect closing state on stream error (Felix Geisendörfer)
+- [GH-142] - re-select database on reconnection (Jean-Hugues Pinson)
+- [GH-146] - add sort example (Maksim Lin)
Some more goodies:
-* Fix bugs with node 0.6
-* Performance improvements
-* New version of `multi_bench.js` that tests more realistic scenarios
-* [GH-140] - support optional callback for subscribe commands
-* Properly flush and error out command queue when connection fails
-* Initial work on reconnection thresholds
+- Fix bugs with node 0.6
+- Performance improvements
+- New version of `multi_bench.js` that tests more realistic scenarios
+- [GH-140] - support optional callback for subscribe commands
+- Properly flush and error out command queue when connection fails
+- Initial work on reconnection thresholds
## v0.6.7 - July 30, 2011
@@ -669,16 +704,16 @@ Some more goodies:
Fix and test for [GH-123]
Passing an Array as as the last argument should expand as users
-expect. The old behavior was to coerce the arguments into Strings,
+expect. The old behavior was to coerce the arguments into Strings,
which did surprising things with Arrays.
## v0.6.5 - July 6, 2011
Contributed changes:
-* Support SlowBuffers (Umair Siddique)
-* Add Multi to exports (Louis-Philippe Perron)
-* Fix for drain event calculation (Vladimir Dronnikov)
+- Support SlowBuffers (Umair Siddique)
+- Add Multi to exports (Louis-Philippe Perron)
+- Fix for drain event calculation (Vladimir Dronnikov)
Thanks!
@@ -690,15 +725,15 @@ Fix bug with optional callbacks for hmset.
Bugs fixed:
-* authentication retry while server is loading db (danmaz74) [GH-101]
-* command arguments processing issue with arrays
+- authentication retry while server is loading db (danmaz74) [GH-101]
+- command arguments processing issue with arrays
New features:
-* Auto update of new commands from redis.io (Dave Hoover)
-* Performance improvements and backpressure controls.
-* Commands now return the true/false value from the underlying socket write(s).
-* Implement command_queue high water and low water for more better control of queueing.
+- Auto update of new commands from redis.io (Dave Hoover)
+- Performance improvements and backpressure controls.
+- Commands now return the true/false value from the underlying socket write(s).
+- Implement command_queue high water and low water for more better control of queueing.
See `examples/backpressure_drain.js` for more information.
@@ -706,7 +741,7 @@ See `examples/backpressure_drain.js` for more information.
Add support and tests for Redis scripting through EXEC command.
-Bug fix for monitor mode. (forddg)
+Bug fix for monitor mode. (forddg)
Auto update of new commands from redis.io (Dave Hoover)
@@ -714,12 +749,12 @@ Auto update of new commands from redis.io (Dave Hoover)
Lots of bugs fixed.
-* connection error did not properly trigger reconnection logic [GH-85]
-* client.hmget(key, [val1, val2]) was not expanding properly [GH-66]
-* client.quit() while in pub/sub mode would throw an error [GH-87]
-* client.multi(['hmset', 'key', {foo: 'bar'}]) fails [GH-92]
-* unsubscribe before subscribe would make things very confused [GH-88]
-* Add BRPOPLPUSH [GH-79]
+- connection error did not properly trigger reconnection logic [GH-85]
+- client.hmget(key, [val1, val2]) was not expanding properly [GH-66]
+- client.quit() while in pub/sub mode would throw an error [GH-87]
+- client.multi(['hmset', 'key', {foo: 'bar'}]) fails [GH-92]
+- unsubscribe before subscribe would make things very confused [GH-88]
+- Add BRPOPLPUSH [GH-79]
## v0.5.11 - April 7, 2011
@@ -759,17 +794,17 @@ Add probe for server readiness.
When a Redis server starts up, it might take a while to load the dataset into memory.
During this time, the server will accept connections, but will return errors for all non-INFO
-commands. Now node_redis will send an INFO command whenever it connects to a server.
+commands. Now node_redis will send an INFO command whenever it connects to a server.
If the info command indicates that the server is not ready, the client will keep trying until
-the server is ready. Once it is ready, the client will emit a "ready" event as well as the
-"connect" event. The client will queue up all commands sent before the server is ready, just
-like it did before. When the server is ready, all offline/non-ready commands will be replayed.
+the server is ready. Once it is ready, the client will emit a "ready" event as well as the
+"connect" event. The client will queue up all commands sent before the server is ready, just
+like it did before. When the server is ready, all offline/non-ready commands will be replayed.
This should be backward compatible with previous versions.
To disable this ready check behavior, set `options.no_ready_check` when creating the client.
As a side effect of this change, the key/val params from the info command are available as
-`client.server_options`. Further, the version string is decomposed into individual elements
+`client.server_options`. Further, the version string is decomposed into individual elements
in `client.server_options.versions`.
## v0.5.4 - February 11, 2011
@@ -796,17 +831,17 @@ Fix bug where subscribe commands would not handle redis-server startup error pro
Some bug fixes:
-* An important bug fix in reconnection logic. Previously, reply callbacks would be invoked twice after
+- An important bug fix in reconnection logic. Previously, reply callbacks would be invoked twice after
a reconnect.
-* Changed error callback argument to be an actual Error object.
+- Changed error callback argument to be an actual Error object.
New feature:
-* Add friendly syntax for HMSET using an object.
+- Add friendly syntax for HMSET using an object.
## v0.4.1 - December 8, 2010
-Remove warning about missing hiredis. You probably do want it though.
+Remove warning about missing hiredis. You probably do want it though.
## v0.4.0 - December 5, 2010
@@ -836,9 +871,9 @@ Send a friendlier "error" event message on stream errors like connection refused
A few bug fixes.
-* Fixed bug with `nil` multi-bulk reply lengths that showed up with `BLPOP` timeouts.
-* Only emit `end` once when connection goes away.
-* Fixed bug in `test.js` where driver finished before all tests completed.
+- Fixed bug with `nil` multi-bulk reply lengths that showed up with `BLPOP` timeouts.
+- Only emit `end` once when connection goes away.
+- Fixed bug in `test.js` where driver finished before all tests completed.
## unversioned wasteland
diff --git a/node_modules/redis/heroku/index.js b/node_modules/redis/heroku/index.js
new file mode 100644
index 0000000..9c9ec27
--- /dev/null
+++ b/node_modules/redis/heroku/index.js
@@ -0,0 +1,14 @@
+const redis = require("redis");
+const client = redis.createClient(process.env.REDISCLOUD_URL);
+
+console.log(process.env.REDISCLOUD_URL);
+
+setInterval(() => {
+ client.get('a', (err, result) => {
+ if (err) {
+ return console.error(err);
+ }
+
+ console.log(result);
+ })
+}, 3000);
\ No newline at end of file
diff --git a/node_modules/redis/heroku/node_modules/.package-lock.json b/node_modules/redis/heroku/node_modules/.package-lock.json
new file mode 100644
index 0000000..2c67eb2
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/.package-lock.json
@@ -0,0 +1,57 @@
+{
+ "name": "heroku",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "node_modules/denque": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz",
+ "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/redis": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.0.tgz",
+ "integrity": "sha512-//lAOcEtNIKk2ekZibes5oyWKYUVWMvMB71lyD/hS9KRePNkB7AU3nXGkArX6uDKEb2N23EyJBthAv6pagD0uw==",
+ "dependencies": {
+ "denque": "^1.5.0",
+ "redis-commands": "^1.7.0",
+ "redis-errors": "^1.2.0",
+ "redis-parser": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-redis"
+ }
+ },
+ "node_modules/redis-commands": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz",
+ "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ=="
+ },
+ "node_modules/redis-errors": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
+ "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/redis-parser": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
+ "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
+ "dependencies": {
+ "redis-errors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ }
+ }
+}
diff --git a/node_modules/redis/heroku/node_modules/denque/CHANGELOG.md b/node_modules/redis/heroku/node_modules/denque/CHANGELOG.md
new file mode 100644
index 0000000..bb5ffb6
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/denque/CHANGELOG.md
@@ -0,0 +1,4 @@
+## 1.5.0
+
+ - feat: adds capacity option for circular buffers (#27)
+
diff --git a/node_modules/redis/heroku/node_modules/denque/LICENSE b/node_modules/redis/heroku/node_modules/denque/LICENSE
new file mode 100644
index 0000000..fd22a2d
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/denque/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2018 Mike Diarmid (Salakar)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this library except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/node_modules/redis/heroku/node_modules/denque/README.md b/node_modules/redis/heroku/node_modules/denque/README.md
new file mode 100644
index 0000000..6821e0d
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/denque/README.md
@@ -0,0 +1,362 @@
+
+
+---
+
+## Installation
+
+```bash
+npm install redis
+```
+
+## Usage
+
+#### Example
+
+```js
+const redis = require("redis");
+const client = redis.createClient();
+
+client.on("error", function(error) {
+ console.error(error);
+});
+
+client.set("key", "value", redis.print);
+client.get("key", redis.print);
+```
+
+Note that the API is entirely asynchronous. To get data back from the server,
+you'll need to use a callback.
+
+### Promises
+
+Node Redis currently doesn't natively support promises (this is coming in v4), however you can wrap the methods you
+want to use with promises using the built-in Node.js `util.promisify` method on Node.js >= v8;
+
+```js
+const { promisify } = require("util");
+const getAsync = promisify(client.get).bind(client);
+
+getAsync.then(console.log).catch(console.error);
+```
+
+### Commands
+
+This library is a 1 to 1 mapping of the [Redis commands](https://redis.io/commands).
+
+Each Redis command is exposed as a function on the `client` object.
+All functions take either an `args` Array plus optional `callback` Function or
+a variable number of individual arguments followed by an optional callback.
+Examples:
+
+```js
+client.hmset(["key", "foo", "bar"], function(err, res) {
+ // ...
+});
+
+// Works the same as
+client.hmset("key", ["foo", "bar"], function(err, res) {
+ // ...
+});
+
+// Or
+client.hmset("key", "foo", "bar", function(err, res) {
+ // ...
+});
+```
+
+Care should be taken with user input if arrays are possible (via body-parser, query string or other method), as single arguments could be unintentionally interpreted as multiple args.
+
+Note that in either form the `callback` is optional:
+
+```js
+client.set("foo", "bar");
+client.set(["hello", "world"]);
+```
+
+If the key is missing, reply will be null. Only if the [Redis Command
+Reference](http://redis.io/commands) states something else it will not be null.
+
+```js
+client.get("missing_key", function(err, reply) {
+ // reply is null when the key is missing
+ console.log(reply);
+});
+```
+
+Minimal parsing is done on the replies. Commands that return a integer return
+JavaScript Numbers, arrays return JavaScript Array. `HGETALL` returns an Object
+keyed by the hash keys. All strings will either be returned as string or as
+buffer depending on your setting. Please be aware that sending null, undefined
+and Boolean values will result in the value coerced to a string!
+
+## API
+
+### Connection and other Events
+
+`client` will emit some events about the state of the connection to the Redis server.
+
+#### `"ready"`
+
+`client` will emit `ready` once a connection is established. Commands issued
+before the `ready` event are queued, then replayed just before this event is
+emitted.
+
+#### `"connect"`
+
+`client` will emit `connect` as soon as the stream is connected to the server.
+
+#### `"reconnecting"`
+
+`client` will emit `reconnecting` when trying to reconnect to the Redis server
+after losing the connection. Listeners are passed an object containing `delay`
+(in ms from the previous try) and `attempt` (the attempt #) attributes.
+
+#### `"error"`
+
+`client` will emit `error` when encountering an error connecting to the Redis
+server or when any other in Node Redis occurs. If you use a command without
+callback and encounter a ReplyError it is going to be emitted to the error
+listener.
+
+So please attach the error listener to Node Redis.
+
+#### `"end"`
+
+`client` will emit `end` when an established Redis server connection has closed.
+
+#### `"warning"`
+
+`client` will emit `warning` when password was set but none is needed and if a
+deprecated option / function / similar is used.
+
+### redis.createClient()
+
+If you have `redis-server` running on the same machine as node, then the
+defaults for port and host are probably fine and you don't need to supply any
+arguments. `createClient()` returns a `RedisClient` object. Otherwise,
+`createClient()` accepts these arguments:
+
+- `redis.createClient([options])`
+- `redis.createClient(unix_socket[, options])`
+- `redis.createClient(redis_url[, options])`
+- `redis.createClient(port[, host][, options])`
+
+**Tip:** If the Redis server runs on the same machine as the client consider
+using unix sockets if possible to increase throughput.
+
+**Note:** Using `'rediss://...` for the protocol in a `redis_url` will enable a TLS socket connection. However, additional TLS options will need to be passed in `options`, if required.
+
+#### `options` object properties
+
+| Property | Default | Description |
+| -------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| host | 127.0.0.1 | IP address of the Redis server |
+| port | 6379 | Port of the Redis server |
+| path | null | The UNIX socket string of the Redis server |
+| url | null | The URL of the Redis server. Format: `[redis[s]:]//[[user][:password@]][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]` (More info avaliable at [IANA](http://www.iana.org/assignments/uri-schemes/prov/redis)). |
+| string_numbers | null | Set to `true`, Node Redis will return Redis number values as Strings instead of javascript Numbers. Useful if you need to handle big numbers (above `Number.MAX_SAFE_INTEGER === 2^53`). Hiredis is incapable of this behavior, so setting this option to `true` will result in the built-in javascript parser being used no matter the value of the `parser` option. |
+| return_buffers | false | If set to `true`, then all replies will be sent to callbacks as Buffers instead of Strings. |
+| detect_buffers | false | If set to `true`, then replies will be sent to callbacks as Buffers. This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to every command on a client. **Note**: This doesn't work properly with the pubsub mode. A subscriber has to either always return Strings or Buffers. |
+| socket_keepalive | true | If set to `true`, the keep-alive functionality is enabled on the underlying socket. |
+| socket_initial_delay | 0 | Initial Delay in milliseconds, and this will also behave the interval keep alive message sending to Redis. |
+| no_ready_check | false | When a connection is established to the Redis server, the server might still be loading the database from disk. While loading, the server will not respond to any commands. To work around this, Node Redis has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. Setting `no_ready_check` to `true` will inhibit this check. |
+| enable_offline_queue | true | By default, if there is no active connection to the Redis server, commands are added to a queue and are executed once the connection has been established. Setting `enable_offline_queue` to `false` will disable this feature and the callback will be executed immediately with an error, or an error will be emitted if no callback is specified. |
+| retry_unfulfilled_commands | false | If set to `true`, all commands that were unfulfilled while the connection is lost will be retried after the connection has been reestablished. Use this with caution if you use state altering commands (e.g. `incr`). This is especially useful if you use blocking commands. |
+| password | null | If set, client will run Redis auth command on connect. Alias `auth_pass` **Note** Node Redis < 2.5 must use `auth_pass` |
+| user | null | The ACL user (only valid when `password` is set) |
+| db | null | If set, client will run Redis `select` command on connect. |
+| family | IPv4 | You can force using IPv6 if you set the family to 'IPv6'. See Node.js [net](https://nodejs.org/api/net.html) or [dns](https://nodejs.org/api/dns.html) modules on how to use the family type. |
+| disable_resubscribing | false | If set to `true`, a client won't resubscribe after disconnecting. |
+| rename_commands | null | Passing an object with renamed commands to use instead of the original functions. For example, if you renamed the command KEYS to "DO-NOT-USE" then the rename_commands object would be: `{ KEYS : "DO-NOT-USE" }` . See the [Redis security topics](http://redis.io/topics/security) for more info. |
+| tls | null | An object containing options to pass to [tls.connect](http://nodejs.org/api/tls.html#tls_tls_connect_port_host_options_callback) to set up a TLS connection to Redis (if, for example, it is set up to be accessible via a tunnel). |
+| prefix | null | A string used to prefix all used keys (e.g. `namespace:test`). Please be aware that the `keys` command will not be prefixed. The `keys` command has a "pattern" as argument and no key and it would be impossible to determine the existing keys in Redis if this would be prefixed. |
+| retry_strategy | function | A function that receives an options object as parameter including the retry `attempt`, the `total_retry_time` indicating how much time passed since the last time connected, the `error` why the connection was lost and the number of `times_connected` in total. If you return a number from this function, the retry will happen exactly after that time in milliseconds. If you return a non-number, no further retry will happen and all offline commands are flushed with errors. Return an error to return that specific error to all offline commands. Example below. |
+| connect_timeout | 3600000 | In milliseconds. This should only be the timeout for connecting to redis, but for now it interferes with `retry_strategy` and stops it from reconnecting after this timeout. |
+
+**`detect_buffers` example:**
+
+```js
+const redis = require("redis");
+const client = redis.createClient({ detect_buffers: true });
+
+client.set("foo_rand000000000000", "OK");
+
+// This will return a JavaScript String
+client.get("foo_rand000000000000", function(err, reply) {
+ console.log(reply.toString()); // Will print `OK`
+});
+
+// This will return a Buffer since original key is specified as a Buffer
+client.get(new Buffer("foo_rand000000000000"), function(err, reply) {
+ console.log(reply.toString()); // Will print ``
+});
+```
+
+**`retry_strategy` example:**
+
+```js
+const client = redis.createClient({
+ retry_strategy: function(options) {
+ if (options.error && options.error.code === "ECONNREFUSED") {
+ // End reconnecting on a specific error and flush all commands with
+ // a individual error
+ return new Error("The server refused the connection");
+ }
+ if (options.total_retry_time > 1000 * 60 * 60) {
+ // End reconnecting after a specific timeout and flush all commands
+ // with a individual error
+ return new Error("Retry time exhausted");
+ }
+ if (options.attempt > 10) {
+ // End reconnecting with built in error
+ return undefined;
+ }
+ // reconnect after
+ return Math.min(options.attempt * 100, 3000);
+ },
+});
+```
+
+### client.auth(password[, callback])
+
+When connecting to a Redis server that requires authentication, the `AUTH`
+command must be sent as the first command after connecting. This can be tricky
+to coordinate with reconnections, the ready check, etc. To make this easier,
+`client.auth()` stashes `password` and will send it after each connection,
+including reconnections. `callback` is invoked only once, after the response to
+the very first `AUTH` command sent.
+NOTE: Your call to `client.auth()` should not be inside the ready handler. If
+you are doing this wrong, `client` will emit an error that looks
+something like this `Error: Ready check failed: ERR operation not permitted`.
+
+### client.quit(callback)
+
+This sends the quit command to the redis server and ends cleanly right after all
+running commands were properly handled. If this is called while reconnecting
+(and therefore no connection to the redis server exists) it is going to end the
+connection right away instead of resulting in further reconnections! All offline
+commands are going to be flushed with an error in that case.
+
+### client.end(flush)
+
+Forcibly close the connection to the Redis server. Note that this does not wait
+until all replies have been parsed. If you want to exit cleanly, call
+`client.quit()` as mentioned above.
+
+You should set flush to true, if you are not absolutely sure you do not care
+about any other commands. If you set flush to false all still running commands
+will silently fail.
+
+This example closes the connection to the Redis server before the replies have
+been read. You probably don't want to do this:
+
+```js
+const redis = require("redis");
+const client = redis.createClient();
+
+client.set("hello", "world", function(err) {
+ // This will either result in an error (flush parameter is set to true)
+ // or will silently fail and this callback will not be called at all (flush set to false)
+ console.error(err);
+});
+
+// No further commands will be processed
+client.end(true);
+
+client.get("hello", function(err) {
+ console.error(err); // => 'The connection has already been closed.'
+});
+```
+
+`client.end()` without the flush parameter set to true should NOT be used in production!
+
+### Error Handling
+
+Currently the following `Error` subclasses exist:
+
+- `RedisError`: _All errors_ returned by the client
+- `ReplyError` subclass of `RedisError`: All errors returned by **Redis** itself
+- `AbortError` subclass of `RedisError`: All commands that could not finish due
+ to what ever reason
+- `ParserError` subclass of `RedisError`: Returned in case of a parser error
+ (this should not happen)
+- `AggregateError` subclass of `AbortError`: Emitted in case multiple unresolved
+ commands without callback got rejected in debug_mode instead of lots of
+ `AbortError`s.
+
+All error classes are exported by the module.
+
+#### Example
+
+```js
+const assert = require("assert");
+
+const redis = require("redis");
+const { AbortError, AggregateError, ReplyError } = require("redis");
+
+const client = redis.createClient();
+
+client.on("error", function(err) {
+ assert(err instanceof Error);
+ assert(err instanceof AbortError);
+ assert(err instanceof AggregateError);
+
+ // The set and get are aggregated in here
+ assert.strictEqual(err.errors.length, 2);
+ assert.strictEqual(err.code, "NR_CLOSED");
+});
+
+client.set("foo", "bar", "baz", function(err, res) {
+ // Too many arguments
+ assert(err instanceof ReplyError); // => true
+ assert.strictEqual(err.command, "SET");
+ assert.deepStrictEqual(err.args, ["foo", 123, "bar"]);
+
+ redis.debug_mode = true;
+
+ client.set("foo", "bar");
+ client.get("foo");
+
+ process.nextTick(function() {
+ // Force closing the connection while the command did not yet return
+ client.end(true);
+ redis.debug_mode = false;
+ });
+});
+```
+
+Every `ReplyError` contains the `command` name in all-caps and the arguments (`args`).
+
+If Node Redis emits a library error because of another error, the triggering
+error is added to the returned error as `origin` attribute.
+
+**_Error codes_**
+
+Node Redis returns a `NR_CLOSED` error code if the clients connection dropped.
+If a command unresolved command got rejected a `UNCERTAIN_STATE` code is
+returned. A `CONNECTION_BROKEN` error code is used in case Node Redis gives up
+to reconnect.
+
+### client.unref()
+
+Call `unref()` on the underlying socket connection to the Redis server, allowing
+the program to exit once no more commands are pending.
+
+This is an **experimental** feature, and only supports a subset of the Redis
+protocol. Any commands where client state is saved on the Redis server, e.g.
+`*SUBSCRIBE` or the blocking `BL*` commands will _NOT_ work with `.unref()`.
+
+```js
+const redis = require("redis");
+const client = redis.createClient();
+
+/*
+ * Calling unref() will allow this program to exit immediately after the get
+ * command finishes. Otherwise the client would hang as long as the
+ * client-server connection is alive.
+ */
+client.unref();
+
+client.get("foo", function(err, value) {
+ if (err) throw err;
+ console.log(value);
+});
+```
+
+### Hash Commands
+
+Most Redis commands take a single String or an Array of Strings as arguments,
+and replies are sent back as a single String or an Array of Strings. When
+dealing with hash values, there are a couple of useful exceptions to this.
+
+#### client.hgetall(hash, callback)
+
+The reply from an `HGETALL` command will be converted into a JavaScript Object. That way you can interact with the
+responses using JavaScript syntax.
+
+**Example:**
+
+```js
+client.hmset("key", "foo", "bar", "hello", "world");
+
+client.hgetall("key", function(err, value) {
+ console.log(value.foo); // > "bar"
+ console.log(value.hello); // > "world"
+});
+```
+
+#### client.hmset(hash, key1, val1, ...keyN, valN, [callback])
+
+Multiple values may also be set by supplying more arguments.
+
+**Example:**
+
+```js
+// key
+// 1) foo => bar
+// 2) hello => world
+client.HMSET("key", "foo", "bar", "hello", "world");
+```
+
+### PubSub
+
+#### Example
+
+This example opens two client connections, subscribes to a channel on one of them, and publishes to that
+channel on the other.
+
+```js
+const redis = require("redis");
+
+const subscriber = redis.createClient();
+const publisher = redis.createClient();
+
+let messageCount = 0;
+
+subscriber.on("subscribe", function(channel, count) {
+ publisher.publish("a channel", "a message");
+ publisher.publish("a channel", "another message");
+});
+
+subscriber.on("message", function(channel, message) {
+ messageCount += 1;
+
+ console.log("Subscriber received message in channel '" + channel + "': " + message);
+
+ if (messageCount === 2) {
+ subscriber.unsubscribe();
+ subscriber.quit();
+ publisher.quit();
+ }
+});
+
+subscriber.subscribe("a channel");
+```
+
+When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into
+a `"subscriber"` mode. At that point, the only valid commands are those that modify the subscription
+set, and quit (also ping on some redis versions). When
+the subscription set is empty, the connection is put back into regular mode.
+
+If you need to send regular commands to Redis while in subscriber mode, just
+open another connection with a new client (use `client.duplicate()` to quickly duplicate an existing client).
+
+#### Subscriber Events
+
+If a client has subscriptions active, it may emit these events:
+
+**"message" (channel, message)**:
+
+Client will emit `message` for every message received that matches an active subscription.
+Listeners are passed the channel name as `channel` and the message as `message`.
+
+**"pmessage" (pattern, channel, message)**:
+
+Client will emit `pmessage` for every message received that matches an active
+subscription pattern. Listeners are passed the original pattern used with
+`PSUBSCRIBE` as `pattern`, the sending channel name as `channel`, and the
+message as `message`.
+
+**"message_buffer" (channel, message)**:
+
+This is the same as the `message` event with the exception, that it is always
+going to emit a buffer. If you listen to the `message` event at the same time as
+the `message_buffer`, it is always going to emit a string.
+
+**"pmessage_buffer" (pattern, channel, message)**:
+
+This is the same as the `pmessage` event with the exception, that it is always
+going to emit a buffer. If you listen to the `pmessage` event at the same time
+as the `pmessage_buffer`, it is always going to emit a string.
+
+**"subscribe" (channel, count)**:
+
+Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are
+passed the channel name as `channel` and the new count of subscriptions for this
+client as `count`.
+
+**"psubscribe" (pattern, count)**:
+
+Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners
+are passed the original pattern as `pattern`, and the new count of subscriptions
+for this client as `count`.
+
+**"unsubscribe" (channel, count)**:
+
+Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners
+are passed the channel name as `channel` and the new count of subscriptions for
+this client as `count`. When `count` is 0, this client has left subscriber mode
+and no more subscriber events will be emitted.
+
+**"punsubscribe" (pattern, count)**:
+
+Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command.
+Listeners are passed the channel name as `channel` and the new count of
+subscriptions for this client as `count`. When `count` is 0, this client has
+left subscriber mode and no more subscriber events will be emitted.
+
+### client.multi([commands])
+
+`MULTI` commands are queued up until an `EXEC` is issued, and then all commands
+are run atomically by Redis. The interface returns an
+individual `Multi` object by calling `client.multi()`. If any command fails to
+queue, all commands are rolled back and none is going to be executed (For
+further information see the [Redis transactions](http://redis.io/topics/transactions) documentation).
+
+```js
+const redis = require("redis");
+const client = redis.createClient();
+
+let setSize = 20;
+
+client.sadd("key", "member1");
+client.sadd("key", "member2");
+
+while (setSize > 0) {
+ client.sadd("key", "member" + setSize);
+ setSize -= 1;
+}
+
+// chain commands
+client
+ .multi()
+ .scard("key")
+ .smembers("key")
+ .keys("*")
+ .dbsize()
+ .exec(function(err, replies) {
+ console.log("MULTI got " + replies.length + " replies");
+ replies.forEach(function(reply, index) {
+ console.log("REPLY @ index " + index + ": " + reply.toString());
+ });
+ });
+```
+
+#### Multi.exec([callback])
+
+`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects
+share all of the same command methods as `client` objects do. Commands are
+queued up inside the `Multi` object until `Multi.exec()` is invoked.
+
+If your code contains an syntax error an `EXECABORT` error is going to be thrown
+and all commands are going to be aborted. That error contains a `.errors`
+property that contains the concrete errors.
+If all commands were queued successfully and an error is thrown by redis while
+processing the commands that error is going to be returned in the result array!
+No other command is going to be aborted though than the ones failing.
+
+You can either chain together `MULTI` commands as in the above example, or you
+can queue individual commands while still sending regular client command as in
+this example:
+
+```js
+const redis = require("redis");
+const client = redis.createClient();
+
+// start a separate multi command queue
+const multi = client.multi();
+
+// add some commands to the queue
+multi.incr("count_cats", redis.print);
+multi.incr("count_dogs", redis.print);
+
+// runs a command immediately outside of the `multi` instance
+client.mset("count_cats", 100, "count_dogs", 50, redis.print);
+
+// drains the multi queue and runs each command atomically
+multi.exec(function(err, replies) {
+ console.log(replies); // 101, 51
+});
+```
+
+In addition to adding commands to the `MULTI` queue individually, you can also
+pass an array of commands and arguments to the constructor:
+
+```js
+const redis = require("redis");
+
+const client = redis.createClient();
+
+client
+ .multi([
+ ["mget", "foo", "bar", redis.print],
+ ["incr", "hello"],
+ ])
+ .exec(function(err, replies) {
+ console.log(replies);
+ });
+```
+
+#### Multi.exec_atomic([callback])
+
+Identical to Multi.exec but with the difference that executing a single command
+will not use transactions.
+
+#### Optimistic Locks
+
+Using `multi` you can make sure your modifications run as a transaction, but you
+can't be sure you got there first. What if another client modified a key while
+you were working with it's data?
+
+To solve this, Redis supports the [WATCH](https://redis.io/topics/transactions)
+command, which is meant to be used with MULTI:
+
+```js
+const redis = require("redis");
+
+const client = redis.createClient();
+
+client.watch("foo", function(watchError) {
+ if (watchError) throw watchError;
+
+ client.get("foo", function(getError, result) {
+ if (getError) throw getError;
+
+ // Process result
+ // Heavy and time consuming operation here to generate "bar"
+
+ client
+ .multi()
+ .set("foo", "bar")
+ .exec(function(execError, results) {
+ /**
+ * If err is null, it means Redis successfully attempted
+ * the operation.
+ */
+ if (execError) throw execError;
+
+ /**
+ * If results === null, it means that a concurrent client
+ * changed the key while we were processing it and thus
+ * the execution of the MULTI command was not performed.
+ *
+ * NOTICE: Failing an execution of MULTI is not considered
+ * an error. So you will have err === null and results === null
+ */
+ });
+ });
+});
+```
+
+The above snippet shows the correct usage of `watch` with `multi`. Every time a
+watched key is changed before the execution of a `multi` command, the execution
+will return `null`. On a normal situation, the execution will return an array of
+values with the results of the operations.
+
+As stated in the snippet, failing the execution of a `multi` command being watched
+is not considered an error. The execution may return an error if, for example, the
+client cannot connect to Redis.
+
+An example where we can see the execution of a `multi` command fail is as follows:
+
+```js
+const clients = {
+ watcher: redis.createClient(),
+ modifier: redis.createClient(),
+};
+
+clients.watcher.watch("foo", function(watchError) {
+ if (watchError) throw watchError;
+
+ // if you comment out the next line, the transaction will work
+ clients.modifier.set("foo", Math.random(), setError => {
+ if (setError) throw setError;
+ });
+
+ // using a setTimeout here to ensure that the MULTI/EXEC will come after the SET.
+ // Normally, you would use a callback to ensure order, but I want the above SET command
+ // to be easily comment-out-able.
+ setTimeout(function() {
+ clients.watcher
+ .multi()
+ .set("foo", "bar")
+ .set("hello", "world")
+ .exec((multiExecError, results) => {
+ if (multiExecError) throw multiExecError;
+
+ if (results === null) {
+ console.log("transaction aborted because results were null");
+ } else {
+ console.log("transaction worked and returned", results);
+ }
+
+ clients.watcher.quit();
+ clients.modifier.quit();
+ });
+ }, 1000);
+});
+```
+
+#### `WATCH` limitations
+
+Redis WATCH works only on _whole_ key values. For example, with WATCH you can
+watch a hash for modifications, but you cannot watch a specific field of a hash.
+
+The following example would watch the keys `foo` and `hello`, not the field `hello`
+of hash `foo`:
+
+```js
+const redis = require("redis");
+
+const client = redis.createClient();
+
+client.hget("foo", "hello", function(hashGetError, result) {
+ if (hashGetError) throw hashGetError;
+
+ //Do some processing with the value from this field and watch it after
+
+ client.watch("foo", "hello", function(watchError) {
+ if (watchError) throw watchError;
+
+ /**
+ * This is now watching the keys 'foo' and 'hello'. It is not
+ * watching the field 'hello' of hash 'foo'. Because the key 'foo'
+ * refers to a hash, this command is now watching the entire hash
+ * for modifications.
+ */
+ });
+});
+```
+
+This limitation also applies to sets (you can not watch individual set members)
+and any other collections.
+
+### client.batch([commands])
+
+Identical to `.multi()` without transactions. This is recommended if you want to
+execute many commands at once but don't need to rely on transactions.
+
+`BATCH` commands are queued up until an `EXEC` is issued, and then all commands
+are run atomically by Redis. The interface returns an
+individual `Batch` object by calling `client.batch()`. The only difference
+between .batch and .multi is that no transaction is going to be used.
+Be aware that the errors are - just like in multi statements - in the result.
+Otherwise both, errors and results could be returned at the same time.
+
+If you fire many commands at once this is going to boost the execution speed
+significantly compared to firing the same commands in a loop without waiting for
+the result! See the benchmarks for further comparison. Please remember that all
+commands are kept in memory until they are fired.
+
+### Monitor mode
+
+Redis supports the `MONITOR` command, which lets you see all commands received
+by the Redis server across all client connections, including from other client
+libraries and other computers.
+
+A `monitor` event is going to be emitted for every command fired from any client
+connected to the server including the monitoring client itself. The callback for
+the `monitor` event takes a timestamp from the Redis server, an array of command
+arguments and the raw monitoring string.
+
+#### Example:
+
+```js
+const redis = require("redis");
+const client = redis.createClient();
+
+client.monitor(function(err, res) {
+ console.log("Entering monitoring mode.");
+});
+
+client.set("foo", "bar");
+
+client.on("monitor", function(time, args, rawReply) {
+ console.log(time + ": " + args); // 1458910076.446514:['set', 'foo', 'bar']
+});
+```
+
+## Extras
+
+Some other things you might find useful.
+
+### `client.server_info`
+
+After the ready probe completes, the results from the INFO command are saved in
+the `client.server_info` object.
+
+The `versions` key contains an array of the elements of the version string for
+easy comparison.
+
+```
+> client.server_info.redis_version
+'2.3.0'
+> client.server_info.versions
+[ 2, 3, 0 ]
+```
+
+### `redis.print()`
+
+A handy callback function for displaying return values when testing. Example:
+
+```js
+const redis = require("redis");
+const client = redis.createClient();
+
+client.on("connect", function() {
+ client.set("foo", "bar", redis.print); // => "Reply: OK"
+ client.get("foo", redis.print); // => "Reply: bar"
+ client.quit();
+});
+```
+
+### Multi-word commands
+
+To execute redis multi-word commands like `SCRIPT LOAD` or `CLIENT LIST` pass
+the second word as first parameter:
+
+```js
+client.script("load", "return 1");
+
+client
+ .multi()
+ .script("load", "return 1")
+ .exec();
+
+client.multi([["script", "load", "return 1"]]).exec();
+```
+
+### `client.duplicate([options][, callback])`
+
+Duplicate all current options and return a new redisClient instance. All options
+passed to the duplicate function are going to replace the original option. If
+you pass a callback, duplicate is going to wait until the client is ready and
+returns it in the callback. If an error occurs in the meanwhile, that is going
+to return an error instead in the callback.
+
+One example of when to use duplicate() would be to accommodate the connection-
+blocking redis commands `BRPOP`, `BLPOP`, and `BRPOPLPUSH`. If these commands
+are used on the same Redis client instance as non-blocking commands, the
+non-blocking ones may be queued up until after the blocking ones finish.
+
+Another reason to use duplicate() is when multiple DBs on the same server are
+accessed via the redis SELECT command. Each DB could use its own connection.
+
+### `client.sendCommand(command_name[, [args][, callback]])`
+
+All Redis commands have been added to the `client` object. However, if new
+commands are introduced before this library is updated or if you want to add
+individual commands you can use `sendCommand()` to send arbitrary commands to
+Redis.
+
+All commands are sent as multi-bulk commands. `args` can either be an Array of
+arguments, or omitted / set to undefined.
+
+### `redis.addCommand(command_name)`
+
+Calling addCommand will add a new command to the prototype. The exact command
+name will be used when calling using this new command. Using arbitrary arguments
+is possible as with any other command.
+
+### `client.connected`
+
+Boolean tracking the state of the connection to the Redis server.
+
+### `client.command_queue_length`
+
+The number of commands that have been sent to the Redis server but not yet
+replied to. You can use this to enforce some kind of maximum queue depth for
+commands while connected.
+
+### `client.offline_queue_length`
+
+The number of commands that have been queued up for a future connection. You can
+use this to enforce some kind of maximum queue depth for pre-connection
+commands.
+
+### Commands with Optional and Keyword arguments
+
+This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation.
+
+#### Example
+
+```js
+const args = ["myzset", 1, "one", 2, "two", 3, "three", 99, "ninety-nine"];
+
+client.zadd(args, function(addError, addResponse) {
+ if (addError) throw addError;
+ console.log("added " + addResponse + " items.");
+
+ // -Infinity and +Infinity also work
+ const args1 = ["myzset", "+inf", "-inf"];
+ client.zrevrangebyscore(args1, function(rangeError, rangeResponse) {
+ if (rangeError) throw rangeError;
+ console.log("response1", rangeResponse);
+ // ...
+ });
+
+ const max = 3;
+ const min = 1;
+ const offset = 1;
+ const count = 2;
+ const args2 = ["myzset", max, min, "WITHSCORES", "LIMIT", offset, count];
+ client.zrevrangebyscore(args2, function(rangeError, rangeResponse) {
+ if (rangeError) throw rangeError;
+ console.log("response2", rangeResponse);
+ // ...
+ });
+});
+```
+
+## Performance
+
+Much effort has been spent to make Node Redis as fast as possible for common operations.
+
+```
+Mac mini (2018), i7-3.2GHz and 32gb memory
+clients: 1, NodeJS: 12.15.0, Redis: 5.0.6, parser: javascript, connected by: tcp
+ PING, 1/1 avg/max: 0.03/ 3.28 2501ms total, 31926 ops/sec
+ PING, batch 50/1 avg/max: 0.08/ 3.35 2501ms total, 599460 ops/sec
+ SET 4B str, 1/1 avg/max: 0.03/ 3.54 2501ms total, 29483 ops/sec
+ SET 4B str, batch 50/1 avg/max: 0.10/ 1.39 2501ms total, 477689 ops/sec
+ SET 4B buf, 1/1 avg/max: 0.04/ 1.52 2501ms total, 23449 ops/sec
+ SET 4B buf, batch 50/1 avg/max: 0.20/ 2.09 2501ms total, 244382 ops/sec
+ GET 4B str, 1/1 avg/max: 0.03/ 1.35 2501ms total, 32205 ops/sec
+ GET 4B str, batch 50/1 avg/max: 0.09/ 2.02 2501ms total, 568992 ops/sec
+ GET 4B buf, 1/1 avg/max: 0.03/ 2.93 2501ms total, 32802 ops/sec
+ GET 4B buf, batch 50/1 avg/max: 0.08/ 1.03 2501ms total, 592863 ops/sec
+ SET 4KiB str, 1/1 avg/max: 0.03/ 0.76 2501ms total, 29287 ops/sec
+ SET 4KiB str, batch 50/1 avg/max: 0.35/ 2.97 2501ms total, 143163 ops/sec
+ SET 4KiB buf, 1/1 avg/max: 0.04/ 1.21 2501ms total, 23070 ops/sec
+ SET 4KiB buf, batch 50/1 avg/max: 0.28/ 2.34 2501ms total, 176809 ops/sec
+ GET 4KiB str, 1/1 avg/max: 0.03/ 1.54 2501ms total, 29555 ops/sec
+ GET 4KiB str, batch 50/1 avg/max: 0.18/ 1.59 2501ms total, 279188 ops/sec
+ GET 4KiB buf, 1/1 avg/max: 0.03/ 1.80 2501ms total, 30681 ops/sec
+ GET 4KiB buf, batch 50/1 avg/max: 0.17/ 5.00 2501ms total, 285886 ops/sec
+ INCR, 1/1 avg/max: 0.03/ 1.99 2501ms total, 32757 ops/sec
+ INCR, batch 50/1 avg/max: 0.09/ 2.54 2501ms total, 538964 ops/sec
+ LPUSH, 1/1 avg/max: 0.05/ 4.85 2501ms total, 19482 ops/sec
+ LPUSH, batch 50/1 avg/max: 0.12/ 9.52 2501ms total, 395562 ops/sec
+ LRANGE 10, 1/1 avg/max: 0.06/ 9.21 2501ms total, 17062 ops/sec
+ LRANGE 10, batch 50/1 avg/max: 0.22/ 1.03 2501ms total, 228269 ops/sec
+ LRANGE 100, 1/1 avg/max: 0.05/ 1.44 2501ms total, 19051 ops/sec
+ LRANGE 100, batch 50/1 avg/max: 0.99/ 3.46 2501ms total, 50480 ops/sec
+ SET 4MiB str, 1/1 avg/max: 4.11/ 13.96 2501ms total, 243 ops/sec
+ SET 4MiB str, batch 20/1 avg/max: 91.16/145.01 2553ms total, 219 ops/sec
+ SET 4MiB buf, 1/1 avg/max: 2.81/ 11.90 2502ms total, 354 ops/sec
+ SET 4MiB buf, batch 20/1 avg/max: 36.21/ 70.96 2535ms total, 552 ops/sec
+ GET 4MiB str, 1/1 avg/max: 2.82/ 19.10 2503ms total, 354 ops/sec
+ GET 4MiB str, batch 20/1 avg/max: 128.57/207.86 2572ms total, 156 ops/sec
+ GET 4MiB buf, 1/1 avg/max: 3.13/ 23.88 2501ms total, 318 ops/sec
+ GET 4MiB buf, batch 20/1 avg/max: 65.91/ 87.59 2572ms total, 303 ops/sec
+```
+
+## Debugging
+
+To get debug output run your Node Redis application with `NODE_DEBUG=redis`.
+
+This is also going to result in good stack traces opposed to useless ones
+otherwise for any async operation.
+If you only want to have good stack traces but not the debug output run your
+application in development mode instead (`NODE_ENV=development`).
+
+Good stack traces are only activated in development and debug mode as this
+results in a significant performance penalty.
+
+**_Comparison_**:
+
+Standard stack trace:
+
+```
+ReplyError: ERR wrong number of arguments for 'set' command
+ at parseError (/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:158:12)
+ at parseType (/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:219:14)
+```
+
+Debug stack trace:
+
+```
+ReplyError: ERR wrong number of arguments for 'set' command
+ at new Command (/home/ruben/repos/redis/lib/command.js:9:902)
+ at RedisClient.set (/home/ruben/repos/redis/lib/commands.js:9:3238)
+ at Context. (/home/ruben/repos/redis/test/good_stacks.spec.js:20:20)
+ at callFnAsync (/home/ruben/repos/redis/node_modules/mocha/lib/runnable.js:349:8)
+ at Test.Runnable.run (/home/ruben/repos/redis/node_modules/mocha/lib/runnable.js:301:7)
+ at Runner.runTest (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:422:10)
+ at /home/ruben/repos/redis/node_modules/mocha/lib/runner.js:528:12
+ at next (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:342:14)
+ at /home/ruben/repos/redis/node_modules/mocha/lib/runner.js:352:7
+ at next (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:284:14)
+ at Immediate._onImmediate (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:320:5)
+ at processImmediate [as _immediateCallback] (timers.js:383:17)
+```
+
+## Contributing
+
+Please see the [contributing guide](CONTRIBUTING.md).
+
+## License
+
+This repository is licensed under the "MIT" license. See [LICENSE](LICENSE).
diff --git a/node_modules/redis/heroku/node_modules/redis/a.js b/node_modules/redis/heroku/node_modules/redis/a.js
new file mode 100644
index 0000000..4b7bfb4
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/a.js
@@ -0,0 +1,12 @@
+let i = 1;
+
+async function write(i) {
+ try {
+ await cluster.incr(i);
+ } catch (err) {
+ console.error(i, err);
+ } finally {
+ await write(i + 1);
+ }
+}
+write(1)
\ No newline at end of file
diff --git a/node_modules/redis/heroku/node_modules/redis/index.js b/node_modules/redis/heroku/node_modules/redis/index.js
new file mode 100644
index 0000000..fe79c5f
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/index.js
@@ -0,0 +1,1039 @@
+'use strict';
+
+var net = require('net');
+var tls = require('tls');
+var util = require('util');
+var utils = require('./lib/utils');
+var Command = require('./lib/command');
+var Queue = require('denque');
+var errorClasses = require('./lib/customErrors');
+var EventEmitter = require('events');
+var Parser = require('redis-parser');
+var RedisErrors = require('redis-errors');
+var commands = require('redis-commands');
+var debug = require('./lib/debug');
+var unifyOptions = require('./lib/createClient');
+var SUBSCRIBE_COMMANDS = {
+ subscribe: true,
+ unsubscribe: true,
+ psubscribe: true,
+ punsubscribe: true
+};
+
+function noop () {}
+
+function handle_detect_buffers_reply (reply, command, buffer_args) {
+ if (buffer_args === false || this.message_buffers) {
+ // If detect_buffers option was specified, then the reply from the parser will be a buffer.
+ // If this command did not use Buffer arguments, then convert the reply to Strings here.
+ reply = utils.reply_to_strings(reply);
+ }
+
+ if (command === 'hgetall') {
+ reply = utils.reply_to_object(reply);
+ }
+ return reply;
+}
+
+exports.debug_mode = /\bredis\b/i.test(process.env.NODE_DEBUG);
+
+// Attention: The second parameter might be removed at will and is not officially supported.
+// Do not rely on this
+function RedisClient (options, stream) {
+ // Copy the options so they are not mutated
+ options = utils.clone(options);
+ EventEmitter.call(this);
+ var cnx_options = {};
+ var self = this;
+ /* istanbul ignore next: travis does not work with stunnel atm. Therefore the tls tests are skipped on travis */
+ for (var tls_option in options.tls) {
+ cnx_options[tls_option] = options.tls[tls_option];
+ // Copy the tls options into the general options to make sure the address is set right
+ if (tls_option === 'port' || tls_option === 'host' || tls_option === 'path' || tls_option === 'family') {
+ options[tls_option] = options.tls[tls_option];
+ }
+ }
+ if (stream) {
+ // The stream from the outside is used so no connection from this side is triggered but from the server this client should talk to
+ // Reconnect etc won't work with this. This requires monkey patching to work, so it is not officially supported
+ options.stream = stream;
+ this.address = '"Private stream"';
+ } else if (options.path) {
+ cnx_options.path = options.path;
+ this.address = options.path;
+ } else {
+ cnx_options.port = +options.port || 6379;
+ cnx_options.host = options.host || '127.0.0.1';
+ cnx_options.family = (!options.family && net.isIP(cnx_options.host)) || (options.family === 'IPv6' ? 6 : 4);
+ this.address = cnx_options.host + ':' + cnx_options.port;
+ }
+
+ this.connection_options = cnx_options;
+ this.connection_id = RedisClient.connection_id++;
+ this.connected = false;
+ this.ready = false;
+ if (options.socket_keepalive === undefined) {
+ options.socket_keepalive = true;
+ }
+ if (options.socket_initial_delay === undefined) {
+ options.socket_initial_delay = 0;
+ // set default to 0, which is aligned to https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay
+ }
+ for (var command in options.rename_commands) {
+ options.rename_commands[command.toLowerCase()] = options.rename_commands[command];
+ }
+ options.return_buffers = !!options.return_buffers;
+ options.detect_buffers = !!options.detect_buffers;
+ // Override the detect_buffers setting if return_buffers is active and print a warning
+ if (options.return_buffers && options.detect_buffers) {
+ self.warn('WARNING: You activated return_buffers and detect_buffers at the same time. The return value is always going to be a buffer.');
+ options.detect_buffers = false;
+ }
+ if (options.detect_buffers) {
+ // We only need to look at the arguments if we do not know what we have to return
+ this.handle_reply = handle_detect_buffers_reply;
+ }
+ this.should_buffer = false;
+ this.command_queue = new Queue(); // Holds sent commands to de-pipeline them
+ this.offline_queue = new Queue(); // Holds commands issued but not able to be sent
+ this.pipeline_queue = new Queue(); // Holds all pipelined commands
+ // ATTENTION: connect_timeout should change in v.3.0 so it does not count towards ending reconnection attempts after x seconds
+ // This should be done by the retry_strategy. Instead it should only be the timeout for connecting to redis
+ this.connect_timeout = +options.connect_timeout || 3600000; // 60 * 60 * 1000 ms
+ this.enable_offline_queue = options.enable_offline_queue === false ? false : true;
+ this.initialize_retry_vars();
+ this.pub_sub_mode = 0;
+ this.subscription_set = {};
+ this.monitoring = false;
+ this.message_buffers = false;
+ this.closing = false;
+ this.server_info = {};
+ this.auth_pass = options.auth_pass || options.password;
+ this.auth_user = options.auth_user || options.user;
+ this.selected_db = options.db; // Save the selected db here, used when reconnecting
+ this.fire_strings = true; // Determine if strings or buffers should be written to the stream
+ this.pipeline = false;
+ this.sub_commands_left = 0;
+ this.times_connected = 0;
+ this.buffers = options.return_buffers || options.detect_buffers;
+ this.options = options;
+ this.reply = 'ON'; // Returning replies is the default
+ this.create_stream();
+ // The listeners will not be attached right away, so let's print the deprecation message while the listener is attached
+ this.on('newListener', function (event) {
+ if ((event === 'message_buffer' || event === 'pmessage_buffer' || event === 'messageBuffer' || event === 'pmessageBuffer') && !this.buffers && !this.message_buffers) {
+ this.reply_parser.optionReturnBuffers = true;
+ this.message_buffers = true;
+ this.handle_reply = handle_detect_buffers_reply;
+ }
+ });
+}
+util.inherits(RedisClient, EventEmitter);
+
+RedisClient.connection_id = 0;
+
+function create_parser (self) {
+ return new Parser({
+ returnReply: function (data) {
+ self.return_reply(data);
+ },
+ returnError: function (err) {
+ // Return a ReplyError to indicate Redis returned an error
+ self.return_error(err);
+ },
+ returnFatalError: function (err) {
+ // Error out all fired commands. Otherwise they might rely on faulty data. We have to reconnect to get in a working state again
+ // Note: the execution order is important. First flush and emit, then create the stream
+ err.message += '. Please report this.';
+ self.ready = false;
+ self.flush_and_error({
+ message: 'Fatal error encountered. Command aborted.',
+ code: 'NR_FATAL'
+ }, {
+ error: err,
+ queues: ['command_queue']
+ });
+ self.emit('error', err);
+ self.create_stream();
+ },
+ returnBuffers: self.buffers || self.message_buffers,
+ stringNumbers: self.options.string_numbers || false
+ });
+}
+
+/******************************************************************************
+
+ All functions in here are internal besides the RedisClient constructor
+ and the exported functions. Don't rely on them as they will be private
+ functions in node_redis v.3
+
+******************************************************************************/
+
+// Attention: the function name "create_stream" should not be changed, as other libraries need this to mock the stream (e.g. fakeredis)
+RedisClient.prototype.create_stream = function () {
+ var self = this;
+
+ // Init parser
+ this.reply_parser = create_parser(this);
+
+ if (this.options.stream) {
+ // Only add the listeners once in case of a reconnect try (that won't work)
+ if (this.stream) {
+ return;
+ }
+ this.stream = this.options.stream;
+ } else {
+ // On a reconnect destroy the former stream and retry
+ if (this.stream) {
+ this.stream.removeAllListeners();
+ this.stream.destroy();
+ }
+
+ /* istanbul ignore if: travis does not work with stunnel atm. Therefore the tls tests are skipped on travis */
+ if (this.options.tls) {
+ this.stream = tls.connect(this.connection_options);
+ } else {
+ this.stream = net.createConnection(this.connection_options);
+ }
+ }
+
+ if (this.options.connect_timeout) {
+ this.stream.setTimeout(this.connect_timeout, function () {
+ // Note: This is only tested if a internet connection is established
+ self.retry_totaltime = self.connect_timeout;
+ self.connection_gone('timeout');
+ });
+ }
+
+ /* istanbul ignore next: travis does not work with stunnel atm. Therefore the tls tests are skipped on travis */
+ var connect_event = this.options.tls ? 'secureConnect' : 'connect';
+ this.stream.once(connect_event, function () {
+ this.removeAllListeners('timeout');
+ self.times_connected++;
+ self.on_connect();
+ });
+
+ this.stream.on('data', function (buffer_from_socket) {
+ // The buffer_from_socket.toString() has a significant impact on big chunks and therefore this should only be used if necessary
+ debug('Net read ' + self.address + ' id ' + self.connection_id); // + ': ' + buffer_from_socket.toString());
+ self.reply_parser.execute(buffer_from_socket);
+ });
+
+ this.stream.on('error', function (err) {
+ self.on_error(err);
+ });
+
+ this.stream.once('close', function (hadError) {
+ self.connection_gone('close');
+ });
+
+ this.stream.once('end', function () {
+ self.connection_gone('end');
+ });
+
+ this.stream.on('drain', function () {
+ self.drain();
+ });
+
+ this.stream.setNoDelay();
+
+ // Fire the command before redis is connected to be sure it's the first fired command
+ if (this.auth_pass !== undefined) {
+ this.ready = true;
+ // Fail silently as we might not be able to connect
+ this.auth(this.auth_pass, this.auth_user, function (err) {
+ if (err && err.code !== 'UNCERTAIN_STATE') {
+ self.emit('error', err);
+ }
+ });
+ this.ready = false;
+ }
+};
+
+RedisClient.prototype.handle_reply = function (reply, command) {
+ if (command === 'hgetall') {
+ reply = utils.reply_to_object(reply);
+ }
+ return reply;
+};
+
+RedisClient.prototype.cork = noop;
+RedisClient.prototype.uncork = noop;
+
+RedisClient.prototype.initialize_retry_vars = function () {
+ this.retry_timer = null;
+ this.retry_totaltime = 0;
+ this.retry_delay = 200;
+ this.retry_backoff = 1.7;
+ this.attempts = 1;
+};
+
+RedisClient.prototype.warn = function (msg) {
+ var self = this;
+ // Warn on the next tick. Otherwise no event listener can be added
+ // for warnings that are emitted in the redis client constructor
+ process.nextTick(function () {
+ if (self.listeners('warning').length !== 0) {
+ self.emit('warning', msg);
+ } else {
+ console.warn('node_redis:', msg);
+ }
+ });
+};
+
+// Flush provided queues, erroring any items with a callback first
+RedisClient.prototype.flush_and_error = function (error_attributes, options) {
+ options = options || {};
+ var aggregated_errors = [];
+ var queue_names = options.queues || ['command_queue', 'offline_queue']; // Flush the command_queue first to keep the order intakt
+ for (var i = 0; i < queue_names.length; i++) {
+ // If the command was fired it might have been processed so far
+ if (queue_names[i] === 'command_queue') {
+ error_attributes.message += ' It might have been processed.';
+ } else { // As the command_queue is flushed first, remove this for the offline queue
+ error_attributes.message = error_attributes.message.replace(' It might have been processed.', '');
+ }
+ // Don't flush everything from the queue
+ for (var command_obj = this[queue_names[i]].shift(); command_obj; command_obj = this[queue_names[i]].shift()) {
+ var err = new errorClasses.AbortError(error_attributes);
+ if (command_obj.error) {
+ err.stack = err.stack + command_obj.error.stack.replace(/^Error.*?\n/, '\n');
+ }
+ err.command = command_obj.command.toUpperCase();
+ if (command_obj.args && command_obj.args.length) {
+ err.args = command_obj.args;
+ }
+ if (options.error) {
+ err.origin = options.error;
+ }
+ if (typeof command_obj.callback === 'function') {
+ command_obj.callback(err);
+ } else {
+ aggregated_errors.push(err);
+ }
+ }
+ }
+ // Currently this would be a breaking change, therefore it's only emitted in debug_mode
+ if (exports.debug_mode && aggregated_errors.length) {
+ var error;
+ if (aggregated_errors.length === 1) {
+ error = aggregated_errors[0];
+ } else {
+ error_attributes.message = error_attributes.message.replace('It', 'They').replace(/command/i, '$&s');
+ error = new errorClasses.AggregateError(error_attributes);
+ error.errors = aggregated_errors;
+ }
+ this.emit('error', error);
+ }
+};
+
+RedisClient.prototype.on_error = function (err) {
+ if (this.closing) {
+ return;
+ }
+
+ err.message = 'Redis connection to ' + this.address + ' failed - ' + err.message;
+ debug(err.message);
+ this.connected = false;
+ this.ready = false;
+
+ // Only emit the error if the retry_strategy option is not set
+ if (!this.options.retry_strategy) {
+ this.emit('error', err);
+ }
+ // 'error' events get turned into exceptions if they aren't listened for. If the user handled this error
+ // then we should try to reconnect.
+ this.connection_gone('error', err);
+};
+
+RedisClient.prototype.on_connect = function () {
+ debug('Stream connected ' + this.address + ' id ' + this.connection_id);
+
+ this.connected = true;
+ this.ready = false;
+ this.emitted_end = false;
+ this.stream.setKeepAlive(this.options.socket_keepalive, this.options.socket_initial_delay);
+ this.stream.setTimeout(0);
+
+ this.emit('connect');
+ this.initialize_retry_vars();
+
+ if (this.options.no_ready_check) {
+ this.on_ready();
+ } else {
+ this.ready_check();
+ }
+};
+
+RedisClient.prototype.on_ready = function () {
+ var self = this;
+
+ debug('on_ready called ' + this.address + ' id ' + this.connection_id);
+ this.ready = true;
+
+ this.cork = function () {
+ self.pipeline = true;
+ if (self.stream.cork) {
+ self.stream.cork();
+ }
+ };
+ this.uncork = function () {
+ if (self.fire_strings) {
+ self.write_strings();
+ } else {
+ self.write_buffers();
+ }
+ self.pipeline = false;
+ self.fire_strings = true;
+ if (self.stream.uncork) {
+ // TODO: Consider using next tick here. See https://github.com/NodeRedis/node_redis/issues/1033
+ self.stream.uncork();
+ }
+ };
+
+ // Restore modal commands from previous connection. The order of the commands is important
+ if (this.selected_db !== undefined) {
+ this.internal_send_command(new Command('select', [this.selected_db]));
+ }
+ if (this.monitoring) { // Monitor has to be fired before pub sub commands
+ this.internal_send_command(new Command('monitor', []));
+ }
+ var callback_count = Object.keys(this.subscription_set).length;
+ if (!this.options.disable_resubscribing && callback_count) {
+ // only emit 'ready' when all subscriptions were made again
+ // TODO: Remove the countdown for ready here. This is not coherent with all other modes and should therefore not be handled special
+ // We know we are ready as soon as all commands were fired
+ var callback = function () {
+ callback_count--;
+ if (callback_count === 0) {
+ self.emit('ready');
+ }
+ };
+ debug('Sending pub/sub on_ready commands');
+ for (var key in this.subscription_set) {
+ var command = key.slice(0, key.indexOf('_'));
+ var args = this.subscription_set[key];
+ this[command]([args], callback);
+ }
+ this.send_offline_queue();
+ return;
+ }
+ this.send_offline_queue();
+ this.emit('ready');
+};
+
+RedisClient.prototype.on_info_cmd = function (err, res) {
+ if (err) {
+ if (err.message === "ERR unknown command 'info'") {
+ this.on_ready();
+ return;
+ }
+ err.message = 'Ready check failed: ' + err.message;
+ this.emit('error', err);
+ return;
+ }
+
+ /* istanbul ignore if: some servers might not respond with any info data. This is just a safety check that is difficult to test */
+ if (!res) {
+ debug('The info command returned without any data.');
+ this.on_ready();
+ return;
+ }
+
+ if (!this.server_info.loading || this.server_info.loading === '0') {
+ // If the master_link_status exists but the link is not up, try again after 50 ms
+ if (this.server_info.master_link_status && this.server_info.master_link_status !== 'up') {
+ this.server_info.loading_eta_seconds = 0.05;
+ } else {
+ // Eta loading should change
+ debug('Redis server ready.');
+ this.on_ready();
+ return;
+ }
+ }
+
+ var retry_time = +this.server_info.loading_eta_seconds * 1000;
+ if (retry_time > 1000) {
+ retry_time = 1000;
+ }
+ debug('Redis server still loading, trying again in ' + retry_time);
+ setTimeout(function (self) {
+ self.ready_check();
+ }, retry_time, this);
+};
+
+RedisClient.prototype.ready_check = function () {
+ var self = this;
+ debug('Checking server ready state...');
+ // Always fire this info command as first command even if other commands are already queued up
+ this.ready = true;
+ this.info(function (err, res) {
+ self.on_info_cmd(err, res);
+ });
+ this.ready = false;
+};
+
+RedisClient.prototype.send_offline_queue = function () {
+ for (var command_obj = this.offline_queue.shift(); command_obj; command_obj = this.offline_queue.shift()) {
+ debug('Sending offline command: ' + command_obj.command);
+ this.internal_send_command(command_obj);
+ }
+ this.drain();
+};
+
+var retry_connection = function (self, error) {
+ debug('Retrying connection...');
+
+ var reconnect_params = {
+ delay: self.retry_delay,
+ attempt: self.attempts,
+ error: error
+ };
+ if (self.options.camel_case) {
+ reconnect_params.totalRetryTime = self.retry_totaltime;
+ reconnect_params.timesConnected = self.times_connected;
+ } else {
+ reconnect_params.total_retry_time = self.retry_totaltime;
+ reconnect_params.times_connected = self.times_connected;
+ }
+ self.emit('reconnecting', reconnect_params);
+
+ self.retry_totaltime += self.retry_delay;
+ self.attempts += 1;
+ self.retry_delay = Math.round(self.retry_delay * self.retry_backoff);
+ self.create_stream();
+ self.retry_timer = null;
+};
+
+RedisClient.prototype.connection_gone = function (why, error) {
+ // If a retry is already in progress, just let that happen
+ if (this.retry_timer) {
+ return;
+ }
+ error = error || null;
+
+ debug('Redis connection is gone from ' + why + ' event.');
+ this.connected = false;
+ this.ready = false;
+ // Deactivate cork to work with the offline queue
+ this.cork = noop;
+ this.uncork = noop;
+ this.pipeline = false;
+ this.pub_sub_mode = 0;
+
+ // since we are collapsing end and close, users don't expect to be called twice
+ if (!this.emitted_end) {
+ this.emit('end');
+ this.emitted_end = true;
+ }
+
+ // If this is a requested shutdown, then don't retry
+ if (this.closing) {
+ debug('Connection ended by quit / end command, not retrying.');
+ this.flush_and_error({
+ message: 'Stream connection ended and command aborted.',
+ code: 'NR_CLOSED'
+ }, {
+ error: error
+ });
+ return;
+ }
+
+ if (typeof this.options.retry_strategy === 'function') {
+ var retry_params = {
+ attempt: this.attempts,
+ error: error
+ };
+ if (this.options.camel_case) {
+ retry_params.totalRetryTime = this.retry_totaltime;
+ retry_params.timesConnected = this.times_connected;
+ } else {
+ retry_params.total_retry_time = this.retry_totaltime;
+ retry_params.times_connected = this.times_connected;
+ }
+ this.retry_delay = this.options.retry_strategy(retry_params);
+ if (typeof this.retry_delay !== 'number') {
+ // Pass individual error through
+ if (this.retry_delay instanceof Error) {
+ error = this.retry_delay;
+ }
+
+ var errorMessage = 'Redis connection in broken state: retry aborted.';
+
+ this.flush_and_error({
+ message: errorMessage,
+ code: 'CONNECTION_BROKEN',
+ }, {
+ error: error
+ });
+ var retryError = new Error(errorMessage);
+ retryError.code = 'CONNECTION_BROKEN';
+ if (error) {
+ retryError.origin = error;
+ }
+ this.end(false);
+ this.emit('error', retryError);
+ return;
+ }
+ }
+
+ if (this.retry_totaltime >= this.connect_timeout) {
+ var message = 'Redis connection in broken state: connection timeout exceeded.';
+ this.flush_and_error({
+ message: message,
+ code: 'CONNECTION_BROKEN',
+ }, {
+ error: error
+ });
+ var err = new Error(message);
+ err.code = 'CONNECTION_BROKEN';
+ if (error) {
+ err.origin = error;
+ }
+ this.end(false);
+ this.emit('error', err);
+ return;
+ }
+
+ // Retry commands after a reconnect instead of throwing an error. Use this with caution
+ if (this.options.retry_unfulfilled_commands) {
+ this.offline_queue.unshift.apply(this.offline_queue, this.command_queue.toArray());
+ this.command_queue.clear();
+ } else if (this.command_queue.length !== 0) {
+ this.flush_and_error({
+ message: 'Redis connection lost and command aborted.',
+ code: 'UNCERTAIN_STATE'
+ }, {
+ error: error,
+ queues: ['command_queue']
+ });
+ }
+
+ if (this.retry_totaltime + this.retry_delay > this.connect_timeout) {
+ // Do not exceed the maximum
+ this.retry_delay = this.connect_timeout - this.retry_totaltime;
+ }
+
+ debug('Retry connection in ' + this.retry_delay + ' ms');
+ this.retry_timer = setTimeout(retry_connection, this.retry_delay, this, error);
+};
+
+RedisClient.prototype.return_error = function (err) {
+ var command_obj = this.command_queue.shift();
+ if (command_obj.error) {
+ err.stack = command_obj.error.stack.replace(/^Error.*?\n/, 'ReplyError: ' + err.message + '\n');
+ }
+ err.command = command_obj.command.toUpperCase();
+ if (command_obj.args && command_obj.args.length) {
+ err.args = command_obj.args;
+ }
+
+ // Count down pub sub mode if in entering modus
+ if (this.pub_sub_mode > 1) {
+ this.pub_sub_mode--;
+ }
+
+ var match = err.message.match(utils.err_code);
+ // LUA script could return user errors that don't behave like all other errors!
+ if (match) {
+ err.code = match[1];
+ }
+
+ utils.callback_or_emit(this, command_obj.callback, err);
+};
+
+RedisClient.prototype.drain = function () {
+ this.should_buffer = false;
+};
+
+function normal_reply (self, reply) {
+ var command_obj = self.command_queue.shift();
+ if (typeof command_obj.callback === 'function') {
+ if (command_obj.command !== 'exec') {
+ reply = self.handle_reply(reply, command_obj.command, command_obj.buffer_args);
+ }
+ command_obj.callback(null, reply);
+ } else {
+ debug('No callback for reply');
+ }
+}
+
+function subscribe_unsubscribe (self, reply, type) {
+ // Subscribe commands take an optional callback and also emit an event, but only the _last_ response is included in the callback
+ // The pub sub commands return each argument in a separate return value and have to be handled that way
+ var command_obj = self.command_queue.get(0);
+ var buffer = self.options.return_buffers || self.options.detect_buffers && command_obj.buffer_args;
+ var channel = (buffer || reply[1] === null) ? reply[1] : reply[1].toString();
+ var count = +reply[2]; // Return the channel counter as number no matter if `string_numbers` is activated or not
+ debug(type, channel);
+
+ // Emit first, then return the callback
+ if (channel !== null) { // Do not emit or "unsubscribe" something if there was no channel to unsubscribe from
+ self.emit(type, channel, count);
+ if (type === 'subscribe' || type === 'psubscribe') {
+ self.subscription_set[type + '_' + channel] = channel;
+ } else {
+ type = type === 'unsubscribe' ? 'subscribe' : 'psubscribe'; // Make types consistent
+ delete self.subscription_set[type + '_' + channel];
+ }
+ }
+
+ if (command_obj.args.length === 1 || self.sub_commands_left === 1 || command_obj.args.length === 0 && (count === 0 || channel === null)) {
+ if (count === 0) { // unsubscribed from all channels
+ var running_command;
+ var i = 1;
+ self.pub_sub_mode = 0; // Deactivating pub sub mode
+ // This should be a rare case and therefore handling it this way should be good performance wise for the general case
+ while (running_command = self.command_queue.get(i)) {
+ if (SUBSCRIBE_COMMANDS[running_command.command]) {
+ self.pub_sub_mode = i; // Entering pub sub mode again
+ break;
+ }
+ i++;
+ }
+ }
+ self.command_queue.shift();
+ if (typeof command_obj.callback === 'function') {
+ // TODO: The current return value is pretty useless.
+ // Evaluate to change this in v.4 to return all subscribed / unsubscribed channels in an array including the number of channels subscribed too
+ command_obj.callback(null, channel);
+ }
+ self.sub_commands_left = 0;
+ } else {
+ if (self.sub_commands_left !== 0) {
+ self.sub_commands_left--;
+ } else {
+ self.sub_commands_left = command_obj.args.length ? command_obj.args.length - 1 : count;
+ }
+ }
+}
+
+function return_pub_sub (self, reply) {
+ var type = reply[0].toString();
+ if (type === 'message') { // channel, message
+ if (!self.options.return_buffers || self.message_buffers) { // backwards compatible. Refactor this in v.4 to always return a string on the normal emitter
+ self.emit('message', reply[1].toString(), reply[2].toString());
+ self.emit('message_buffer', reply[1], reply[2]);
+ self.emit('messageBuffer', reply[1], reply[2]);
+ } else {
+ self.emit('message', reply[1], reply[2]);
+ }
+ } else if (type === 'pmessage') { // pattern, channel, message
+ if (!self.options.return_buffers || self.message_buffers) { // backwards compatible. Refactor this in v.4 to always return a string on the normal emitter
+ self.emit('pmessage', reply[1].toString(), reply[2].toString(), reply[3].toString());
+ self.emit('pmessage_buffer', reply[1], reply[2], reply[3]);
+ self.emit('pmessageBuffer', reply[1], reply[2], reply[3]);
+ } else {
+ self.emit('pmessage', reply[1], reply[2], reply[3]);
+ }
+ } else {
+ subscribe_unsubscribe(self, reply, type);
+ }
+}
+
+RedisClient.prototype.return_reply = function (reply) {
+ if (this.monitoring) {
+ var replyStr;
+ if (this.buffers && Buffer.isBuffer(reply)) {
+ replyStr = reply.toString();
+ } else {
+ replyStr = reply;
+ }
+ // If in monitor mode, all normal commands are still working and we only want to emit the streamlined commands
+ if (typeof replyStr === 'string' && utils.monitor_regex.test(replyStr)) {
+ var timestamp = replyStr.slice(0, replyStr.indexOf(' '));
+ var args = replyStr.slice(replyStr.indexOf('"') + 1, -1).split('" "').map(function (elem) {
+ return elem.replace(/\\"/g, '"');
+ });
+ this.emit('monitor', timestamp, args, replyStr);
+ return;
+ }
+ }
+ if (this.pub_sub_mode === 0) {
+ normal_reply(this, reply);
+ } else if (this.pub_sub_mode !== 1) {
+ this.pub_sub_mode--;
+ normal_reply(this, reply);
+ } else if (!(reply instanceof Array) || reply.length <= 2) {
+ // Only PING and QUIT are allowed in this context besides the pub sub commands
+ // Ping replies with ['pong', null|value] and quit with 'OK'
+ normal_reply(this, reply);
+ } else {
+ return_pub_sub(this, reply);
+ }
+};
+
+function handle_offline_command (self, command_obj) {
+ var command = command_obj.command;
+ var err, msg;
+ if (self.closing || !self.enable_offline_queue) {
+ command = command.toUpperCase();
+ if (!self.closing) {
+ if (self.stream.writable) {
+ msg = 'The connection is not yet established and the offline queue is deactivated.';
+ } else {
+ msg = 'Stream not writeable.';
+ }
+ } else {
+ msg = 'The connection is already closed.';
+ }
+ err = new errorClasses.AbortError({
+ message: command + " can't be processed. " + msg,
+ code: 'NR_CLOSED',
+ command: command
+ });
+ if (command_obj.args.length) {
+ err.args = command_obj.args;
+ }
+ utils.reply_in_order(self, command_obj.callback, err);
+ } else {
+ debug('Queueing ' + command + ' for next server connection.');
+ self.offline_queue.push(command_obj);
+ }
+ self.should_buffer = true;
+}
+
+// Do not call internal_send_command directly, if you are not absolutly certain it handles everything properly
+// e.g. monitor / info does not work with internal_send_command only
+RedisClient.prototype.internal_send_command = function (command_obj) {
+ var arg, prefix_keys;
+ var i = 0;
+ var command_str = '';
+ var args = command_obj.args;
+ var command = command_obj.command;
+ var len = args.length;
+ var big_data = false;
+ var args_copy = new Array(len);
+
+ if (process.domain && command_obj.callback) {
+ command_obj.callback = process.domain.bind(command_obj.callback);
+ }
+
+ if (this.ready === false || this.stream.writable === false) {
+ // Handle offline commands right away
+ handle_offline_command(this, command_obj);
+ return false; // Indicate buffering
+ }
+
+ for (i = 0; i < len; i += 1) {
+ if (typeof args[i] === 'string') {
+ // 30000 seemed to be a good value to switch to buffers after testing and checking the pros and cons
+ if (args[i].length > 30000) {
+ big_data = true;
+ args_copy[i] = Buffer.from(args[i], 'utf8');
+ } else {
+ args_copy[i] = args[i];
+ }
+ } else if (typeof args[i] === 'object') { // Checking for object instead of Buffer.isBuffer helps us finding data types that we can't handle properly
+ if (args[i] instanceof Date) { // Accept dates as valid input
+ args_copy[i] = args[i].toString();
+ } else if (Buffer.isBuffer(args[i])) {
+ args_copy[i] = args[i];
+ command_obj.buffer_args = true;
+ big_data = true;
+ } else {
+ var invalidArgError = new Error(
+ 'node_redis: The ' + command.toUpperCase() + ' command contains a invalid argument type.\n' +
+ 'Only strings, dates and buffers are accepted. Please update your code to use valid argument types.'
+ );
+ invalidArgError.command = command_obj.command.toUpperCase();
+ if (command_obj.args && command_obj.args.length) {
+ invalidArgError.args = command_obj.args;
+ }
+ if (command_obj.callback) {
+ command_obj.callback(invalidArgError);
+ return false;
+ }
+ throw invalidArgError;
+ }
+ } else if (typeof args[i] === 'undefined') {
+ var undefinedArgError = new Error(
+ 'node_redis: The ' + command.toUpperCase() + ' command contains a invalid argument type of "undefined".\n' +
+ 'Only strings, dates and buffers are accepted. Please update your code to use valid argument types.'
+ );
+ undefinedArgError.command = command_obj.command.toUpperCase();
+ if (command_obj.args && command_obj.args.length) {
+ undefinedArgError.args = command_obj.args;
+ }
+ // there is always a callback in this scenario
+ command_obj.callback(undefinedArgError);
+ return false;
+ } else {
+ // Seems like numbers are converted fast using string concatenation
+ args_copy[i] = '' + args[i];
+ }
+ }
+
+ if (this.options.prefix) {
+ prefix_keys = commands.getKeyIndexes(command, args_copy);
+ for (i = prefix_keys.pop(); i !== undefined; i = prefix_keys.pop()) {
+ args_copy[i] = this.options.prefix + args_copy[i];
+ }
+ }
+ if (this.options.rename_commands && this.options.rename_commands[command]) {
+ command = this.options.rename_commands[command];
+ }
+ // Always use 'Multi bulk commands', but if passed any Buffer args, then do multiple writes, one for each arg.
+ // This means that using Buffers in commands is going to be slower, so use Strings if you don't already have a Buffer.
+ command_str = '*' + (len + 1) + '\r\n$' + command.length + '\r\n' + command + '\r\n';
+
+ if (big_data === false) { // Build up a string and send entire command in one write
+ for (i = 0; i < len; i += 1) {
+ arg = args_copy[i];
+ command_str += '$' + Buffer.byteLength(arg) + '\r\n' + arg + '\r\n';
+ }
+ debug('Send ' + this.address + ' id ' + this.connection_id + ': ' + command_str);
+ this.write(command_str);
+ } else {
+ debug('Send command (' + command_str + ') has Buffer arguments');
+ this.fire_strings = false;
+ this.write(command_str);
+
+ for (i = 0; i < len; i += 1) {
+ arg = args_copy[i];
+ if (typeof arg === 'string') {
+ this.write('$' + Buffer.byteLength(arg) + '\r\n' + arg + '\r\n');
+ } else { // buffer
+ this.write('$' + arg.length + '\r\n');
+ this.write(arg);
+ this.write('\r\n');
+ }
+ debug('send_command: buffer send ' + arg.length + ' bytes');
+ }
+ }
+ if (command_obj.call_on_write) {
+ command_obj.call_on_write();
+ }
+ // Handle `CLIENT REPLY ON|OFF|SKIP`
+ // This has to be checked after call_on_write
+ /* istanbul ignore else: TODO: Remove this as soon as we test Redis 3.2 on travis */
+ if (this.reply === 'ON') {
+ this.command_queue.push(command_obj);
+ } else {
+ // Do not expect a reply
+ // Does this work in combination with the pub sub mode?
+ if (command_obj.callback) {
+ utils.reply_in_order(this, command_obj.callback, null, undefined, this.command_queue);
+ }
+ if (this.reply === 'SKIP') {
+ this.reply = 'SKIP_ONE_MORE';
+ } else if (this.reply === 'SKIP_ONE_MORE') {
+ this.reply = 'ON';
+ }
+ }
+ return !this.should_buffer;
+};
+
+RedisClient.prototype.write_strings = function () {
+ var str = '';
+ for (var command = this.pipeline_queue.shift(); command; command = this.pipeline_queue.shift()) {
+ // Write to stream if the string is bigger than 4mb. The biggest string may be Math.pow(2, 28) - 15 chars long
+ if (str.length + command.length > 4 * 1024 * 1024) {
+ this.should_buffer = !this.stream.write(str);
+ str = '';
+ }
+ str += command;
+ }
+ if (str !== '') {
+ this.should_buffer = !this.stream.write(str);
+ }
+};
+
+RedisClient.prototype.write_buffers = function () {
+ for (var command = this.pipeline_queue.shift(); command; command = this.pipeline_queue.shift()) {
+ this.should_buffer = !this.stream.write(command);
+ }
+};
+
+RedisClient.prototype.write = function (data) {
+ if (this.pipeline === false) {
+ this.should_buffer = !this.stream.write(data);
+ return;
+ }
+ this.pipeline_queue.push(data);
+};
+
+Object.defineProperty(exports, 'debugMode', {
+ get: function () {
+ return this.debug_mode;
+ },
+ set: function (val) {
+ this.debug_mode = val;
+ }
+});
+
+// Don't officially expose the command_queue directly but only the length as read only variable
+Object.defineProperty(RedisClient.prototype, 'command_queue_length', {
+ get: function () {
+ return this.command_queue.length;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'offline_queue_length', {
+ get: function () {
+ return this.offline_queue.length;
+ }
+});
+
+// Add support for camelCase by adding read only properties to the client
+// All known exposed snake_case variables are added here
+Object.defineProperty(RedisClient.prototype, 'retryDelay', {
+ get: function () {
+ return this.retry_delay;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'retryBackoff', {
+ get: function () {
+ return this.retry_backoff;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'commandQueueLength', {
+ get: function () {
+ return this.command_queue.length;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'offlineQueueLength', {
+ get: function () {
+ return this.offline_queue.length;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'shouldBuffer', {
+ get: function () {
+ return this.should_buffer;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'connectionId', {
+ get: function () {
+ return this.connection_id;
+ }
+});
+
+Object.defineProperty(RedisClient.prototype, 'serverInfo', {
+ get: function () {
+ return this.server_info;
+ }
+});
+
+exports.createClient = function () {
+ return new RedisClient(unifyOptions.apply(null, arguments));
+};
+exports.RedisClient = RedisClient;
+exports.print = utils.print;
+exports.Multi = require('./lib/multi');
+exports.AbortError = errorClasses.AbortError;
+exports.RedisError = RedisErrors.RedisError;
+exports.ParserError = RedisErrors.ParserError;
+exports.ReplyError = RedisErrors.ReplyError;
+exports.AggregateError = errorClasses.AggregateError;
+
+// Add all redis commands / node_redis api to the client
+require('./lib/individualCommands');
+require('./lib/extendedApi');
+
+//enables adding new commands (for modules and new commands)
+exports.addCommand = exports.add_command = require('./lib/commands');
diff --git a/node_modules/redis/heroku/node_modules/redis/lib/command.js b/node_modules/redis/heroku/node_modules/redis/lib/command.js
new file mode 100644
index 0000000..717115c
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/lib/command.js
@@ -0,0 +1,16 @@
+'use strict';
+
+var betterStackTraces = /development/i.test(process.env.NODE_ENV) || /\bredis\b/i.test(process.env.NODE_DEBUG);
+
+function Command (command, args, callback, call_on_write) {
+ this.command = command;
+ this.args = args;
+ this.buffer_args = false;
+ this.callback = callback;
+ this.call_on_write = call_on_write;
+ if (betterStackTraces) {
+ this.error = new Error();
+ }
+}
+
+module.exports = Command;
diff --git a/node_modules/redis/heroku/node_modules/redis/lib/commands.js b/node_modules/redis/heroku/node_modules/redis/lib/commands.js
new file mode 100644
index 0000000..a3b5189
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/lib/commands.js
@@ -0,0 +1,105 @@
+'use strict';
+
+var commands = require('redis-commands');
+var Multi = require('./multi');
+var RedisClient = require('../').RedisClient;
+var Command = require('./command');
+
+var addCommand = function (command) {
+ // Some rare Redis commands use special characters in their command name
+ // Convert those to a underscore to prevent using invalid function names
+ var commandName = command.replace(/(?:^([0-9])|[^a-zA-Z0-9_$])/g, '_$1');
+
+ // Do not override existing functions
+ if (!RedisClient.prototype[command]) {
+ RedisClient.prototype[command.toUpperCase()] = RedisClient.prototype[command] = function () {
+ var arr;
+ var len = arguments.length;
+ var callback;
+ var i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ if (len === 2) {
+ callback = arguments[1];
+ }
+ } else if (len > 1 && Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else {
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ return this.internal_send_command(new Command(command, arr, callback));
+ };
+ // Alias special function names (e.g. NR.RUN becomes NR_RUN and nr_run)
+ if (commandName !== command) {
+ RedisClient.prototype[commandName.toUpperCase()] = RedisClient.prototype[commandName] = RedisClient.prototype[command];
+ }
+ Object.defineProperty(RedisClient.prototype[command], 'name', {
+ value: commandName
+ });
+ }
+
+ // Do not override existing functions
+ if (!Multi.prototype[command]) {
+ Multi.prototype[command.toUpperCase()] = Multi.prototype[command] = function () {
+ var arr;
+ var len = arguments.length;
+ var callback;
+ var i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ if (len === 2) {
+ callback = arguments[1];
+ }
+ } else if (len > 1 && Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else {
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ this.queue.push(new Command(command, arr, callback));
+ return this;
+ };
+ // Alias special function names (e.g. NR.RUN becomes NR_RUN and nr_run)
+ if (commandName !== command) {
+ Multi.prototype[commandName.toUpperCase()] = Multi.prototype[commandName] = Multi.prototype[command];
+ }
+ Object.defineProperty(Multi.prototype[command], 'name', {
+ value: commandName
+ });
+ }
+};
+
+commands.list.forEach(addCommand);
+
+module.exports = addCommand;
diff --git a/node_modules/redis/heroku/node_modules/redis/lib/createClient.js b/node_modules/redis/heroku/node_modules/redis/lib/createClient.js
new file mode 100644
index 0000000..b03bb57
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/lib/createClient.js
@@ -0,0 +1,88 @@
+'use strict';
+
+var utils = require('./utils');
+var URL = require('url');
+
+module.exports = function createClient (port_arg, host_arg, options) {
+
+ if (typeof port_arg === 'number' || typeof port_arg === 'string' && /^\d+$/.test(port_arg)) {
+
+ var host;
+ if (typeof host_arg === 'string') {
+ host = host_arg;
+ } else {
+ if (options && host_arg) {
+ throw new TypeError('Unknown type of connection in createClient()');
+ }
+ options = options || host_arg;
+ }
+ options = utils.clone(options);
+ options.host = host || options.host;
+ options.port = port_arg;
+
+ } else if (typeof port_arg === 'string' || port_arg && port_arg.url) {
+
+ options = utils.clone(port_arg.url ? port_arg : host_arg || options);
+ var url = port_arg.url || port_arg;
+ var parsed = URL.parse(url, true, true);
+
+ // [redis:]//[[user][:password]@][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]
+ if (parsed.slashes) { // We require slashes
+ if (parsed.auth) {
+ var columnIndex = parsed.auth.indexOf(':');
+ options.password = parsed.auth.slice(columnIndex + 1);
+ if (columnIndex > 0) {
+ options.user = parsed.auth.slice(0, columnIndex);
+ }
+ }
+ if (parsed.protocol) {
+ if (parsed.protocol === 'rediss:') {
+ options.tls = options.tls || {};
+ } else if (parsed.protocol !== 'redis:') {
+ console.warn('node_redis: WARNING: You passed "' + parsed.protocol.substring(0, parsed.protocol.length - 1) + '" as protocol instead of the "redis" protocol!');
+ }
+ }
+ if (parsed.pathname && parsed.pathname !== '/') {
+ options.db = parsed.pathname.substr(1);
+ }
+ if (parsed.hostname) {
+ options.host = parsed.hostname;
+ }
+ if (parsed.port) {
+ options.port = parsed.port;
+ }
+ if (parsed.search !== '') {
+ var elem;
+ for (elem in parsed.query) {
+ // If options are passed twice, only the parsed options will be used
+ if (elem in options) {
+ if (options[elem] === parsed.query[elem]) {
+ console.warn('node_redis: WARNING: You passed the ' + elem + ' option twice!');
+ } else {
+ throw new RangeError('The ' + elem + ' option is added twice and does not match');
+ }
+ }
+ options[elem] = parsed.query[elem];
+ }
+ }
+ } else if (parsed.hostname) {
+ throw new RangeError('The redis url must begin with slashes "//" or contain slashes after the redis protocol');
+ } else {
+ options.path = url;
+ }
+
+ } else if (typeof port_arg === 'object' || port_arg === undefined) {
+ options = utils.clone(port_arg || options);
+ options.host = options.host || host_arg;
+
+ if (port_arg && arguments.length !== 1) {
+ throw new TypeError('Too many arguments passed to createClient. Please only pass the options object');
+ }
+ }
+
+ if (!options) {
+ throw new TypeError('Unknown type of connection in createClient()');
+ }
+
+ return options;
+};
diff --git a/node_modules/redis/heroku/node_modules/redis/lib/customErrors.js b/node_modules/redis/heroku/node_modules/redis/lib/customErrors.js
new file mode 100644
index 0000000..2483db0
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/lib/customErrors.js
@@ -0,0 +1,58 @@
+'use strict';
+
+var util = require('util');
+var assert = require('assert');
+var RedisError = require('redis-errors').RedisError;
+var ADD_STACKTRACE = false;
+
+function AbortError (obj, stack) {
+ assert(obj, 'The options argument is required');
+ assert.strictEqual(typeof obj, 'object', 'The options argument has to be of type object');
+
+ Object.defineProperty(this, 'message', {
+ value: obj.message || '',
+ configurable: true,
+ writable: true
+ });
+ if (stack || stack === undefined) {
+ Error.captureStackTrace(this, AbortError);
+ }
+ for (var keys = Object.keys(obj), key = keys.pop(); key; key = keys.pop()) {
+ this[key] = obj[key];
+ }
+}
+
+function AggregateError (obj) {
+ assert(obj, 'The options argument is required');
+ assert.strictEqual(typeof obj, 'object', 'The options argument has to be of type object');
+
+ AbortError.call(this, obj, ADD_STACKTRACE);
+ Object.defineProperty(this, 'message', {
+ value: obj.message || '',
+ configurable: true,
+ writable: true
+ });
+ Error.captureStackTrace(this, AggregateError);
+ for (var keys = Object.keys(obj), key = keys.pop(); key; key = keys.pop()) {
+ this[key] = obj[key];
+ }
+}
+
+util.inherits(AbortError, RedisError);
+util.inherits(AggregateError, AbortError);
+
+Object.defineProperty(AbortError.prototype, 'name', {
+ value: 'AbortError',
+ configurable: true,
+ writable: true
+});
+Object.defineProperty(AggregateError.prototype, 'name', {
+ value: 'AggregateError',
+ configurable: true,
+ writable: true
+});
+
+module.exports = {
+ AbortError: AbortError,
+ AggregateError: AggregateError
+};
diff --git a/node_modules/redis/heroku/node_modules/redis/lib/debug.js b/node_modules/redis/heroku/node_modules/redis/lib/debug.js
new file mode 100644
index 0000000..d69c1ea
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/lib/debug.js
@@ -0,0 +1,13 @@
+'use strict';
+
+var index = require('../');
+
+function debug () {
+ if (index.debug_mode) {
+ var data = Array.prototype.slice.call(arguments);
+ data.unshift(new Date().toISOString());
+ console.error.apply(null, data);
+ }
+}
+
+module.exports = debug;
diff --git a/node_modules/redis/heroku/node_modules/redis/lib/extendedApi.js b/node_modules/redis/heroku/node_modules/redis/lib/extendedApi.js
new file mode 100644
index 0000000..27ed421
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/lib/extendedApi.js
@@ -0,0 +1,113 @@
+'use strict';
+
+var utils = require('./utils');
+var debug = require('./debug');
+var RedisClient = require('../').RedisClient;
+var Command = require('./command');
+var noop = function () {};
+
+/**********************************************
+All documented and exposed API belongs in here
+**********************************************/
+
+// Redirect calls to the appropriate function and use to send arbitrary / not supported commands
+RedisClient.prototype.send_command = RedisClient.prototype.sendCommand = function (command, args, callback) {
+ // Throw to fail early instead of relying in order in this case
+ if (typeof command !== 'string') {
+ throw new TypeError('Wrong input type "' + (command !== null && command !== undefined ? command.constructor.name : command) + '" for command name');
+ }
+ command = command.toLowerCase();
+ if (!Array.isArray(args)) {
+ if (args === undefined || args === null) {
+ args = [];
+ } else if (typeof args === 'function' && callback === undefined) {
+ callback = args;
+ args = [];
+ } else {
+ throw new TypeError('Wrong input type "' + args.constructor.name + '" for args');
+ }
+ }
+ if (typeof callback !== 'function' && callback !== undefined) {
+ throw new TypeError('Wrong input type "' + (callback !== null ? callback.constructor.name : 'null') + '" for callback function');
+ }
+
+ // Using the raw multi command is only possible with this function
+ // If the command is not yet added to the client, the internal function should be called right away
+ // Otherwise we need to redirect the calls to make sure the internal functions don't get skipped
+ // The internal functions could actually be used for any non hooked function
+ // but this might change from time to time and at the moment there's no good way to distinguish them
+ // from each other, so let's just do it do it this way for the time being
+ if (command === 'multi' || typeof this[command] !== 'function') {
+ return this.internal_send_command(new Command(command, args, callback));
+ }
+ if (typeof callback === 'function') {
+ args = args.concat([callback]); // Prevent manipulating the input array
+ }
+ return this[command].apply(this, args);
+};
+
+RedisClient.prototype.end = function (flush) {
+ // Flush queue if wanted
+ if (flush) {
+ this.flush_and_error({
+ message: 'Connection forcefully ended and command aborted.',
+ code: 'NR_CLOSED'
+ });
+ } else if (arguments.length === 0) {
+ this.warn(
+ 'Using .end() without the flush parameter is deprecated and throws from v.3.0.0 on.\n' +
+ 'Please check the doku (https://github.com/NodeRedis/node_redis) and explictly use flush.'
+ );
+ }
+ // Clear retry_timer
+ if (this.retry_timer) {
+ clearTimeout(this.retry_timer);
+ this.retry_timer = null;
+ }
+ this.stream.removeAllListeners();
+ this.stream.on('error', noop);
+ this.connected = false;
+ this.ready = false;
+ this.closing = true;
+ return this.stream.destroySoon();
+};
+
+RedisClient.prototype.unref = function () {
+ if (this.connected) {
+ debug("Unref'ing the socket connection");
+ this.stream.unref();
+ } else {
+ debug('Not connected yet, will unref later');
+ this.once('connect', function () {
+ this.unref();
+ });
+ }
+};
+
+RedisClient.prototype.duplicate = function (options, callback) {
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+ var existing_options = utils.clone(this.options);
+ options = utils.clone(options);
+ for (var elem in options) {
+ existing_options[elem] = options[elem];
+ }
+ var client = new RedisClient(existing_options);
+ client.selected_db = options.db || this.selected_db;
+ if (typeof callback === 'function') {
+ var ready_listener = function () {
+ callback(null, client);
+ client.removeAllListeners(error_listener);
+ };
+ var error_listener = function (err) {
+ callback(err);
+ client.end(true);
+ };
+ client.once('ready', ready_listener);
+ client.once('error', error_listener);
+ return;
+ }
+ return client;
+};
diff --git a/node_modules/redis/heroku/node_modules/redis/lib/individualCommands.js b/node_modules/redis/heroku/node_modules/redis/lib/individualCommands.js
new file mode 100644
index 0000000..c3ea3da
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/lib/individualCommands.js
@@ -0,0 +1,629 @@
+'use strict';
+
+var utils = require('./utils');
+var debug = require('./debug');
+var Multi = require('./multi');
+var Command = require('./command');
+var no_password_is_set = /no password is set|called without any password configured/;
+var loading = /LOADING/;
+var RedisClient = require('../').RedisClient;
+
+/********************************************************************************************
+ Replace built-in redis functions
+
+ The callback may be hooked as needed. The same does not apply to the rest of the function.
+ State should not be set outside of the callback if not absolutly necessary.
+ This is important to make sure it works the same as single command or in a multi context.
+ To make sure everything works with the offline queue use the "call_on_write" function.
+ This is going to be executed while writing to the stream.
+
+ TODO: Implement individal command generation as soon as possible to prevent divergent code
+ on single and multi calls!
+********************************************************************************************/
+
+RedisClient.prototype.multi = RedisClient.prototype.MULTI = function multi (args) {
+ var multi = new Multi(this, args);
+ multi.exec = multi.EXEC = multi.exec_transaction;
+ return multi;
+};
+
+// ATTENTION: This is not a native function but is still handled as a individual command as it behaves just the same as multi
+RedisClient.prototype.batch = RedisClient.prototype.BATCH = function batch (args) {
+ return new Multi(this, args);
+};
+
+function select_callback (self, db, callback) {
+ return function (err, res) {
+ if (err === null) {
+ // Store db in this.select_db to restore it on reconnect
+ self.selected_db = db;
+ }
+ utils.callback_or_emit(self, callback, err, res);
+ };
+}
+
+RedisClient.prototype.select = RedisClient.prototype.SELECT = function select (db, callback) {
+ return this.internal_send_command(new Command('select', [db], select_callback(this, db, callback)));
+};
+
+Multi.prototype.select = Multi.prototype.SELECT = function select (db, callback) {
+ this.queue.push(new Command('select', [db], select_callback(this._client, db, callback)));
+ return this;
+};
+
+RedisClient.prototype.monitor = RedisClient.prototype.MONITOR = function monitor (callback) {
+ // Use a individual command, as this is a special case that does not has to be checked for any other command
+ var self = this;
+ var call_on_write = function () {
+ // Activating monitor mode has to happen before Redis returned the callback. The monitor result is returned first.
+ // Therefore we expect the command to be properly processed. If this is not the case, it's not an issue either.
+ self.monitoring = true;
+ };
+ return this.internal_send_command(new Command('monitor', [], callback, call_on_write));
+};
+
+// Only works with batch, not in a transaction
+Multi.prototype.monitor = Multi.prototype.MONITOR = function monitor (callback) {
+ // Use a individual command, as this is a special case that does not has to be checked for any other command
+ if (this.exec !== this.exec_transaction) {
+ var self = this;
+ var call_on_write = function () {
+ self._client.monitoring = true;
+ };
+ this.queue.push(new Command('monitor', [], callback, call_on_write));
+ return this;
+ }
+ // Set multi monitoring to indicate the exec that it should abort
+ // Remove this "hack" as soon as Redis might fix this
+ this.monitoring = true;
+ return this;
+};
+
+function quit_callback (self, callback) {
+ return function (err, res) {
+ if (err && err.code === 'NR_CLOSED') {
+ // Pretent the quit command worked properly in this case.
+ // Either the quit landed in the offline queue and was flushed at the reconnect
+ // or the offline queue is deactivated and the command was rejected right away
+ // or the stream is not writable
+ // or while sending the quit, the connection ended / closed
+ err = null;
+ res = 'OK';
+ }
+ utils.callback_or_emit(self, callback, err, res);
+ if (self.stream.writable) {
+ // If the socket is still alive, kill it. This could happen if quit got a NR_CLOSED error code
+ self.stream.destroy();
+ }
+ };
+}
+
+RedisClient.prototype.QUIT = RedisClient.prototype.quit = function quit (callback) {
+ // TODO: Consider this for v.3
+ // Allow the quit command to be fired as soon as possible to prevent it landing in the offline queue.
+ // this.ready = this.offline_queue.length === 0;
+ var backpressure_indicator = this.internal_send_command(new Command('quit', [], quit_callback(this, callback)));
+ // Calling quit should always end the connection, no matter if there's a connection or not
+ this.closing = true;
+ this.ready = false;
+ return backpressure_indicator;
+};
+
+// Only works with batch, not in a transaction
+Multi.prototype.QUIT = Multi.prototype.quit = function quit (callback) {
+ var self = this._client;
+ var call_on_write = function () {
+ // If called in a multi context, we expect redis is available
+ self.closing = true;
+ self.ready = false;
+ };
+ this.queue.push(new Command('quit', [], quit_callback(self, callback), call_on_write));
+ return this;
+};
+
+function info_callback (self, callback) {
+ return function (err, res) {
+ if (res) {
+ var obj = {};
+ var lines = res.toString().split('\r\n');
+ var line, parts, sub_parts;
+
+ for (var i = 0; i < lines.length; i++) {
+ parts = lines[i].split(':');
+ if (parts[1]) {
+ if (parts[0].indexOf('db') === 0) {
+ sub_parts = parts[1].split(',');
+ obj[parts[0]] = {};
+ while (line = sub_parts.pop()) {
+ line = line.split('=');
+ obj[parts[0]][line[0]] = +line[1];
+ }
+ } else {
+ obj[parts[0]] = parts[1];
+ }
+ }
+ }
+ obj.versions = [];
+ if (obj.redis_version) {
+ obj.redis_version.split('.').forEach(function (num) {
+ obj.versions.push(+num);
+ });
+ }
+ // Expose info key/vals to users
+ self.server_info = obj;
+ } else {
+ self.server_info = {};
+ }
+ utils.callback_or_emit(self, callback, err, res);
+ };
+}
+
+// Store info in this.server_info after each call
+RedisClient.prototype.info = RedisClient.prototype.INFO = function info (section, callback) {
+ var args = [];
+ if (typeof section === 'function') {
+ callback = section;
+ } else if (section !== undefined) {
+ args = Array.isArray(section) ? section : [section];
+ }
+ return this.internal_send_command(new Command('info', args, info_callback(this, callback)));
+};
+
+Multi.prototype.info = Multi.prototype.INFO = function info (section, callback) {
+ var args = [];
+ if (typeof section === 'function') {
+ callback = section;
+ } else if (section !== undefined) {
+ args = Array.isArray(section) ? section : [section];
+ }
+ this.queue.push(new Command('info', args, info_callback(this._client, callback)));
+ return this;
+};
+
+function auth_callback (self, pass, user, callback) {
+ return function (err, res) {
+ if (err) {
+ if (no_password_is_set.test(err.message)) {
+ self.warn('Warning: Redis server does not require a password, but a password was supplied.');
+ err = null;
+ res = 'OK';
+ } else if (loading.test(err.message)) {
+ // If redis is still loading the db, it will not authenticate and everything else will fail
+ debug('Redis still loading, trying to authenticate later');
+ setTimeout(function () {
+ self.auth(pass, user, callback);
+ }, 100);
+ return;
+ }
+ }
+ utils.callback_or_emit(self, callback, err, res);
+ };
+}
+
+RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (pass, user, callback) {
+ debug('Sending auth to ' + this.address + ' id ' + this.connection_id);
+
+ // Backward compatibility support for auth with password only
+ if (user instanceof Function) {
+ callback = user;
+ user = null;
+ }
+ // Stash auth for connect and reconnect.
+ this.auth_pass = pass;
+ this.auth_user = user;
+ var ready = this.ready;
+ this.ready = ready || this.offline_queue.length === 0;
+ var tmp = this.internal_send_command(new Command('auth', user ? [user, pass] : [pass], auth_callback(this, pass, user, callback)));
+ this.ready = ready;
+ return tmp;
+};
+
+// Only works with batch, not in a transaction
+Multi.prototype.auth = Multi.prototype.AUTH = function auth (pass, user, callback) {
+ debug('Sending auth to ' + this.address + ' id ' + this.connection_id);
+
+ // Backward compatibility support for auth with password only
+ if (user instanceof Function) {
+ callback = user;
+ user = null;
+ }
+ // Stash auth for connect and reconnect.
+ this.auth_pass = pass;
+ this.auth_user = user;
+ this.queue.push(new Command('auth', user ? [user, pass] : [pass], auth_callback(this._client, pass, user, callback)));
+ return this;
+};
+
+RedisClient.prototype.client = RedisClient.prototype.CLIENT = function client () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ callback = arguments[1];
+ } else if (Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this;
+ var call_on_write = undefined;
+ // CLIENT REPLY ON|OFF|SKIP
+ /* istanbul ignore next: TODO: Remove this as soon as Travis runs Redis 3.2 */
+ if (arr.length === 2 && arr[0].toString().toUpperCase() === 'REPLY') {
+ var reply_on_off = arr[1].toString().toUpperCase();
+ if (reply_on_off === 'ON' || reply_on_off === 'OFF' || reply_on_off === 'SKIP') {
+ call_on_write = function () {
+ self.reply = reply_on_off;
+ };
+ }
+ }
+ return this.internal_send_command(new Command('client', arr, callback, call_on_write));
+};
+
+Multi.prototype.client = Multi.prototype.CLIENT = function client () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ callback = arguments[1];
+ } else if (Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this._client;
+ var call_on_write = undefined;
+ // CLIENT REPLY ON|OFF|SKIP
+ /* istanbul ignore next: TODO: Remove this as soon as Travis runs Redis 3.2 */
+ if (arr.length === 2 && arr[0].toString().toUpperCase() === 'REPLY') {
+ var reply_on_off = arr[1].toString().toUpperCase();
+ if (reply_on_off === 'ON' || reply_on_off === 'OFF' || reply_on_off === 'SKIP') {
+ call_on_write = function () {
+ self.reply = reply_on_off;
+ };
+ }
+ }
+ this.queue.push(new Command('client', arr, callback, call_on_write));
+ return this;
+};
+
+RedisClient.prototype.hmset = RedisClient.prototype.HMSET = function hmset () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ callback = arguments[1];
+ } else if (Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else if (typeof arguments[1] === 'object' && (arguments.length === 2 || arguments.length === 3 && (typeof arguments[2] === 'function' || typeof arguments[2] === 'undefined'))) {
+ arr = [arguments[0]];
+ for (var field in arguments[1]) {
+ arr.push(field, arguments[1][field]);
+ }
+ callback = arguments[2];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ return this.internal_send_command(new Command('hmset', arr, callback));
+};
+
+Multi.prototype.hmset = Multi.prototype.HMSET = function hmset () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0];
+ callback = arguments[1];
+ } else if (Array.isArray(arguments[1])) {
+ if (len === 3) {
+ callback = arguments[2];
+ }
+ len = arguments[1].length;
+ arr = new Array(len + 1);
+ arr[0] = arguments[0];
+ for (; i < len; i += 1) {
+ arr[i + 1] = arguments[1][i];
+ }
+ } else if (typeof arguments[1] === 'object' && (arguments.length === 2 || arguments.length === 3 && (typeof arguments[2] === 'function' || typeof arguments[2] === 'undefined'))) {
+ arr = [arguments[0]];
+ for (var field in arguments[1]) {
+ arr.push(field, arguments[1][field]);
+ }
+ callback = arguments[2];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ this.queue.push(new Command('hmset', arr, callback));
+ return this;
+};
+
+RedisClient.prototype.subscribe = RedisClient.prototype.SUBSCRIBE = function subscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this;
+ var call_on_write = function () {
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ return this.internal_send_command(new Command('subscribe', arr, callback, call_on_write));
+};
+
+Multi.prototype.subscribe = Multi.prototype.SUBSCRIBE = function subscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this._client;
+ var call_on_write = function () {
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ this.queue.push(new Command('subscribe', arr, callback, call_on_write));
+ return this;
+};
+
+RedisClient.prototype.unsubscribe = RedisClient.prototype.UNSUBSCRIBE = function unsubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this;
+ var call_on_write = function () {
+ // Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ return this.internal_send_command(new Command('unsubscribe', arr, callback, call_on_write));
+};
+
+Multi.prototype.unsubscribe = Multi.prototype.UNSUBSCRIBE = function unsubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this._client;
+ var call_on_write = function () {
+ // Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ this.queue.push(new Command('unsubscribe', arr, callback, call_on_write));
+ return this;
+};
+
+RedisClient.prototype.psubscribe = RedisClient.prototype.PSUBSCRIBE = function psubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this;
+ var call_on_write = function () {
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ return this.internal_send_command(new Command('psubscribe', arr, callback, call_on_write));
+};
+
+Multi.prototype.psubscribe = Multi.prototype.PSUBSCRIBE = function psubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this._client;
+ var call_on_write = function () {
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ this.queue.push(new Command('psubscribe', arr, callback, call_on_write));
+ return this;
+};
+
+RedisClient.prototype.punsubscribe = RedisClient.prototype.PUNSUBSCRIBE = function punsubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this;
+ var call_on_write = function () {
+ // Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ return this.internal_send_command(new Command('punsubscribe', arr, callback, call_on_write));
+};
+
+Multi.prototype.punsubscribe = Multi.prototype.PUNSUBSCRIBE = function punsubscribe () {
+ var arr,
+ len = arguments.length,
+ callback,
+ i = 0;
+ if (Array.isArray(arguments[0])) {
+ arr = arguments[0].slice(0);
+ callback = arguments[1];
+ } else {
+ len = arguments.length;
+ // The later should not be the average use case
+ if (len !== 0 && (typeof arguments[len - 1] === 'function' || typeof arguments[len - 1] === 'undefined')) {
+ len--;
+ callback = arguments[len];
+ }
+ arr = new Array(len);
+ for (; i < len; i += 1) {
+ arr[i] = arguments[i];
+ }
+ }
+ var self = this._client;
+ var call_on_write = function () {
+ // Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
+ self.pub_sub_mode = self.pub_sub_mode || self.command_queue.length + 1;
+ };
+ this.queue.push(new Command('punsubscribe', arr, callback, call_on_write));
+ return this;
+};
diff --git a/node_modules/redis/heroku/node_modules/redis/lib/multi.js b/node_modules/redis/heroku/node_modules/redis/lib/multi.js
new file mode 100644
index 0000000..d89cffb
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/lib/multi.js
@@ -0,0 +1,187 @@
+'use strict';
+
+var Queue = require('denque');
+var utils = require('./utils');
+var Command = require('./command');
+
+function Multi (client, args) {
+ this._client = client;
+ this.queue = new Queue();
+ var command, tmp_args;
+ if (args) { // Either undefined or an array. Fail hard if it's not an array
+ for (var i = 0; i < args.length; i++) {
+ command = args[i][0];
+ tmp_args = args[i].slice(1);
+ if (Array.isArray(command)) {
+ this[command[0]].apply(this, command.slice(1).concat(tmp_args));
+ } else {
+ this[command].apply(this, tmp_args);
+ }
+ }
+ }
+}
+
+function pipeline_transaction_command (self, command_obj, index) {
+ // Queueing is done first, then the commands are executed
+ var tmp = command_obj.callback;
+ command_obj.callback = function (err, reply) {
+ // Ignore the multi command. This is applied by node_redis and the user does not benefit by it
+ if (err && index !== -1) {
+ if (tmp) {
+ tmp(err);
+ }
+ err.position = index;
+ self.errors.push(err);
+ }
+ // Keep track of who wants buffer responses:
+ // By the time the callback is called the command_obj got the buffer_args attribute attached
+ self.wants_buffers[index] = command_obj.buffer_args;
+ command_obj.callback = tmp;
+ };
+ self._client.internal_send_command(command_obj);
+}
+
+Multi.prototype.exec_atomic = Multi.prototype.EXEC_ATOMIC = Multi.prototype.execAtomic = function exec_atomic (callback) {
+ if (this.queue.length < 2) {
+ return this.exec_batch(callback);
+ }
+ return this.exec(callback);
+};
+
+function multi_callback (self, err, replies) {
+ var i = 0, command_obj;
+
+ if (err) {
+ err.errors = self.errors;
+ if (self.callback) {
+ self.callback(err);
+ // Exclude connection errors so that those errors won't be emitted twice
+ } else if (err.code !== 'CONNECTION_BROKEN') {
+ self._client.emit('error', err);
+ }
+ return;
+ }
+
+ if (replies) {
+ while (command_obj = self.queue.shift()) {
+ if (replies[i] instanceof Error) {
+ var match = replies[i].message.match(utils.err_code);
+ // LUA script could return user errors that don't behave like all other errors!
+ if (match) {
+ replies[i].code = match[1];
+ }
+ replies[i].command = command_obj.command.toUpperCase();
+ if (typeof command_obj.callback === 'function') {
+ command_obj.callback(replies[i]);
+ }
+ } else {
+ // If we asked for strings, even in detect_buffers mode, then return strings:
+ replies[i] = self._client.handle_reply(replies[i], command_obj.command, self.wants_buffers[i]);
+ if (typeof command_obj.callback === 'function') {
+ command_obj.callback(null, replies[i]);
+ }
+ }
+ i++;
+ }
+ }
+
+ if (self.callback) {
+ self.callback(null, replies);
+ }
+}
+
+Multi.prototype.exec_transaction = function exec_transaction (callback) {
+ if (this.monitoring || this._client.monitoring) {
+ var err = new RangeError(
+ 'Using transaction with a client that is in monitor mode does not work due to faulty return values of Redis.'
+ );
+ err.command = 'EXEC';
+ err.code = 'EXECABORT';
+ return utils.reply_in_order(this._client, callback, err);
+ }
+ var self = this;
+ var len = self.queue.length;
+ self.errors = [];
+ self.callback = callback;
+ self._client.cork();
+ self.wants_buffers = new Array(len);
+ pipeline_transaction_command(self, new Command('multi', []), -1);
+ // Drain queue, callback will catch 'QUEUED' or error
+ for (var index = 0; index < len; index++) {
+ // The commands may not be shifted off, since they are needed in the result handler
+ pipeline_transaction_command(self, self.queue.get(index), index);
+ }
+
+ self._client.internal_send_command(new Command('exec', [], function (err, replies) {
+ multi_callback(self, err, replies);
+ }));
+ self._client.uncork();
+ return !self._client.should_buffer;
+};
+
+function batch_callback (self, cb, i) {
+ return function batch_callback (err, res) {
+ if (err) {
+ self.results[i] = err;
+ // Add the position to the error
+ self.results[i].position = i;
+ } else {
+ self.results[i] = res;
+ }
+ cb(err, res);
+ };
+}
+
+Multi.prototype.exec = Multi.prototype.EXEC = Multi.prototype.exec_batch = function exec_batch (callback) {
+ var self = this;
+ var len = self.queue.length;
+ var index = 0;
+ var command_obj;
+ if (len === 0) {
+ utils.reply_in_order(self._client, callback, null, []);
+ return !self._client.should_buffer;
+ }
+ self._client.cork();
+ if (!callback) {
+ while (command_obj = self.queue.shift()) {
+ self._client.internal_send_command(command_obj);
+ }
+ self._client.uncork();
+ return !self._client.should_buffer;
+ }
+ var callback_without_own_cb = function (err, res) {
+ if (err) {
+ self.results.push(err);
+ // Add the position to the error
+ var i = self.results.length - 1;
+ self.results[i].position = i;
+ } else {
+ self.results.push(res);
+ }
+ // Do not emit an error here. Otherwise each error would result in one emit.
+ // The errors will be returned in the result anyway
+ };
+ var last_callback = function (cb) {
+ return function (err, res) {
+ cb(err, res);
+ callback(null, self.results);
+ };
+ };
+ self.results = [];
+ while (command_obj = self.queue.shift()) {
+ if (typeof command_obj.callback === 'function') {
+ command_obj.callback = batch_callback(self, command_obj.callback, index);
+ } else {
+ command_obj.callback = callback_without_own_cb;
+ }
+ if (typeof callback === 'function' && index === len - 1) {
+ command_obj.callback = last_callback(command_obj.callback);
+ }
+ this._client.internal_send_command(command_obj);
+ index++;
+ }
+ self._client.uncork();
+ return !self._client.should_buffer;
+};
+
+module.exports = Multi;
diff --git a/node_modules/redis/heroku/node_modules/redis/lib/utils.js b/node_modules/redis/heroku/node_modules/redis/lib/utils.js
new file mode 100644
index 0000000..52e58ec
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/lib/utils.js
@@ -0,0 +1,134 @@
+'use strict';
+
+// hgetall converts its replies to an Object. If the reply is empty, null is returned.
+// These function are only called with internal data and have therefore always the same instanceof X
+function replyToObject (reply) {
+ // The reply might be a string or a buffer if this is called in a transaction (multi)
+ if (reply.length === 0 || !(reply instanceof Array)) {
+ return null;
+ }
+ var obj = {};
+ for (var i = 0; i < reply.length; i += 2) {
+ obj[reply[i].toString('binary')] = reply[i + 1];
+ }
+ return obj;
+}
+
+function replyToStrings (reply) {
+ if (reply instanceof Buffer) {
+ return reply.toString();
+ }
+ if (reply instanceof Array) {
+ var res = new Array(reply.length);
+ for (var i = 0; i < reply.length; i++) {
+ // Recusivly call the function as slowlog returns deep nested replies
+ res[i] = replyToStrings(reply[i]);
+ }
+ return res;
+ }
+
+ return reply;
+}
+
+function print (err, reply) {
+ if (err) {
+ // A error always begins with Error:
+ console.log(err.toString());
+ } else {
+ console.log('Reply: ' + reply);
+ }
+}
+
+var camelCase;
+// Deep clone arbitrary objects with arrays. Can't handle cyclic structures (results in a range error)
+// Any attribute with a non primitive value besides object and array will be passed by reference (e.g. Buffers, Maps, Functions)
+// All capital letters are going to be replaced with a lower case letter and a underscore infront of it
+function clone (obj) {
+ var copy;
+ if (Array.isArray(obj)) {
+ copy = new Array(obj.length);
+ for (var i = 0; i < obj.length; i++) {
+ copy[i] = clone(obj[i]);
+ }
+ return copy;
+ }
+ if (Object.prototype.toString.call(obj) === '[object Object]') {
+ copy = {};
+ var elems = Object.keys(obj);
+ var elem;
+ while (elem = elems.pop()) {
+ if (elem === 'tls') { // special handle tls
+ copy[elem] = obj[elem];
+ continue;
+ }
+ // Accept camelCase options and convert them to snake_case
+ var snake_case = elem.replace(/[A-Z][^A-Z]/g, '_$&').toLowerCase();
+ // If camelCase is detected, pass it to the client, so all variables are going to be camelCased
+ // There are no deep nested options objects yet, but let's handle this future proof
+ if (snake_case !== elem.toLowerCase()) {
+ camelCase = true;
+ }
+ copy[snake_case] = clone(obj[elem]);
+ }
+ return copy;
+ }
+ return obj;
+}
+
+function convenienceClone (obj) {
+ camelCase = false;
+ obj = clone(obj) || {};
+ if (camelCase) {
+ obj.camel_case = true;
+ }
+ return obj;
+}
+
+function callbackOrEmit (self, callback, err, res) {
+ if (callback) {
+ callback(err, res);
+ } else if (err) {
+ self.emit('error', err);
+ }
+}
+
+function replyInOrder (self, callback, err, res, queue) {
+ // If the queue is explicitly passed, use that, otherwise fall back to the offline queue first,
+ // as there might be commands in both queues at the same time
+ var command_obj;
+ /* istanbul ignore if: TODO: Remove this as soon as we test Redis 3.2 on travis */
+ if (queue) {
+ command_obj = queue.peekBack();
+ } else {
+ command_obj = self.offline_queue.peekBack() || self.command_queue.peekBack();
+ }
+ if (!command_obj) {
+ process.nextTick(function () {
+ callbackOrEmit(self, callback, err, res);
+ });
+ } else {
+ var tmp = command_obj.callback;
+ command_obj.callback = tmp ?
+ function (e, r) {
+ tmp(e, r);
+ callbackOrEmit(self, callback, err, res);
+ } :
+ function (e, r) {
+ if (e) {
+ self.emit('error', e);
+ }
+ callbackOrEmit(self, callback, err, res);
+ };
+ }
+}
+
+module.exports = {
+ reply_to_strings: replyToStrings,
+ reply_to_object: replyToObject,
+ print: print,
+ err_code: /^([A-Z]+)\s+(.+)$/,
+ monitor_regex: /^[0-9]{10,11}\.[0-9]+ \[[0-9]+ .+\]( ".+?")+$/,
+ clone: convenienceClone,
+ callback_or_emit: callbackOrEmit,
+ reply_in_order: replyInOrder
+};
diff --git a/node_modules/redis/heroku/node_modules/redis/npm b/node_modules/redis/heroku/node_modules/redis/npm
new file mode 100644
index 0000000..e69de29
diff --git a/node_modules/redis/heroku/node_modules/redis/package.json b/node_modules/redis/heroku/node_modules/redis/package.json
new file mode 100644
index 0000000..be84ce4
--- /dev/null
+++ b/node_modules/redis/heroku/node_modules/redis/package.json
@@ -0,0 +1,77 @@
+{
+ "name": "redis",
+ "version": "3.1.0",
+ "description": "A high performance Redis client.",
+ "keywords": [
+ "database",
+ "redis",
+ "transaction",
+ "pipelining",
+ "performance",
+ "queue",
+ "nodejs",
+ "pubsub",
+ "backpressure"
+ ],
+ "author": "Matt Ranney ",
+ "contributors": [
+ {
+ "name": "Mike Diarmid (Salakar)",
+ "url": "https://github.com/salakar"
+ },
+ {
+ "name": "Ruben Bridgewater (BridgeAR)",
+ "url": "https://github.com/BridgeAR"
+ }
+ ],
+ "license": "MIT",
+ "main": "./index.js",
+ "scripts": {
+ "coveralls": "nyc report --reporter=text-lcov | coveralls",
+ "coverage": "nyc report --reporter=html",
+ "benchmark": "node benchmarks/multi_bench.js",
+ "test": "nyc --cache mocha ./test/*.spec.js ./test/commands/*.spec.js --timeout=8000 && npm run coverage",
+ "lint": "eslint .",
+ "lint:fix": "eslint . --fix",
+ "lint:report": "eslint --output-file=eslint-report.json --format=json .",
+ "compare": "node benchmarks/diff_multi_bench_output.js beforeBench.txt afterBench.txt"
+ },
+ "dependencies": {
+ "denque": "^1.5.0",
+ "redis-commands": "^1.7.0",
+ "redis-errors": "^1.2.0",
+ "redis-parser": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "devDependencies": {
+ "bluebird": "^3.7.2",
+ "coveralls": "^3.1.0",
+ "cross-spawn": "^7.0.3",
+ "eslint": "^7.21.0",
+ "intercept-stdout": "~0.1.2",
+ "metrics": "^0.1.21",
+ "mocha": "^8.3.0",
+ "nyc": "^15.1.0",
+ "prettier": "^2.2.1",
+ "tcp-port-used": "^1.0.1",
+ "uuid": "^8.3.2"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/NodeRedis/node-redis.git"
+ },
+ "bugs": {
+ "url": "https://github.com/NodeRedis/node-redis/issues"
+ },
+ "homepage": "https://github.com/NodeRedis/node-redis",
+ "directories": {
+ "example": "examples",
+ "test": "test"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-redis"
+ }
+}
diff --git a/node_modules/redis/heroku/package.json b/node_modules/redis/heroku/package.json
new file mode 100644
index 0000000..2f888e5
--- /dev/null
+++ b/node_modules/redis/heroku/package.json
@@ -0,0 +1,9 @@
+{
+ "scripts": {
+ "start": "node ./index.js"
+ },
+ "dependencies": {
+ "redis": "^3.1.0"
+ }
+}
+
diff --git a/node_modules/redis/index.js b/node_modules/redis/index.js
old mode 100755
new mode 100644
index 58fcf84..fe79c5f
--- a/node_modules/redis/index.js
+++ b/node_modules/redis/index.js
@@ -5,10 +5,11 @@ var tls = require('tls');
var util = require('util');
var utils = require('./lib/utils');
var Command = require('./lib/command');
-var Queue = require('double-ended-queue');
+var Queue = require('denque');
var errorClasses = require('./lib/customErrors');
var EventEmitter = require('events');
var Parser = require('redis-parser');
+var RedisErrors = require('redis-errors');
var commands = require('redis-commands');
var debug = require('./lib/debug');
var unifyOptions = require('./lib/createClient');
@@ -19,11 +20,6 @@ var SUBSCRIBE_COMMANDS = {
punsubscribe: true
};
-// Newer Node.js versions > 0.10 return the EventEmitter right away and using .EventEmitter was deprecated
-if (typeof EventEmitter !== 'function') {
- EventEmitter = EventEmitter.EventEmitter;
-}
-
function noop () {}
function handle_detect_buffers_reply (reply, command, buffer_args) {
@@ -71,36 +67,18 @@ function RedisClient (options, stream) {
cnx_options.family = (!options.family && net.isIP(cnx_options.host)) || (options.family === 'IPv6' ? 6 : 4);
this.address = cnx_options.host + ':' + cnx_options.port;
}
- // Warn on misusing deprecated functions
- if (typeof options.retry_strategy === 'function') {
- if ('max_attempts' in options) {
- self.warn('WARNING: You activated the retry_strategy and max_attempts at the same time. This is not possible and max_attempts will be ignored.');
- // Do not print deprecation warnings twice
- delete options.max_attempts;
- }
- if ('retry_max_delay' in options) {
- self.warn('WARNING: You activated the retry_strategy and retry_max_delay at the same time. This is not possible and retry_max_delay will be ignored.');
- // Do not print deprecation warnings twice
- delete options.retry_max_delay;
- }
- }
this.connection_options = cnx_options;
this.connection_id = RedisClient.connection_id++;
this.connected = false;
this.ready = false;
- if (options.socket_nodelay === undefined) {
- options.socket_nodelay = true;
- } else if (!options.socket_nodelay) { // Only warn users with this set to false
- self.warn(
- 'socket_nodelay is deprecated and will be removed in v.3.0.0.\n' +
- 'Setting socket_nodelay to false likely results in a reduced throughput. Please use .batch for pipelining instead.\n' +
- 'If you are sure you rely on the NAGLE-algorithm you can activate it by calling client.stream.setNoDelay(false) instead.'
- );
- }
if (options.socket_keepalive === undefined) {
options.socket_keepalive = true;
}
+ if (options.socket_initial_delay === undefined) {
+ options.socket_initial_delay = 0;
+ // set default to 0, which is aligned to https://nodejs.org/api/net.html#net_socket_setkeepalive_enable_initialdelay
+ }
for (var command in options.rename_commands) {
options.rename_commands[command.toLowerCase()] = options.rename_commands[command];
}
@@ -116,14 +94,6 @@ function RedisClient (options, stream) {
this.handle_reply = handle_detect_buffers_reply;
}
this.should_buffer = false;
- this.max_attempts = options.max_attempts | 0;
- if ('max_attempts' in options) {
- self.warn(
- 'max_attempts is deprecated and will be removed in v.3.0.0.\n' +
- 'To reduce the number of options and to improve the reconnection handling please use the new `retry_strategy` option instead.\n' +
- 'This replaces the max_attempts and retry_max_delay option.'
- );
- }
this.command_queue = new Queue(); // Holds sent commands to de-pipeline them
this.offline_queue = new Queue(); // Holds commands issued but not able to be sent
this.pipeline_queue = new Queue(); // Holds all pipelined commands
@@ -131,14 +101,6 @@ function RedisClient (options, stream) {
// This should be done by the retry_strategy. Instead it should only be the timeout for connecting to redis
this.connect_timeout = +options.connect_timeout || 3600000; // 60 * 60 * 1000 ms
this.enable_offline_queue = options.enable_offline_queue === false ? false : true;
- this.retry_max_delay = +options.retry_max_delay || null;
- if ('retry_max_delay' in options) {
- self.warn(
- 'retry_max_delay is deprecated and will be removed in v.3.0.0.\n' +
- 'To reduce the amount of options and the improve the reconnection handling please use the new `retry_strategy` option instead.\n' +
- 'This replaces the max_attempts and retry_max_delay option.'
- );
- }
this.initialize_retry_vars();
this.pub_sub_mode = 0;
this.subscription_set = {};
@@ -147,8 +109,8 @@ function RedisClient (options, stream) {
this.closing = false;
this.server_info = {};
this.auth_pass = options.auth_pass || options.password;
+ this.auth_user = options.auth_user || options.user;
this.selected_db = options.db; // Save the selected db here, used when reconnecting
- this.old_state = null;
this.fire_strings = true; // Determine if strings or buffers should be written to the stream
this.pipeline = false;
this.sub_commands_left = 0;
@@ -159,23 +121,7 @@ function RedisClient (options, stream) {
this.create_stream();
// The listeners will not be attached right away, so let's print the deprecation message while the listener is attached
this.on('newListener', function (event) {
- if (event === 'idle') {
- this.warn(
- 'The idle event listener is deprecated and will likely be removed in v.3.0.0.\n' +
- 'If you rely on this feature please open a new ticket in node_redis with your use case'
- );
- } else if (event === 'drain') {
- this.warn(
- 'The drain event listener is deprecated and will be removed in v.3.0.0.\n' +
- 'If you want to keep on listening to this event please listen to the stream drain event directly.'
- );
- } else if ((event === 'message_buffer' || event === 'pmessage_buffer' || event === 'messageBuffer' || event === 'pmessageBuffer') && !this.buffers && !this.message_buffers) {
- if (this.reply_parser.name !== 'javascript') {
- return this.warn(
- 'You attached the "' + event + '" listener without the returnBuffers option set to true.\n' +
- 'Please use the JavaScript parser or set the returnBuffers option to true to return buffers.'
- );
- }
+ if ((event === 'message_buffer' || event === 'pmessage_buffer' || event === 'messageBuffer' || event === 'pmessageBuffer') && !this.buffers && !this.message_buffers) {
this.reply_parser.optionReturnBuffers = true;
this.message_buffers = true;
this.handle_reply = handle_detect_buffers_reply;
@@ -201,7 +147,7 @@ function create_parser (self) {
err.message += '. Please report this.';
self.ready = false;
self.flush_and_error({
- message: 'Fatal error encountert. Command aborted.',
+ message: 'Fatal error encountered. Command aborted.',
code: 'NR_FATAL'
}, {
error: err,
@@ -211,7 +157,6 @@ function create_parser (self) {
self.create_stream();
},
returnBuffers: self.buffers || self.message_buffers,
- name: self.options.parser || 'javascript',
stringNumbers: self.options.string_numbers || false
});
}
@@ -272,19 +217,12 @@ RedisClient.prototype.create_stream = function () {
// The buffer_from_socket.toString() has a significant impact on big chunks and therefore this should only be used if necessary
debug('Net read ' + self.address + ' id ' + self.connection_id); // + ': ' + buffer_from_socket.toString());
self.reply_parser.execute(buffer_from_socket);
- self.emit_idle();
});
this.stream.on('error', function (err) {
self.on_error(err);
});
- /* istanbul ignore next: difficult to test and not important as long as we keep this listener */
- this.stream.on('clientError', function (err) {
- debug('clientError occured');
- self.on_error(err);
- });
-
this.stream.once('close', function (hadError) {
self.connection_gone('close');
});
@@ -297,15 +235,13 @@ RedisClient.prototype.create_stream = function () {
self.drain();
});
- if (this.options.socket_nodelay) {
- this.stream.setNoDelay();
- }
+ this.stream.setNoDelay();
// Fire the command before redis is connected to be sure it's the first fired command
if (this.auth_pass !== undefined) {
this.ready = true;
// Fail silently as we might not be able to connect
- this.auth(this.auth_pass, function (err) {
+ this.auth(this.auth_pass, this.auth_user, function (err) {
if (err && err.code !== 'UNCERTAIN_STATE') {
self.emit('error', err);
}
@@ -401,7 +337,7 @@ RedisClient.prototype.on_error = function (err) {
this.connected = false;
this.ready = false;
- // Only emit the error if the retry_stategy option is not set
+ // Only emit the error if the retry_strategy option is not set
if (!this.options.retry_strategy) {
this.emit('error', err);
}
@@ -416,7 +352,7 @@ RedisClient.prototype.on_connect = function () {
this.connected = true;
this.ready = false;
this.emitted_end = false;
- this.stream.setKeepAlive(this.options.socket_keepalive);
+ this.stream.setKeepAlive(this.options.socket_keepalive, this.options.socket_initial_delay);
this.stream.setTimeout(0);
this.emit('connect');
@@ -621,25 +557,28 @@ RedisClient.prototype.connection_gone = function (why, error) {
if (this.retry_delay instanceof Error) {
error = this.retry_delay;
}
+
+ var errorMessage = 'Redis connection in broken state: retry aborted.';
+
this.flush_and_error({
- message: 'Stream connection ended and command aborted.',
- code: 'NR_CLOSED'
+ message: errorMessage,
+ code: 'CONNECTION_BROKEN',
}, {
error: error
});
+ var retryError = new Error(errorMessage);
+ retryError.code = 'CONNECTION_BROKEN';
+ if (error) {
+ retryError.origin = error;
+ }
this.end(false);
+ this.emit('error', retryError);
return;
}
}
- if (this.max_attempts !== 0 && this.attempts >= this.max_attempts || this.retry_totaltime >= this.connect_timeout) {
- var message = 'Redis connection in broken state: ';
- if (this.retry_totaltime >= this.connect_timeout) {
- message += 'connection timeout exceeded.';
- } else {
- message += 'maximum connection attempts exceeded.';
- }
-
+ if (this.retry_totaltime >= this.connect_timeout) {
+ var message = 'Redis connection in broken state: connection timeout exceeded.';
this.flush_and_error({
message: message,
code: 'CONNECTION_BROKEN',
@@ -651,8 +590,8 @@ RedisClient.prototype.connection_gone = function (why, error) {
if (error) {
err.origin = error;
}
- this.emit('error', err);
this.end(false);
+ this.emit('error', err);
return;
}
@@ -670,15 +609,12 @@ RedisClient.prototype.connection_gone = function (why, error) {
});
}
- if (this.retry_max_delay !== null && this.retry_delay > this.retry_max_delay) {
- this.retry_delay = this.retry_max_delay;
- } else if (this.retry_totaltime + this.retry_delay > this.connect_timeout) {
+ if (this.retry_totaltime + this.retry_delay > this.connect_timeout) {
// Do not exceed the maximum
this.retry_delay = this.connect_timeout - this.retry_totaltime;
}
debug('Retry connection in ' + this.retry_delay + ' ms');
-
this.retry_timer = setTimeout(retry_connection, this.retry_delay, this, error);
};
@@ -707,16 +643,9 @@ RedisClient.prototype.return_error = function (err) {
};
RedisClient.prototype.drain = function () {
- this.emit('drain');
this.should_buffer = false;
};
-RedisClient.prototype.emit_idle = function () {
- if (this.command_queue.length === 0 && this.pub_sub_mode === 0) {
- this.emit('idle');
- }
-};
-
function normal_reply (self, reply) {
var command_obj = self.command_queue.shift();
if (typeof command_obj.callback === 'function') {
@@ -766,7 +695,7 @@ function subscribe_unsubscribe (self, reply, type) {
self.command_queue.shift();
if (typeof command_obj.callback === 'function') {
// TODO: The current return value is pretty useless.
- // Evaluate to change this in v.3 to return all subscribed / unsubscribed channels in an array including the number of channels subscribed too
+ // Evaluate to change this in v.4 to return all subscribed / unsubscribed channels in an array including the number of channels subscribed too
command_obj.callback(null, channel);
}
self.sub_commands_left = 0;
@@ -782,7 +711,7 @@ function subscribe_unsubscribe (self, reply, type) {
function return_pub_sub (self, reply) {
var type = reply[0].toString();
if (type === 'message') { // channel, message
- if (!self.options.return_buffers || self.message_buffers) { // backwards compatible. Refactor this in v.3 to always return a string on the normal emitter
+ if (!self.options.return_buffers || self.message_buffers) { // backwards compatible. Refactor this in v.4 to always return a string on the normal emitter
self.emit('message', reply[1].toString(), reply[2].toString());
self.emit('message_buffer', reply[1], reply[2]);
self.emit('messageBuffer', reply[1], reply[2]);
@@ -790,7 +719,7 @@ function return_pub_sub (self, reply) {
self.emit('message', reply[1], reply[2]);
}
} else if (type === 'pmessage') { // pattern, channel, message
- if (!self.options.return_buffers || self.message_buffers) { // backwards compatible. Refactor this in v.3 to always return a string on the normal emitter
+ if (!self.options.return_buffers || self.message_buffers) { // backwards compatible. Refactor this in v.4 to always return a string on the normal emitter
self.emit('pmessage', reply[1].toString(), reply[2].toString(), reply[3].toString());
self.emit('pmessage_buffer', reply[1], reply[2], reply[3]);
self.emit('pmessageBuffer', reply[1], reply[2], reply[3]);
@@ -891,39 +820,44 @@ RedisClient.prototype.internal_send_command = function (command_obj) {
// 30000 seemed to be a good value to switch to buffers after testing and checking the pros and cons
if (args[i].length > 30000) {
big_data = true;
- args_copy[i] = new Buffer(args[i], 'utf8');
+ args_copy[i] = Buffer.from(args[i], 'utf8');
} else {
args_copy[i] = args[i];
}
} else if (typeof args[i] === 'object') { // Checking for object instead of Buffer.isBuffer helps us finding data types that we can't handle properly
if (args[i] instanceof Date) { // Accept dates as valid input
args_copy[i] = args[i].toString();
- } else if (args[i] === null) {
- this.warn(
- 'Deprecated: The ' + command.toUpperCase() + ' command contains a "null" argument.\n' +
- 'This is converted to a "null" string now and will return an error from v.3.0 on.\n' +
- 'Please handle this in your code to make sure everything works as you intended it to.'
- );
- args_copy[i] = 'null'; // Backwards compatible :/
} else if (Buffer.isBuffer(args[i])) {
args_copy[i] = args[i];
command_obj.buffer_args = true;
big_data = true;
} else {
- this.warn(
- 'Deprecated: The ' + command.toUpperCase() + ' command contains a argument of type ' + args[i].constructor.name + '.\n' +
- 'This is converted to "' + args[i].toString() + '" by using .toString() now and will return an error from v.3.0 on.\n' +
- 'Please handle this in your code to make sure everything works as you intended it to.'
+ var invalidArgError = new Error(
+ 'node_redis: The ' + command.toUpperCase() + ' command contains a invalid argument type.\n' +
+ 'Only strings, dates and buffers are accepted. Please update your code to use valid argument types.'
);
- args_copy[i] = args[i].toString(); // Backwards compatible :/
+ invalidArgError.command = command_obj.command.toUpperCase();
+ if (command_obj.args && command_obj.args.length) {
+ invalidArgError.args = command_obj.args;
+ }
+ if (command_obj.callback) {
+ command_obj.callback(invalidArgError);
+ return false;
+ }
+ throw invalidArgError;
}
} else if (typeof args[i] === 'undefined') {
- this.warn(
- 'Deprecated: The ' + command.toUpperCase() + ' command contains a "undefined" argument.\n' +
- 'This is converted to a "undefined" string now and will return an error from v.3.0 on.\n' +
- 'Please handle this in your code to make sure everything works as you intended it to.'
+ var undefinedArgError = new Error(
+ 'node_redis: The ' + command.toUpperCase() + ' command contains a invalid argument type of "undefined".\n' +
+ 'Only strings, dates and buffers are accepted. Please update your code to use valid argument types.'
);
- args_copy[i] = 'undefined'; // Backwards compatible :/
+ undefinedArgError.command = command_obj.command.toUpperCase();
+ if (command_obj.args && command_obj.args.length) {
+ undefinedArgError.args = command_obj.args;
+ }
+ // there is always a callback in this scenario
+ command_obj.callback(undefinedArgError);
+ return false;
} else {
// Seems like numbers are converted fast using string concatenation
args_copy[i] = '' + args[i];
@@ -1092,9 +1026,9 @@ exports.RedisClient = RedisClient;
exports.print = utils.print;
exports.Multi = require('./lib/multi');
exports.AbortError = errorClasses.AbortError;
-exports.RedisError = Parser.RedisError;
-exports.ParserError = Parser.ParserError;
-exports.ReplyError = Parser.ReplyError;
+exports.RedisError = RedisErrors.RedisError;
+exports.ParserError = RedisErrors.ParserError;
+exports.ReplyError = RedisErrors.ReplyError;
exports.AggregateError = errorClasses.AggregateError;
// Add all redis commands / node_redis api to the client
@@ -1102,4 +1036,4 @@ require('./lib/individualCommands');
require('./lib/extendedApi');
//enables adding new commands (for modules and new commands)
-exports.addCommand = exports.add_command = require('./lib/commands');
\ No newline at end of file
+exports.addCommand = exports.add_command = require('./lib/commands');
diff --git a/node_modules/redis/lib/command.js b/node_modules/redis/lib/command.js
old mode 100755
new mode 100644
diff --git a/node_modules/redis/lib/commands.js b/node_modules/redis/lib/commands.js
old mode 100755
new mode 100644
index 6275ec8..a3b5189
--- a/node_modules/redis/lib/commands.js
+++ b/node_modules/redis/lib/commands.js
@@ -4,18 +4,6 @@ var commands = require('redis-commands');
var Multi = require('./multi');
var RedisClient = require('../').RedisClient;
var Command = require('./command');
-// Feature detect if a function may change it's name
-var changeFunctionName = (function () {
- var fn = function abc () {};
- try {
- Object.defineProperty(fn, 'name', {
- value: 'foobar'
- });
- return true;
- } catch (e) {
- return false;
- }
-}());
var addCommand = function (command) {
// Some rare Redis commands use special characters in their command name
@@ -61,11 +49,9 @@ var addCommand = function (command) {
if (commandName !== command) {
RedisClient.prototype[commandName.toUpperCase()] = RedisClient.prototype[commandName] = RedisClient.prototype[command];
}
- if (changeFunctionName) {
- Object.defineProperty(RedisClient.prototype[command], 'name', {
- value: commandName
- });
- }
+ Object.defineProperty(RedisClient.prototype[command], 'name', {
+ value: commandName
+ });
}
// Do not override existing functions
@@ -108,11 +94,9 @@ var addCommand = function (command) {
if (commandName !== command) {
Multi.prototype[commandName.toUpperCase()] = Multi.prototype[commandName] = Multi.prototype[command];
}
- if (changeFunctionName) {
- Object.defineProperty(Multi.prototype[command], 'name', {
- value: commandName
- });
- }
+ Object.defineProperty(Multi.prototype[command], 'name', {
+ value: commandName
+ });
}
};
diff --git a/node_modules/redis/lib/createClient.js b/node_modules/redis/lib/createClient.js
old mode 100755
new mode 100644
index 2f3b09f..b03bb57
--- a/node_modules/redis/lib/createClient.js
+++ b/node_modules/redis/lib/createClient.js
@@ -29,10 +29,18 @@ module.exports = function createClient (port_arg, host_arg, options) {
// [redis:]//[[user][:password]@][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]
if (parsed.slashes) { // We require slashes
if (parsed.auth) {
- options.password = parsed.auth.split(':')[1];
+ var columnIndex = parsed.auth.indexOf(':');
+ options.password = parsed.auth.slice(columnIndex + 1);
+ if (columnIndex > 0) {
+ options.user = parsed.auth.slice(0, columnIndex);
+ }
}
- if (parsed.protocol && parsed.protocol !== 'redis:') {
- console.warn('node_redis: WARNING: You passed "' + parsed.protocol.substring(0, parsed.protocol.length - 1) + '" as protocol instead of the "redis" protocol!');
+ if (parsed.protocol) {
+ if (parsed.protocol === 'rediss:') {
+ options.tls = options.tls || {};
+ } else if (parsed.protocol !== 'redis:') {
+ console.warn('node_redis: WARNING: You passed "' + parsed.protocol.substring(0, parsed.protocol.length - 1) + '" as protocol instead of the "redis" protocol!');
+ }
}
if (parsed.pathname && parsed.pathname !== '/') {
options.db = parsed.pathname.substr(1);
@@ -68,7 +76,7 @@ module.exports = function createClient (port_arg, host_arg, options) {
options.host = options.host || host_arg;
if (port_arg && arguments.length !== 1) {
- throw new TypeError('To many arguments passed to createClient. Please only pass the options object');
+ throw new TypeError('Too many arguments passed to createClient. Please only pass the options object');
}
}
diff --git a/node_modules/redis/lib/customErrors.js b/node_modules/redis/lib/customErrors.js
old mode 100755
new mode 100644
index d9b3442..2483db0
--- a/node_modules/redis/lib/customErrors.js
+++ b/node_modules/redis/lib/customErrors.js
@@ -2,14 +2,13 @@
var util = require('util');
var assert = require('assert');
-var RedisError = require('redis-parser').RedisError;
+var RedisError = require('redis-errors').RedisError;
var ADD_STACKTRACE = false;
function AbortError (obj, stack) {
assert(obj, 'The options argument is required');
assert.strictEqual(typeof obj, 'object', 'The options argument has to be of type object');
- RedisError.call(this, obj.message, ADD_STACKTRACE);
Object.defineProperty(this, 'message', {
value: obj.message || '',
configurable: true,
diff --git a/node_modules/redis/lib/debug.js b/node_modules/redis/lib/debug.js
old mode 100755
new mode 100644
index 0e6333f..d69c1ea
--- a/node_modules/redis/lib/debug.js
+++ b/node_modules/redis/lib/debug.js
@@ -4,7 +4,9 @@ var index = require('../');
function debug () {
if (index.debug_mode) {
- console.error.apply(null, arguments);
+ var data = Array.prototype.slice.call(arguments);
+ data.unshift(new Date().toISOString());
+ console.error.apply(null, data);
}
}
diff --git a/node_modules/redis/lib/extendedApi.js b/node_modules/redis/lib/extendedApi.js
old mode 100755
new mode 100644
index bac3691..27ed421
--- a/node_modules/redis/lib/extendedApi.js
+++ b/node_modules/redis/lib/extendedApi.js
@@ -95,7 +95,7 @@ RedisClient.prototype.duplicate = function (options, callback) {
existing_options[elem] = options[elem];
}
var client = new RedisClient(existing_options);
- client.selected_db = this.selected_db;
+ client.selected_db = options.db || this.selected_db;
if (typeof callback === 'function') {
var ready_listener = function () {
callback(null, client);
diff --git a/node_modules/redis/lib/individualCommands.js b/node_modules/redis/lib/individualCommands.js
old mode 100755
new mode 100644
index d366b64..c3ea3da
--- a/node_modules/redis/lib/individualCommands.js
+++ b/node_modules/redis/lib/individualCommands.js
@@ -4,7 +4,7 @@ var utils = require('./utils');
var debug = require('./debug');
var Multi = require('./multi');
var Command = require('./command');
-var no_password_is_set = /no password is set/;
+var no_password_is_set = /no password is set|called without any password configured/;
var loading = /LOADING/;
var RedisClient = require('../').RedisClient;
@@ -180,7 +180,7 @@ Multi.prototype.info = Multi.prototype.INFO = function info (section, callback)
return this;
};
-function auth_callback (self, pass, callback) {
+function auth_callback (self, pass, user, callback) {
return function (err, res) {
if (err) {
if (no_password_is_set.test(err.message)) {
@@ -191,7 +191,7 @@ function auth_callback (self, pass, callback) {
// If redis is still loading the db, it will not authenticate and everything else will fail
debug('Redis still loading, trying to authenticate later');
setTimeout(function () {
- self.auth(pass, callback);
+ self.auth(pass, user, callback);
}, 100);
return;
}
@@ -200,25 +200,37 @@ function auth_callback (self, pass, callback) {
};
}
-RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (pass, callback) {
+RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (pass, user, callback) {
debug('Sending auth to ' + this.address + ' id ' + this.connection_id);
+ // Backward compatibility support for auth with password only
+ if (user instanceof Function) {
+ callback = user;
+ user = null;
+ }
// Stash auth for connect and reconnect.
this.auth_pass = pass;
+ this.auth_user = user;
var ready = this.ready;
this.ready = ready || this.offline_queue.length === 0;
- var tmp = this.internal_send_command(new Command('auth', [pass], auth_callback(this, pass, callback)));
+ var tmp = this.internal_send_command(new Command('auth', user ? [user, pass] : [pass], auth_callback(this, pass, user, callback)));
this.ready = ready;
return tmp;
};
// Only works with batch, not in a transaction
-Multi.prototype.auth = Multi.prototype.AUTH = function auth (pass, callback) {
+Multi.prototype.auth = Multi.prototype.AUTH = function auth (pass, user, callback) {
debug('Sending auth to ' + this.address + ' id ' + this.connection_id);
+ // Backward compatibility support for auth with password only
+ if (user instanceof Function) {
+ callback = user;
+ user = null;
+ }
// Stash auth for connect and reconnect.
this.auth_pass = pass;
- this.queue.push(new Command('auth', [pass], auth_callback(this._client, callback)));
+ this.auth_user = user;
+ this.queue.push(new Command('auth', user ? [user, pass] : [pass], auth_callback(this._client, pass, user, callback)));
return this;
};
diff --git a/node_modules/redis/lib/multi.js b/node_modules/redis/lib/multi.js
old mode 100755
new mode 100644
index 63f5d21..d89cffb
--- a/node_modules/redis/lib/multi.js
+++ b/node_modules/redis/lib/multi.js
@@ -1,6 +1,6 @@
'use strict';
-var Queue = require('double-ended-queue');
+var Queue = require('denque');
var utils = require('./utils');
var Command = require('./command');
diff --git a/node_modules/redis/lib/utils.js b/node_modules/redis/lib/utils.js
old mode 100755
new mode 100644
index 52e58ec..d0336ae
--- a/node_modules/redis/lib/utils.js
+++ b/node_modules/redis/lib/utils.js
@@ -127,7 +127,7 @@ module.exports = {
reply_to_object: replyToObject,
print: print,
err_code: /^([A-Z]+)\s+(.+)$/,
- monitor_regex: /^[0-9]{10,11}\.[0-9]+ \[[0-9]+ .+\]( ".+?")+$/,
+ monitor_regex: /^[0-9]{10,11}\.[0-9]+ \[[0-9]+ .+\].*"$/,
clone: convenienceClone,
callback_or_emit: callbackOrEmit,
reply_in_order: replyInOrder
diff --git a/node_modules/redis/node_modules/denque/CHANGELOG.md b/node_modules/redis/node_modules/denque/CHANGELOG.md
new file mode 100644
index 0000000..bb5ffb6
--- /dev/null
+++ b/node_modules/redis/node_modules/denque/CHANGELOG.md
@@ -0,0 +1,4 @@
+## 1.5.0
+
+ - feat: adds capacity option for circular buffers (#27)
+
diff --git a/node_modules/redis/node_modules/denque/LICENSE b/node_modules/redis/node_modules/denque/LICENSE
new file mode 100644
index 0000000..fd22a2d
--- /dev/null
+++ b/node_modules/redis/node_modules/denque/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2018 Mike Diarmid (Salakar)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this library except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/node_modules/redis/node_modules/denque/README.md b/node_modules/redis/node_modules/denque/README.md
new file mode 100644
index 0000000..6821e0d
--- /dev/null
+++ b/node_modules/redis/node_modules/denque/README.md
@@ -0,0 +1,362 @@
+
+
+
\ No newline at end of file
diff --git a/node_modules/socket.io-adapter/.npmignore b/node_modules/socket.io-adapter/.npmignore
deleted file mode 100755
index 3c3629e..0000000
--- a/node_modules/socket.io-adapter/.npmignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
diff --git a/node_modules/socket.io-adapter/Readme.md b/node_modules/socket.io-adapter/Readme.md
index 1327723..75cdc69 100755
--- a/node_modules/socket.io-adapter/Readme.md
+++ b/node_modules/socket.io-adapter/Readme.md
@@ -6,7 +6,7 @@ Default socket.io in-memory adapter class.
## How to use
This module is not intended for end-user usage, but can be used as an
-interface to inherit from from other adapters you might want to build.
+interface to inherit from other adapters you might want to build.
As an example of an adapter that builds on top of this, please take a look
at [socket.io-redis](https://github.com/learnboost/socket.io-redis).
diff --git a/node_modules/socket.io-adapter/index.js b/node_modules/socket.io-adapter/index.js
index aeb5b6e..f21dcbd 100755
--- a/node_modules/socket.io-adapter/index.js
+++ b/node_modules/socket.io-adapter/index.js
@@ -74,8 +74,8 @@ Adapter.prototype.addAll = function(id, rooms, fn){
*/
Adapter.prototype.del = function(id, room, fn){
- this.sids[id] = this.sids[id] || {};
- delete this.sids[id][room];
+ if (this.sids[id]) delete this.sids[id][room];
+
if (this.rooms.hasOwnProperty(room)) {
this.rooms[room].del(id);
if (this.rooms[room].length === 0) delete this.rooms[room];
diff --git a/node_modules/socket.io-adapter/package.json b/node_modules/socket.io-adapter/package.json
index d10297c..386c88e 100755
--- a/node_modules/socket.io-adapter/package.json
+++ b/node_modules/socket.io-adapter/package.json
@@ -1,8 +1,8 @@
{
"_from": "socket.io-adapter@~1.1.0",
- "_id": "socket.io-adapter@1.1.1",
+ "_id": "socket.io-adapter@1.1.2",
"_inBundle": false,
- "_integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=",
+ "_integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==",
"_location": "/socket.io-adapter",
"_phantomChildren": {},
"_requested": {
@@ -18,10 +18,10 @@
"_requiredBy": [
"/socket.io"
],
- "_resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz",
- "_shasum": "2a805e8a14d6372124dd9159ad4502f8cb07f06b",
+ "_resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz",
+ "_shasum": "ab3f0d6f66b8fc7fca3959ab5991f82221789be9",
"_spec": "socket.io-adapter@~1.1.0",
- "_where": "/Users/Xtrendence/Documents/Website/Node Projects/x-chat/node_modules/socket.io",
+ "_where": "C:\\Users\\Xtrendence\\Documents\\GitHub\\X-Chat\\node_modules\\socket.io",
"bugs": {
"url": "https://github.com/socketio/socket.io-adapter/issues"
},
@@ -35,5 +35,5 @@
"type": "git",
"url": "git://github.com/socketio/socket.io-adapter.git"
},
- "version": "1.1.1"
+ "version": "1.1.2"
}
diff --git a/node_modules/socket.io-client/CHANGELOG.md b/node_modules/socket.io-client/CHANGELOG.md
new file mode 100644
index 0000000..b1e87ea
--- /dev/null
+++ b/node_modules/socket.io-client/CHANGELOG.md
@@ -0,0 +1,20 @@
+# [2.4.0](https://github.com/Automattic/socket.io-client/compare/2.3.1...2.4.0) (2021-01-04)
+
+The minor bump is matching the bump of the server, but there is no new feature in this release.
+
+
+## [2.3.1](https://github.com/socketio/socket.io-client/compare/2.3.0...2.3.1) (2020-09-30)
+
+The `debug` dependency has been reverted to `~3.1.0`, as the newer versions contains ES6 syntax which breaks in IE
+browsers.
+
+Please note that this only applied to users that bundle the Socket.IO client in their application, with webpack for
+example, as the "official" bundles (in the dist/ folder) were already transpiled with babel.
+
+For webpack users, you can also take a look at the [webpack-remove-debug](https://github.com/johngodley/webpack-remove-debug)
+plugin.
+
+### Bug Fixes
+
+* fix reconnection after opening socket asynchronously ([#1253](https://github.com/socketio/socket.io-client/issues/1253)) ([050108b](https://github.com/Automattic/socket.io-client/commit/050108b2281effda086b197cf174ee2e8e1aad79))
+
diff --git a/node_modules/socket.io-client/README.md b/node_modules/socket.io-client/README.md
index b4c1856..bf7b5de 100755
--- a/node_modules/socket.io-client/README.md
+++ b/node_modules/socket.io-client/README.md
@@ -1,7 +1,7 @@
# socket.io-client
-[![Build Status](https://secure.travis-ci.org/socketio/socket.io-client.svg?branch=master)](http://travis-ci.org/socketio/socket.io-client)
+[![Build Status](https://github.com/socketio/socket.io-client/workflows/CI/badge.svg)](https://github.com/socketio/socket.io-client/actions)
[![Dependency Status](https://david-dm.org/socketio/socket.io-client.svg)](https://david-dm.org/socketio/socket.io-client)
[![devDependency Status](https://david-dm.org/socketio/socket.io-client/dev-status.svg)](https://david-dm.org/socketio/socket.io-client#info=devDependencies)
[![NPM version](https://badge.fury.io/js/socket.io-client.svg)](https://www.npmjs.com/package/socket.io-client)
@@ -14,12 +14,12 @@
A standalone build of `socket.io-client` is exposed automatically by the
socket.io server as `/socket.io/socket.io.js`. Alternatively you can
-serve the file `socket.io.js` found in the `dist` folder.
+serve the file `socket.io.js` found in the `dist` folder or include it via [CDN](https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js).
```html