aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CHANGELOG.md14
-rw-r--r--clientSource/package-lock.json59
-rw-r--r--clientSource/package.json2
-rw-r--r--package-lock.json1979
-rw-r--r--package.json5
-rw-r--r--server/main.js13
-rw-r--r--server/package-lock.json19
-rw-r--r--server/package.json7
-rw-r--r--server/src/commands/admin/addmod.js27
-rw-r--r--server/src/commands/admin/listusers.js35
-rw-r--r--server/src/commands/admin/reload.js21
-rw-r--r--server/src/commands/admin/removemod.js29
-rw-r--r--server/src/commands/admin/saveconfig.js23
-rw-r--r--server/src/commands/admin/shout.js19
-rw-r--r--server/src/commands/core/changenick.js67
-rw-r--r--server/src/commands/core/chat.js69
-rw-r--r--server/src/commands/core/emote.js53
-rw-r--r--server/src/commands/core/help.js47
-rw-r--r--server/src/commands/core/invite.js37
-rw-r--r--server/src/commands/core/join.js67
-rw-r--r--server/src/commands/core/morestats.js42
-rw-r--r--server/src/commands/core/move.js49
-rw-r--r--server/src/commands/core/ping.js11
-rw-r--r--server/src/commands/core/stats.js22
-rw-r--r--server/src/commands/core/whisper.js69
-rw-r--r--server/src/commands/internal/disconnect.js17
-rw-r--r--server/src/commands/internal/legacylayer.js19
-rw-r--r--server/src/commands/internal/socketreply.js15
-rw-r--r--server/src/commands/mod/ban.js31
-rw-r--r--server/src/commands/mod/dumb.js85
-rw-r--r--server/src/commands/mod/kick.js37
-rw-r--r--server/src/commands/mod/moveuser.js59
-rw-r--r--server/src/commands/mod/speak.js33
-rw-r--r--server/src/commands/mod/unban.js22
-rw-r--r--server/src/commands/mod/unbanall.js19
-rw-r--r--server/src/scripts/configLib/SetupWizard.js47
-rw-r--r--server/src/scripts/configure.js18
-rw-r--r--server/src/scripts/setupSchema/Banner.js12
-rw-r--r--server/src/scripts/setupSchema/Questions.js20
-rw-r--r--server/src/serverLib/CommandManager.js201
-rw-r--r--server/src/serverLib/ConfigManager.js74
-rw-r--r--server/src/serverLib/CoreApp.js84
-rw-r--r--server/src/serverLib/ImportsManager.js87
-rw-r--r--server/src/serverLib/MainServer.js376
-rw-r--r--server/src/serverLib/RateLimiter.js105
-rw-r--r--server/src/serverLib/StatsManager.js63
-rw-r--r--server/src/serverLib/index.js14
-rw-r--r--server/src/utility/Constants.js19
48 files changed, 1541 insertions, 2701 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 27811ba..20ee736 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,13 +3,25 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
+## [2.1.92 pre 2.2] - 2019-11-06
+### Added
+- (Server) `./server/src/utility/` directory
+- (Server) `Constants.js` class in `utility`
+- (Server) `esm` module to transpile ES6
+
+### Changed
+- (Server) Changed ES5 styling to ES6
+- (Server) And improved source comments
+- (Server) Minor code format changes
+- (Server) Updated all dependencies (be sure to update your local copy with the new packages)
+
## [2.1.91 pre 2.2] - 2019-08-17
### Added
- (Client) Markdown engine
- (Client) Imgur based image posting (through markdown)
### Changed
-- (Client) Removed cloudflare references making hack.chat is self-hosted again
+- (Client) Removed cloudflare references making hack.chat self-hosted again
- (Client) The way messages are pushed, closing an xss vuln in PRs 985dd6f and 9fcb235
- (Client) Side bar layout
- (Client) Fixed some options not storing
diff --git a/clientSource/package-lock.json b/clientSource/package-lock.json
index b08a515..85b9e00 100644
--- a/clientSource/package-lock.json
+++ b/clientSource/package-lock.json
@@ -5,9 +5,12 @@
"requires": true,
"dependencies": {
"async": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz",
- "integrity": "sha1-rDYTsdqb7RtHUQu0ZRuJMeRxRsc="
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "requires": {
+ "lodash": "^4.17.14"
+ }
},
"colors": {
"version": "1.0.3",
@@ -28,14 +31,14 @@
}
},
"ecstatic": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-1.4.1.tgz",
- "integrity": "sha1-Mst7b6LikNWGaGdNEV6PDD1WfWo=",
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz",
+ "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==",
"requires": {
- "he": "^0.5.0",
- "mime": "^1.2.11",
+ "he": "^1.1.1",
+ "mime": "^1.6.0",
"minimist": "^1.1.0",
- "url-join": "^1.0.0"
+ "url-join": "^2.0.5"
}
},
"eventemitter3": {
@@ -52,9 +55,9 @@
}
},
"he": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/he/-/he-0.5.0.tgz",
- "integrity": "sha1-LAX/rvkLaOhg8/0rVO9YCYknfuI="
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"http-proxy": {
"version": "1.18.0",
@@ -67,20 +70,25 @@
}
},
"http-server": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.9.0.tgz",
- "integrity": "sha1-jxsGvcczYY1NxCgxx7oa/04GABo=",
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.11.1.tgz",
+ "integrity": "sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==",
"requires": {
"colors": "1.0.3",
"corser": "~2.0.0",
- "ecstatic": "^1.4.0",
+ "ecstatic": "^3.0.0",
"http-proxy": "^1.8.1",
"opener": "~1.4.0",
"optimist": "0.6.x",
- "portfinder": "0.4.x",
+ "portfinder": "^1.0.13",
"union": "~0.4.3"
}
},
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ },
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
@@ -133,12 +141,13 @@
}
},
"portfinder": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-0.4.0.tgz",
- "integrity": "sha1-o/+t/6/k+5jgYBqF7aJ8J86Eyh4=",
+ "version": "1.0.25",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz",
+ "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==",
"requires": {
- "async": "0.9.0",
- "mkdirp": "0.5.x"
+ "async": "^2.6.2",
+ "debug": "^3.1.1",
+ "mkdirp": "^0.5.1"
}
},
"qs": {
@@ -160,9 +169,9 @@
}
},
"url-join": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz",
- "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg="
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz",
+ "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg="
},
"wordwrap": {
"version": "0.0.3",
diff --git a/clientSource/package.json b/clientSource/package.json
index 7abba43..63df0d3 100644
--- a/clientSource/package.json
+++ b/clientSource/package.json
@@ -17,6 +17,6 @@
"author": "Marzavec",
"license": "WTFPL",
"dependencies": {
- "http-server": "^0.9.0"
+ "http-server": "^0.11.1"
}
}
diff --git a/package-lock.json b/package-lock.json
index d79ef14..5ba3eb5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -55,6 +55,16 @@
"proxy-agent": "^3.1.0",
"semver": "^5.5.0",
"ws": "^5.1.0"
+ },
+ "dependencies": {
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ }
}
},
"@pm2/agent-node": {
@@ -68,6 +78,14 @@
"ws": "^6.0.0"
},
"dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
"ws": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
@@ -97,6 +115,14 @@
"tslib": "1.9.3"
},
"dependencies": {
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
@@ -129,6 +155,14 @@
"ws": "^3.0.0"
},
"dependencies": {
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -147,11 +181,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
- "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=="
- },
"ws": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
@@ -199,22 +228,12 @@
}
},
"anymatch": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
- "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+ "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
"requires": {
- "micromatch": "^3.1.4",
- "normalize-path": "^2.1.1"
- },
- "dependencies": {
- "normalize-path": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
- "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
- "requires": {
- "remove-trailing-separator": "^1.0.1"
- }
- }
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
}
},
"argparse": {
@@ -232,48 +251,15 @@
}
}
},
- "arr-diff": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
- "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
- },
- "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=="
- },
- "arr-union": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
- "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
- },
- "array-unique": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
- "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
- },
- "assign-symbols": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
- "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
- },
"ast-types": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.2.tgz",
"integrity": "sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA=="
},
"async": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
- "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
- "requires": {
- "lodash": "^4.17.14"
- }
- },
- "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=="
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.1.0.tgz",
+ "integrity": "sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ=="
},
"async-limiter": {
"version": "1.0.1",
@@ -289,11 +275,6 @@
"shimmer": "^1.1.0"
}
},
- "atob": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
- "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
- },
"axios": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz",
@@ -308,60 +289,10 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
- "base": {
- "version": "0.11.2",
- "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
- "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
- "requires": {
- "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"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "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==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "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==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
"binary-extensions": {
- "version": "1.13.1",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
- "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw=="
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
+ "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow=="
},
"blessed": {
"version": "0.1.81",
@@ -383,30 +314,11 @@
}
},
"braces": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
- "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
- "requires": {
- "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"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "requires": {
+ "fill-range": "^7.0.1"
}
},
"buffer-from": {
@@ -419,22 +331,6 @@
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
},
- "cache-base": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
- "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
- "requires": {
- "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"
- }
- },
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -451,43 +347,18 @@
"integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY="
},
"chokidar": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
- "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
- "requires": {
- "anymatch": "^2.0.0",
- "async-each": "^1.0.1",
- "braces": "^2.3.2",
- "fsevents": "^1.2.7",
- "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"
- }
- },
- "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==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz",
+ "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==",
"requires": {
- "arr-union": "^3.1.0",
- "define-property": "^0.2.5",
- "isobject": "^3.0.0",
- "static-extend": "^0.1.1"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- }
+ "anymatch": "~3.1.1",
+ "braces": "~3.0.2",
+ "fsevents": "~2.1.1",
+ "glob-parent": "~5.1.0",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.2.0"
}
},
"cli-table-redemption": {
@@ -527,15 +398,6 @@
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
},
- "collection-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
- "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
- "requires": {
- "map-visit": "^1.0.0",
- "object-visit": "^1.0.0"
- }
- },
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -554,11 +416,6 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag=="
},
- "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=="
- },
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -573,20 +430,15 @@
"emitter-listener": "^1.1.1"
}
},
- "copy-descriptor": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
- "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
- },
"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="
},
"cron": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/cron/-/cron-1.7.2.tgz",
- "integrity": "sha512-+SaJ2OfeRvfQqwXQ2kgr0Y5pzBR/lijf5OpnnaruwWnmI799JfWr2jN2ItOV9s3A/+TFOt6mxvKzQq5F0Jp6VQ==",
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/cron/-/cron-1.7.1.tgz",
+ "integrity": "sha512-gmMB/pJcqUVs/NklR1sCGlNYM7TizEw+1gebz20BMc/8bTm/r7QUp3ZPSPlG8Z5XRlvb7qhjEjq/+bdIfUCL2A==",
"requires": {
"moment-timezone": "^0.5.x"
}
@@ -597,9 +449,9 @@
"integrity": "sha1-lQL18BVKLVoioCPnn3HMk2+m728="
},
"data-uri-to-buffer": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz",
- "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA=="
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz",
+ "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ=="
},
"date-fns": {
"version": "1.30.1",
@@ -607,60 +459,18 @@
"integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw=="
},
"debug": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
- "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
- "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="
- },
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
},
- "define-property": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
- "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
- "requires": {
- "is-descriptor": "^1.0.2",
- "isobject": "^3.0.1"
- },
- "dependencies": {
- "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==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "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==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
"degenerator": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz",
@@ -719,6 +529,11 @@
"source-map": "~0.6.1"
}
},
+ "esm": {
+ "version": "3.2.25",
+ "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
+ "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="
+ },
"esprima": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
@@ -744,134 +559,11 @@
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz",
"integrity": "sha1-YZegldX7a1folC9v1+qtY6CclFI="
},
- "expand-brackets": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
- "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
- "requires": {
- "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"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "requires": {
- "ms": "2.0.0"
- }
- },
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
- }
- }
- },
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
- "extend-shallow": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
- "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
- "requires": {
- "assign-symbols": "^1.0.0",
- "is-extendable": "^1.0.1"
- },
- "dependencies": {
- "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==",
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
- }
- },
- "extglob": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
- "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
- "requires": {
- "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"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "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==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "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==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
"fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
@@ -888,24 +580,11 @@
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
"fill-range": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
- "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1",
- "to-regex-range": "^2.1.0"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "requires": {
+ "to-regex-range": "^5.0.1"
}
},
"follow-redirects": {
@@ -931,504 +610,16 @@
}
}
},
- "for-in": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
- "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
- },
- "fragment-cache": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
- "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
- "requires": {
- "map-cache": "^0.2.2"
- }
- },
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
- "version": "1.2.9",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
- "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
- "optional": true,
- "requires": {
- "nan": "^2.12.1",
- "node-pre-gyp": "^0.12.0"
- },
- "dependencies": {
- "abbrev": {
- "version": "1.1.1",
- "bundled": true,
- "optional": true
- },
- "ansi-regex": {
- "version": "2.1.1",
- "bundled": true,
- "optional": true
- },
- "aproba": {
- "version": "1.2.0",
- "bundled": true,
- "optional": true
- },
- "are-we-there-yet": {
- "version": "1.1.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "delegates": "^1.0.0",
- "readable-stream": "^2.0.6"
- }
- },
- "balanced-match": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "bundled": true,
- "optional": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "chownr": {
- "version": "1.1.1",
- "bundled": true,
- "optional": true
- },
- "code-point-at": {
- "version": "1.1.0",
- "bundled": true,
- "optional": true
- },
- "concat-map": {
- "version": "0.0.1",
- "bundled": true,
- "optional": true
- },
- "console-control-strings": {
- "version": "1.1.0",
- "bundled": true,
- "optional": true
- },
- "core-util-is": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "debug": {
- "version": "4.1.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "deep-extend": {
- "version": "0.6.0",
- "bundled": true,
- "optional": true
- },
- "delegates": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "detect-libc": {
- "version": "1.0.3",
- "bundled": true,
- "optional": true
- },
- "fs-minipass": {
- "version": "1.2.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "minipass": "^2.2.1"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "gauge": {
- "version": "2.7.4",
- "bundled": true,
- "optional": true,
- "requires": {
- "aproba": "^1.0.3",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.0",
- "object-assign": "^4.1.0",
- "signal-exit": "^3.0.0",
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wide-align": "^1.1.0"
- }
- },
- "glob": {
- "version": "7.1.3",
- "bundled": true,
- "optional": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "has-unicode": {
- "version": "2.0.1",
- "bundled": true,
- "optional": true
- },
- "iconv-lite": {
- "version": "0.4.24",
- "bundled": true,
- "optional": true,
- "requires": {
- "safer-buffer": ">= 2.1.2 < 3"
- }
- },
- "ignore-walk": {
- "version": "3.0.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "minimatch": "^3.0.4"
- }
- },
- "inflight": {
- "version": "1.0.6",
- "bundled": true,
- "optional": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.3",
- "bundled": true,
- "optional": true
- },
- "ini": {
- "version": "1.3.5",
- "bundled": true,
- "optional": true
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "isarray": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "minimatch": {
- "version": "3.0.4",
- "bundled": true,
- "optional": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "minimist": {
- "version": "0.0.8",
- "bundled": true,
- "optional": true
- },
- "minipass": {
- "version": "2.3.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
- }
- },
- "minizlib": {
- "version": "1.2.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "minipass": "^2.2.1"
- }
- },
- "mkdirp": {
- "version": "0.5.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "minimist": "0.0.8"
- }
- },
- "ms": {
- "version": "2.1.1",
- "bundled": true,
- "optional": true
- },
- "needle": {
- "version": "2.3.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "debug": "^4.1.0",
- "iconv-lite": "^0.4.4",
- "sax": "^1.2.4"
- }
- },
- "node-pre-gyp": {
- "version": "0.12.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "detect-libc": "^1.0.2",
- "mkdirp": "^0.5.1",
- "needle": "^2.2.1",
- "nopt": "^4.0.1",
- "npm-packlist": "^1.1.6",
- "npmlog": "^4.0.2",
- "rc": "^1.2.7",
- "rimraf": "^2.6.1",
- "semver": "^5.3.0",
- "tar": "^4"
- }
- },
- "nopt": {
- "version": "4.0.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "abbrev": "1",
- "osenv": "^0.1.4"
- }
- },
- "npm-bundled": {
- "version": "1.0.6",
- "bundled": true,
- "optional": true
- },
- "npm-packlist": {
- "version": "1.4.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "ignore-walk": "^3.0.1",
- "npm-bundled": "^1.0.1"
- }
- },
- "npmlog": {
- "version": "4.1.2",
- "bundled": true,
- "optional": true,
- "requires": {
- "are-we-there-yet": "~1.1.2",
- "console-control-strings": "~1.1.0",
- "gauge": "~2.7.3",
- "set-blocking": "~2.0.0"
- }
- },
- "number-is-nan": {
- "version": "1.0.1",
- "bundled": true,
- "optional": true
- },
- "object-assign": {
- "version": "4.1.1",
- "bundled": true,
- "optional": true
- },
- "once": {
- "version": "1.4.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "wrappy": "1"
- }
- },
- "os-homedir": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "os-tmpdir": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "osenv": {
- "version": "0.1.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "os-homedir": "^1.0.0",
- "os-tmpdir": "^1.0.0"
- }
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "bundled": true,
- "optional": true
- },
- "process-nextick-args": {
- "version": "2.0.0",
- "bundled": true,
- "optional": true
- },
- "rc": {
- "version": "1.2.8",
- "bundled": true,
- "optional": true,
- "requires": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "dependencies": {
- "minimist": {
- "version": "1.2.0",
- "bundled": true,
- "optional": true
- }
- }
- },
- "readable-stream": {
- "version": "2.3.6",
- "bundled": true,
- "optional": true,
- "requires": {
- "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"
- }
- },
- "rimraf": {
- "version": "2.6.3",
- "bundled": true,
- "optional": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "bundled": true,
- "optional": true
- },
- "safer-buffer": {
- "version": "2.1.2",
- "bundled": true,
- "optional": true
- },
- "sax": {
- "version": "1.2.4",
- "bundled": true,
- "optional": true
- },
- "semver": {
- "version": "5.7.0",
- "bundled": true,
- "optional": true
- },
- "set-blocking": {
- "version": "2.0.0",
- "bundled": true,
- "optional": true
- },
- "signal-exit": {
- "version": "3.0.2",
- "bundled": true,
- "optional": true
- },
- "string-width": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- },
- "strip-json-comments": {
- "version": "2.0.1",
- "bundled": true,
- "optional": true
- },
- "tar": {
- "version": "4.4.8",
- "bundled": true,
- "optional": true,
- "requires": {
- "chownr": "^1.1.1",
- "fs-minipass": "^1.2.5",
- "minipass": "^2.3.4",
- "minizlib": "^1.1.1",
- "mkdirp": "^0.5.0",
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.2"
- }
- },
- "util-deprecate": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "wide-align": {
- "version": "1.1.3",
- "bundled": true,
- "optional": true,
- "requires": {
- "string-width": "^1.0.2 || 2"
- }
- },
- "wrappy": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "yallist": {
- "version": "3.0.3",
- "bundled": true,
- "optional": true
- }
- }
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.1.tgz",
+ "integrity": "sha512-4FRPXWETxtigtJW/gxzEDsX1LVbPAM93VleB83kZB+ellqbHMkyt2aJfuzNLRvFPnGi6bcE5SvfxgbXPeKteJw==",
+ "optional": true
},
"ftp": {
"version": "0.3.10",
@@ -1453,33 +644,33 @@
}
},
"get-uri": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.3.tgz",
- "integrity": "sha512-x5j6Ks7FOgLD/GlvjKwgu7wdmMR55iuRHhn8hj/+gA+eSbxQvZ+AEomq+3MgVEZj1vpi738QahGbCCSIDtXtkw==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.4.tgz",
+ "integrity": "sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==",
"requires": {
- "data-uri-to-buffer": "2",
- "debug": "4",
+ "data-uri-to-buffer": "1",
+ "debug": "2",
"extend": "~3.0.2",
"file-uri-to-path": "1",
"ftp": "~0.3.10",
- "readable-stream": "3"
+ "readable-stream": "2"
},
"dependencies": {
"debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
- "ms": "^2.1.1"
+ "ms": "2.0.0"
}
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
- "get-value": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
- "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
- },
"git-node-fs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz",
@@ -1491,9 +682,9 @@
"integrity": "sha1-WZrBkrcYdYJeE6RF86bgURjC90U="
},
"glob": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
- "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -1504,29 +695,13 @@
}
},
"glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
+ "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
"requires": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- },
- "dependencies": {
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
+ "is-glob": "^4.0.1"
}
},
- "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=="
- },
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
@@ -1540,40 +715,6 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
- "has-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
- "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
- "requires": {
- "get-value": "^2.0.6",
- "has-values": "^1.0.0",
- "isobject": "^3.0.0"
- }
- },
- "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=",
- "requires": {
- "is-number": "^3.0.0",
- "kind-of": "^4.0.0"
- },
- "dependencies": {
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- },
- "kind-of": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
- "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
"http-errors": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
@@ -1611,12 +752,22 @@
}
},
"https-proxy-agent": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz",
- "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz",
+ "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==",
"requires": {
"agent-base": "^4.3.0",
"debug": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
}
},
"iconv-lite": {
@@ -1656,35 +807,12 @@
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
},
- "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=",
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
"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=",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"requires": {
- "binary-extensions": "^1.0.0"
+ "binary-extensions": "^2.0.0"
}
},
"is-buffer": {
@@ -1692,51 +820,6 @@
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
"integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
},
- "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=",
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
- "requires": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
- },
- "dependencies": {
- "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=="
- }
- }
- },
- "is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
- },
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -1751,51 +834,15 @@
}
},
"is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "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==",
- "requires": {
- "isobject": "^3.0.1"
- }
- },
- "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=="
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
- },
"js-git": {
"version": "0.7.8",
"resolved": "https://registry.npmjs.org/js-git/-/js-git-0.7.8.tgz",
@@ -1807,11 +854,6 @@
"pako": "^0.2.5"
}
},
- "kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
- },
"lazy": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz",
@@ -1827,9 +869,9 @@
}
},
"lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ "version": "4.17.14",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
+ "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw=="
},
"lodash.findindex": {
"version": "4.6.0",
@@ -1857,45 +899,11 @@
"integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg=="
},
"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==",
- "requires": {
- "pseudomap": "^1.0.2",
- "yallist": "^2.1.2"
- }
- },
- "map-cache": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
- "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
- },
- "map-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
- "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"requires": {
- "object-visit": "^1.0.0"
- }
- },
- "micromatch": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
- "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
- "requires": {
- "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"
+ "yallist": "^3.0.2"
}
},
"minimatch": {
@@ -1911,25 +919,6 @@
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
- "mixin-deep": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
- "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
- "requires": {
- "for-in": "^1.0.2",
- "is-extendable": "^1.0.1"
- },
- "dependencies": {
- "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==",
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
- }
- },
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
@@ -1949,9 +938,9 @@
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"moment-timezone": {
- "version": "0.5.26",
- "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.26.tgz",
- "integrity": "sha512-sFP4cgEKTCymBBKgoxZjYzlSovC20Y6J7y3nanDc5RoBIXKlZhoYwBoZGe3flwU6A372AcRwScH8KiwV6zjy1g==",
+ "version": "0.5.27",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.27.tgz",
+ "integrity": "sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw==",
"requires": {
"moment": ">= 2.9.0"
}
@@ -1966,30 +955,6 @@
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
},
- "nan": {
- "version": "2.14.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
- "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
- "optional": true
- },
- "nanomatch": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
- "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
- "requires": {
- "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"
- }
- },
"needle": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz",
@@ -1998,6 +963,16 @@
"debug": "^3.2.6",
"iconv-lite": "^0.4.4",
"sax": "^1.2.4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
}
},
"netmask": {
@@ -2026,55 +1001,6 @@
}
}
},
- "object-copy": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
- "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
- "requires": {
- "copy-descriptor": "^0.1.0",
- "define-property": "^0.2.5",
- "kind-of": "^3.0.3"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "object-visit": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
- "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
- "requires": {
- "isobject": "^3.0.0"
- }
- },
- "object.pick": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
- "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
- "requires": {
- "isobject": "^3.0.1"
- }
- },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -2084,28 +1010,28 @@
}
},
"optionator": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
- "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
"requires": {
"deep-is": "~0.1.3",
- "fast-levenshtein": "~2.0.4",
+ "fast-levenshtein": "~2.0.6",
"levn": "~0.3.0",
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2",
- "wordwrap": "~1.0.0"
+ "word-wrap": "~1.2.3"
}
},
"pac-proxy-agent": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz",
- "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.1.tgz",
+ "integrity": "sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==",
"requires": {
"agent-base": "^4.2.0",
- "debug": "^3.1.0",
+ "debug": "^4.1.1",
"get-uri": "^2.0.0",
"http-proxy-agent": "^2.1.0",
- "https-proxy-agent": "^2.2.1",
+ "https-proxy-agent": "^3.0.0",
"pac-resolver": "^3.0.0",
"raw-body": "^2.2.0",
"socks-proxy-agent": "^4.0.1"
@@ -2128,16 +1054,6 @@
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
"integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
},
- "pascalcase": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
- "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
- },
- "path-dirname": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
- "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
- },
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@@ -2148,6 +1064,11 @@
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
},
+ "picomatch": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz",
+ "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA=="
+ },
"pidusage": {
"version": "2.0.17",
"resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.17.tgz",
@@ -2157,40 +1078,42 @@
}
},
"pm2": {
- "version": "3.5.1",
- "resolved": "https://registry.npmjs.org/pm2/-/pm2-3.5.1.tgz",
- "integrity": "sha512-pDPBetbI48JDynxmtSPNSKRDk/LRbhsHrJ/WSCKVD1TUNnb6XNMe6GzO7DCNijJBvdaQ+u1WxNudxqExlXdhEw==",
- "requires": {
- "@pm2/agent": "^0.5.22",
- "@pm2/io": "^4.1.2",
- "@pm2/js-api": "^0.5.43",
- "async": "^2.6.1",
- "blessed": "^0.1.81",
- "chalk": "^2.4.1",
- "chokidar": "^2.0.4",
- "cli-table-redemption": "^1.0.0",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/pm2/-/pm2-4.1.2.tgz",
+ "integrity": "sha512-HkNP3K79PmqxkxfgNX/t5rsfWLNMc89KVKDm2Xoju0MU3TbGZSc2rWLZffgEitITsMcPpkKtZmAJBcxMXvURFA==",
+ "requires": {
+ "@pm2/agent": "^0.5.26",
+ "@pm2/io": "^4.3.2",
+ "@pm2/js-api": "^0.5.60",
+ "async": "^3.1.0",
+ "blessed": "0.1.81",
+ "chalk": "2.4.2",
+ "chokidar": "^3.2.0",
+ "cli-table-redemption": "1.0.1",
"commander": "2.15.1",
- "cron": "^1.3",
- "date-fns": "^1.29.0",
- "debug": "^3.1",
+ "cron": "1.7.1",
+ "date-fns": "1.30.1",
+ "debug": "4.1.1",
"eventemitter2": "5.0.1",
"fclone": "1.0.11",
+ "lodash": "4.17.14",
"mkdirp": "0.5.1",
- "moment": "^2.22.2",
- "needle": "^2.2.1",
- "pidusage": "^2.0.14",
+ "moment": "2.24.0",
+ "needle": "2.4.0",
+ "pidusage": "2.0.17",
"pm2-axon": "3.3.0",
- "pm2-axon-rpc": "^0.5.1",
+ "pm2-axon-rpc": "0.5.1",
"pm2-deploy": "^0.4.0",
"pm2-multimeter": "^0.1.2",
"promptly": "^2",
+ "ps-list": "6.3.0",
"semver": "^5.5",
- "shelljs": "~0.8.2",
- "source-map-support": "^0.5.6",
- "sprintf-js": "1.1.1",
- "v8-compile-cache": "^2.0.0",
+ "shelljs": "0.8.3",
+ "source-map-support": "0.5.12",
+ "sprintf-js": "1.1.2",
+ "systeminformation": "^4.14.11",
"vizion": "~2.0.2",
- "yamljs": "^0.3.0"
+ "yamljs": "0.3.0"
}
},
"pm2-axon": {
@@ -2202,6 +1125,16 @@
"amp-message": "~0.1.1",
"debug": "^3.0",
"escape-regexp": "0.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
}
},
"pm2-axon-rpc": {
@@ -2210,6 +1143,16 @@
"integrity": "sha512-hT8gN3/j05895QLXpwg+Ws8PjO4AVID6Uf9StWpud9HB2homjc1KKCcI0vg9BNOt56FmrqKDT1NQgheIz35+sA==",
"requires": {
"debug": "^3.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
}
},
"pm2-deploy": {
@@ -2219,6 +1162,16 @@
"requires": {
"async": "^2.6",
"tv4": "^1.3"
+ },
+ "dependencies": {
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ }
}
},
"pm2-multimeter": {
@@ -2229,11 +1182,6 @@
"charm": "~0.1.1"
}
},
- "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="
- },
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -2253,16 +1201,16 @@
}
},
"proxy-agent": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.0.tgz",
- "integrity": "sha512-IkbZL4ClW3wwBL/ABFD2zJ8iP84CY0uKMvBPk/OceQe/cEjrxzN1pMHsLwhbzUoRhG9QbSxYC+Z7LBkTiBNvrA==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.1.tgz",
+ "integrity": "sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw==",
"requires": {
"agent-base": "^4.2.0",
- "debug": "^3.1.0",
+ "debug": "4",
"http-proxy-agent": "^2.1.0",
- "https-proxy-agent": "^2.2.1",
- "lru-cache": "^4.1.2",
- "pac-proxy-agent": "^3.0.0",
+ "https-proxy-agent": "^3.0.0",
+ "lru-cache": "^5.1.1",
+ "pac-proxy-agent": "^3.0.1",
"proxy-from-env": "^1.0.0",
"socks-proxy-agent": "^4.0.1"
}
@@ -2272,10 +1220,10 @@
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
"integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4="
},
- "pseudomap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
- "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+ "ps-list": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/ps-list/-/ps-list-6.3.0.tgz",
+ "integrity": "sha512-qau0czUSB0fzSlBOQt0bo+I2v6R+xiQdj78e1BR/Qjfl5OHWJ/urXi8+ilw1eHe+5hSeDI1wrwVTgDp2wst4oA=="
},
"raw-body": {
"version": "2.4.1",
@@ -2297,33 +1245,17 @@
}
},
"readable-stream": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
- "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
- "requires": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "dependencies": {
- "string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "requires": {
- "safe-buffer": "~5.2.0"
- }
- }
- }
- },
- "readdirp": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
- "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
- "requires": {
- "graceful-fs": "^4.1.11",
- "micromatch": "^3.1.10",
- "readable-stream": "^2.0.2"
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "requires": {
+ "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"
},
"dependencies": {
"isarray": {
@@ -2331,25 +1263,6 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
- "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==",
- "requires": {
- "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"
- }
- },
- "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=="
- },
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -2360,6 +1273,14 @@
}
}
},
+ "readdirp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz",
+ "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==",
+ "requires": {
+ "picomatch": "^2.0.4"
+ }
+ },
"rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
@@ -2368,30 +1289,6 @@
"resolve": "^1.1.6"
}
},
- "regex-not": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
- "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
- "requires": {
- "extend-shallow": "^3.0.2",
- "safe-regex": "^1.1.0"
- }
- },
- "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="
- },
- "repeat-element": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
- "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g=="
- },
- "repeat-string": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
- "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
- },
"require-in-the-middle": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-4.0.1.tgz",
@@ -2400,16 +1297,6 @@
"debug": "^4.1.1",
"module-details-from-path": "^1.0.3",
"resolve": "^1.12.0"
- },
- "dependencies": {
- "debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
- "requires": {
- "ms": "^2.1.1"
- }
- }
}
},
"resolve": {
@@ -2420,28 +1307,10 @@
"path-parse": "^1.0.6"
}
},
- "resolve-url": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
- "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
- },
- "ret": {
- "version": "0.1.15",
- "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
- "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
- },
"safe-buffer": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
- "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
- },
- "safe-regex": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
- "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
- "requires": {
- "ret": "~0.1.10"
- }
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
@@ -2458,27 +1327,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
},
- "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==",
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-extendable": "^0.1.1",
- "is-plain-object": "^2.0.3",
- "split-string": "^3.0.1"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
"setprototypeof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
@@ -2505,137 +1353,17 @@
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
},
"smart-buffer": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz",
- "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw=="
- },
- "snapdragon": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
- "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
- "requires": {
- "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"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "requires": {
- "ms": "2.0.0"
- }
- },
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
- }
- }
- },
- "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==",
- "requires": {
- "define-property": "^1.0.0",
- "isobject": "^3.0.0",
- "snapdragon-util": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "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==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "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==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "snapdragon-util": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
- "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
- "requires": {
- "kind-of": "^3.2.0"
- },
- "dependencies": {
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz",
+ "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw=="
},
"socks": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz",
- "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==",
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz",
+ "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==",
"requires": {
- "ip": "^1.1.5",
- "smart-buffer": "4.0.2"
+ "ip": "1.1.5",
+ "smart-buffer": "^4.1.0"
}
},
"socks-proxy-agent": {
@@ -2662,63 +1390,19 @@
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
- "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==",
- "requires": {
- "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"
- }
- },
"source-map-support": {
- "version": "0.5.13",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
- "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "version": "0.5.12",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz",
+ "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==",
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
- "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="
- },
- "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==",
- "requires": {
- "extend-shallow": "^3.0.0"
- }
- },
"sprintf-js": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz",
- "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw="
- },
- "static-extend": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
- "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
- "requires": {
- "define-property": "^0.2.5",
- "object-copy": "^0.1.0"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- }
- }
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
},
"statuses": {
"version": "1.5.0",
@@ -2746,52 +1430,23 @@
"has-flag": "^3.0.0"
}
},
+ "systeminformation": {
+ "version": "4.14.17",
+ "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-4.14.17.tgz",
+ "integrity": "sha512-CQbT5vnkqNb3JNl41xr8sYA8AX7GoaWP55/jnmFNQY0XQmUuoFshSNUkCkxiDdEC1qu2Vg9s0jR6LLmVSmNJUw==",
+ "optional": true
+ },
"thunkify": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz",
"integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0="
},
- "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=",
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "to-regex": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
- "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
- "requires": {
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "regex-not": "^1.0.2",
- "safe-regex": "^1.1.0"
- }
- },
"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=",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"requires": {
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1"
+ "is-number": "^7.0.0"
}
},
"toidentifier": {
@@ -2822,78 +1477,11 @@
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
},
- "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==",
- "requires": {
- "arr-union": "^3.1.0",
- "get-value": "^2.0.6",
- "is-extendable": "^0.1.1",
- "set-value": "^2.0.1"
- }
- },
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
- "unset-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
- "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
- "requires": {
- "has-value": "^0.3.1",
- "isobject": "^3.0.0"
- },
- "dependencies": {
- "has-value": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
- "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
- "requires": {
- "get-value": "^2.0.3",
- "has-values": "^0.1.4",
- "isobject": "^2.0.0"
- },
- "dependencies": {
- "isobject": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
- "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
- "requires": {
- "isarray": "1.0.0"
- }
- }
- }
- },
- "has-values": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
- "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
- },
- "isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
- }
- }
- },
- "upath": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
- "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg=="
- },
- "urix": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
- "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI="
- },
- "use": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
- "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
- },
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -2904,11 +1492,6 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
},
- "v8-compile-cache": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",
- "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g=="
- },
"vizion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/vizion/-/vizion-2.0.2.tgz",
@@ -2934,10 +1517,10 @@
}
}
},
- "wordwrap": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
- "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
},
"wrappy": {
"version": "1.0.2",
@@ -2958,9 +1541,9 @@
"integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM="
},
"yallist": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
- "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
},
"yamljs": {
"version": "0.3.0",
diff --git a/package.json b/package.json
index 9edd245..b54c911 100644
--- a/package.json
+++ b/package.json
@@ -12,12 +12,13 @@
"npm": ">= 6.7.0"
},
"scripts": {
- "start": "pm2 start ./server/main.js --name hackchat-dev-server && cd ./clientSource && npm start && pm2 stop hackchat-dev-server",
+ "start": "pm2 start ./server/main.js --node-args=\"-r esm\" --name hackchat-dev-server && cd ./clientSource && npm start && pm2 stop hackchat-dev-server",
"postinstall": "cd ./clientSource && npm install && cd .. & cd ./server && npm install && npm run config"
},
"author": "Marzavec",
"license": "WTFPL",
"dependencies": {
- "pm2": "^3.5.1"
+ "esm": "^3.2.25",
+ "pm2": "^4.1.2"
}
}
diff --git a/server/main.js b/server/main.js
index 70042e8..b01d09d 100644
--- a/server/main.js
+++ b/server/main.js
@@ -1,15 +1,12 @@
/**
* HackChat main server entry point
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
+ * @author Marzavec ( https://github.com/marzavec )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
*/
-'use strict';
-
// import and initialize the core application
-const CoreApp = require('./src/serverLib/CoreApp');
+import { CoreApp } from './src/serverLib/CoreApp';
+
const coreApp = new CoreApp();
coreApp.init();
diff --git a/server/package-lock.json b/server/package-lock.json
index 27205bc..26fd58b 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -18,9 +18,9 @@
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
},
"async-limiter": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
- "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
},
"balanced-match": {
"version": "1.0.0",
@@ -104,6 +104,11 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
+ "esm": {
+ "version": "3.2.25",
+ "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
+ "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="
+ },
"eyes": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
@@ -350,11 +355,11 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz",
- "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz",
+ "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==",
"requires": {
- "async-limiter": "~1.0.0"
+ "async-limiter": "^1.0.0"
}
}
}
diff --git a/server/package.json b/server/package.json
index 51a149d..3eb733c 100644
--- a/server/package.json
+++ b/server/package.json
@@ -12,8 +12,8 @@
"npm": ">= 5.7.1"
},
"scripts": {
- "start": "node main.js",
- "config": "node src/scripts/configure.js"
+ "start": "node -r esm main.js",
+ "config": "node -r esm src/scripts/configure.js"
},
"author": "Marzavec",
"license": "WTFPL",
@@ -22,9 +22,10 @@
"common-tags": "^1.8.0",
"dateformat": "^3.0.3",
"didyoumean2": "^2.0.2",
+ "esm": "^3.2.25",
"fs-extra": "^7.0.1",
"prompt": "^1.0.0",
"readdir-recursive": "0.0.4",
- "ws": "^6.1.4"
+ "ws": "^7.2.0"
}
}
diff --git a/server/src/commands/admin/addmod.js b/server/src/commands/admin/addmod.js
index 6853a42..26cec40 100644
--- a/server/src/commands/admin/addmod.js
+++ b/server/src/commands/admin/addmod.js
@@ -3,26 +3,26 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// increase rate limit chance and ignore if not admin
- if (socket.uType != 'admin') {
- return server.police.frisk(socket.remoteAddress, 20);
+ if (socket.uType !== 'admin') {
+ return server.police.frisk(socket.address, 20);
}
// add new trip to config
core.config.mods.push({ trip: data.trip });
// find targets current connections
- let newMod = server.findSockets({ trip: data.trip });
+ const newMod = server.findSockets({ trip: data.trip });
if (newMod.length !== 0) {
- for (let i = 0, l = newMod.length; i < l; i++) {
+ for (let i = 0, l = newMod.length; i < l; i += 1) {
// upgrade privilages
newMod[i].uType = 'mod';
// inform new mod
server.send({
cmd: 'info',
- text: 'You are now a mod.'
+ text: 'You are now a mod.',
}, newMod[i]);
}
}
@@ -30,21 +30,22 @@ exports.run = async (core, server, socket, data) => {
// return success message
server.reply({
cmd: 'info',
- text: `Added mod trip: ${data.trip}, remember to run 'saveconfig' to make it permanent`
+ text: `Added mod trip: ${data.trip}, remember to run 'saveconfig' to make it permanent`,
}, socket);
// notify all mods
server.broadcast({
cmd: 'info',
- text: `Added mod: ${data.trip}`
+ text: `Added mod: ${data.trip}`,
}, { uType: 'mod' });
-};
-// module meta
-exports.requiredData = ['trip'];
-exports.info = {
+ return true;
+}
+
+export const requiredData = ['trip'];
+export const info = {
name: 'addmod',
description: 'Adds target trip to the config as a mod and upgrades the socket type',
usage: `
- API: { cmd: 'addmod', trip: '<target trip>' }`
+ API: { cmd: 'addmod', trip: '<target trip>' }`,
};
diff --git a/server/src/commands/admin/listusers.js b/server/src/commands/admin/listusers.js
index 5ff350f..0b0199f 100644
--- a/server/src/commands/admin/listusers.js
+++ b/server/src/commands/admin/listusers.js
@@ -3,46 +3,47 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket) {
// increase rate limit chance and ignore if not admin
- if (socket.uType != 'admin') {
- return server.police.frisk(socket.remoteAddress, 20);
+ if (socket.uType !== 'admin') {
+ return server.police.frisk(socket.address, 20);
}
// find all users currently in a channel
- let currentUsers = server.findSockets({
- channel: (channel) => true
+ const currentUsers = server.findSockets({
+ channel: (channel) => true,
});
// compile channel and user list
- let channels = {};
- for (let i = 0, j = currentUsers.length; i < j; i++) {
+ const channels = {};
+ for (let i = 0, j = currentUsers.length; i < j; i += 1) {
if (typeof channels[currentUsers[i].channel] === 'undefined') {
channels[currentUsers[i].channel] = [];
}
-
+
channels[currentUsers[i].channel].push(
- `[${currentUsers[i].trip||'null'}]${currentUsers[i].nick}`
+ `[${currentUsers[i].trip || 'null'}]${currentUsers[i].nick}`,
);
}
// build output
- let lines = [];
- for (let channel in channels) {
- lines.push(`?${channel} ${channels[channel].join(", ")}`);
+ const lines = [];
+ for (const channel in channels) {
+ lines.push(`?${channel} ${channels[channel].join(', ')}`);
}
// send reply
server.reply({
cmd: 'info',
- text: lines.join("\n")
+ text: lines.join('\n'),
}, socket);
-};
-// module meta
-exports.info = {
+ return true;
+}
+
+export const info = {
name: 'listusers',
description: 'Outputs all current channels and sockets in those channels',
usage: `
- API: { cmd: 'listusers' }`
+ API: { cmd: 'listusers' }`,
};
diff --git a/server/src/commands/admin/reload.js b/server/src/commands/admin/reload.js
index 588d1c5..206e2ca 100644
--- a/server/src/commands/admin/reload.js
+++ b/server/src/commands/admin/reload.js
@@ -3,10 +3,10 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// increase rate limit chance and ignore if not admin
- if (socket.uType != 'admin') {
- return server.police.frisk(socket.remoteAddress, 20);
+ if (socket.uType !== 'admin') {
+ return server.police.frisk(socket.address, 20);
}
// do command reload and store results
@@ -17,7 +17,7 @@ exports.run = async (core, server, socket, data) => {
server.loadHooks();
// build reply based on reload results
- if (loadResult == '') {
+ if (loadResult === '') {
loadResult = `Reloaded ${core.commands.commands.length} commands, 0 errors`;
} else {
loadResult = `Reloaded ${core.commands.commands.length} commands, error(s):
@@ -31,20 +31,21 @@ exports.run = async (core, server, socket, data) => {
// reply with results
server.reply({
cmd: 'info',
- text: loadResult
+ text: loadResult,
}, socket);
// notify mods of reload #transparency
server.broadcast({
cmd: 'info',
- text: loadResult
+ text: loadResult,
}, { uType: 'mod' });
-};
-// module meta
-exports.info = {
+ return true;
+}
+
+export const info = {
name: 'reload',
description: '(Re)loads any new commands into memory, outputs errors if any',
usage: `
- API: { cmd: 'reload', reason: '<optional reason append>' }`
+ API: { cmd: 'reload', reason: '<optional reason append>' }`,
};
diff --git a/server/src/commands/admin/removemod.js b/server/src/commands/admin/removemod.js
index a2d862c..9190dd6 100644
--- a/server/src/commands/admin/removemod.js
+++ b/server/src/commands/admin/removemod.js
@@ -3,26 +3,26 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// increase rate limit chance and ignore if not admin
- if (socket.uType != 'admin') {
- return server.police.frisk(socket.remoteAddress, 20);
+ if (socket.uType !== 'admin') {
+ return server.police.frisk(socket.address, 20);
}
// remove trip from config
- core.config.mods = core.config.mods.filter(mod => mod.trip !== data.trip);
+ core.config.mods = core.config.mods.filter((mod) => mod.trip !== data.trip);
// find targets current connections
- let targetMod = server.findSockets({ trip: data.trip });
+ const targetMod = server.findSockets({ trip: data.trip });
if (targetMod.length !== 0) {
- for (let i = 0, l = targetMod.length; i < l; i++) {
+ for (let i = 0, l = targetMod.length; i < l; i += 1) {
// downgrade privilages
targetMod[i].uType = 'user';
// inform ex-mod
server.send({
cmd: 'info',
- text: 'You are now a user.'
+ text: 'You are now a user.',
}, targetMod[i]);
}
}
@@ -32,21 +32,22 @@ exports.run = async (core, server, socket, data) => {
cmd: 'info',
text: `Removed mod trip: ${
data.trip
- }, remember to run 'saveconfig' to make it permanent`
+ }, remember to run 'saveconfig' to make it permanent`,
}, socket);
// notify all mods
server.broadcast({
cmd: 'info',
- text: `Removed mod: ${data.trip}`
+ text: `Removed mod: ${data.trip}`,
}, { uType: 'mod' });
-};
-// module meta
-exports.requiredData = ['trip'];
-exports.info = {
+ return true;
+}
+
+export const requiredData = ['trip'];
+export const info = {
name: 'removemod',
description: 'Removes target trip from the config as a mod and downgrades the socket type',
usage: `
- API: { cmd: 'removemod', trip: '<target trip>' }`
+ API: { cmd: 'removemod', trip: '<target trip>' }`,
};
diff --git a/server/src/commands/admin/saveconfig.js b/server/src/commands/admin/saveconfig.js
index 65fff0e..6c713b4 100644
--- a/server/src/commands/admin/saveconfig.js
+++ b/server/src/commands/admin/saveconfig.js
@@ -3,37 +3,38 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket) {
// increase rate limit chance and ignore if not admin
- if (socket.uType != 'admin') {
- return server.police.frisk(socket.remoteAddress, 20);
+ if (socket.uType !== 'admin') {
+ return server.police.frisk(socket.address, 20);
}
// attempt save, notify of failure
if (!core.configManager.save()) {
return server.reply({
cmd: 'warn',
- text: 'Failed to save config, check logs.'
- }, client);
+ text: 'Failed to save config, check logs.',
+ }, socket);
}
// return success message
server.reply({
cmd: 'info',
- text: 'Config saved!'
+ text: 'Config saved!',
}, socket);
// notify mods #transparency
server.broadcast({
cmd: 'info',
- text: 'Config saved!'
+ text: 'Config saved!',
}, { uType: 'mod' });
-};
-// module meta
-exports.info = {
+ return true;
+}
+
+export const info = {
name: 'saveconfig',
description: 'Writes the current config to disk',
usage: `
- API: { cmd: 'saveconfig' }`
+ API: { cmd: 'saveconfig' }`,
};
diff --git a/server/src/commands/admin/shout.js b/server/src/commands/admin/shout.js
index 821a22a..73b0734 100644
--- a/server/src/commands/admin/shout.js
+++ b/server/src/commands/admin/shout.js
@@ -3,24 +3,25 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// increase rate limit chance and ignore if not admin
- if (socket.uType != 'admin') {
- return server.police.frisk(socket.remoteAddress, 20);
+ if (socket.uType !== 'admin') {
+ return server.police.frisk(socket.address, 20);
}
// send text to all channels
server.broadcast({
cmd: 'info',
- text: `Server Notice: ${data.text}`
+ text: `Server Notice: ${data.text}`,
}, {});
-};
-// module meta
-exports.requiredData = ['text'];
-exports.info = {
+ return true;
+}
+
+export const requiredData = ['text'];
+export const info = {
name: 'shout',
description: 'Displays passed text to every client connected',
usage: `
- API: { cmd: 'shout', text: '<shout text>' }`
+ API: { cmd: 'shout', text: '<shout text>' }`,
};
diff --git a/server/src/commands/core/changenick.js b/server/src/commands/core/changenick.js
index cb6d1d0..632da83 100644
--- a/server/src/commands/core/changenick.js
+++ b/server/src/commands/core/changenick.js
@@ -6,43 +6,43 @@
const verifyNickname = (nick) => /^[a-zA-Z0-9_]{1,24}$/.test(nick);
// module main
-exports.run = async (core, server, socket, data) => {
- if (server.police.frisk(socket.remoteAddress, 6)) {
+export async function run(core, server, socket, data) {
+ if (server.police.frisk(socket.address, 6)) {
return server.reply({
cmd: 'warn',
- text: 'You are changing nicknames too fast. Wait a moment before trying again.'
+ text: 'You are changing nicknames too fast. Wait a moment before trying again.',
}, socket);
}
// verify user data is string
if (typeof data.nick !== 'string') {
- return;
+ return true;
}
// make sure requested nickname meets standards
- let newNick = data.nick.trim();
+ const newNick = data.nick.trim();
if (!verifyNickname(newNick)) {
return server.reply({
cmd: 'warn',
- text: 'Nickname must consist of up to 24 letters, numbers, and underscores'
+ text: 'Nickname must consist of up to 24 letters, numbers, and underscores',
}, socket);
}
// prevent admin impersonation
// TODO: prevent mod impersonation
- if (newNick.toLowerCase() == core.config.adminName.toLowerCase()) {
- server.police.frisk(socket.remoteAddress, 4);
+ if (newNick.toLowerCase() === core.config.adminName.toLowerCase()) {
+ server.police.frisk(socket.address, 4);
return server.reply({
cmd: 'warn',
- text: 'You are not the admin, liar!'
+ text: 'You are not the admin, liar!',
}, socket);
}
// find any sockets that have the same nickname
- let userExists = server.findSockets({
+ const userExists = server.findSockets({
channel: socket.channel,
- nick: (targetNick) => targetNick.toLowerCase() === newNick.toLowerCase()
+ nick: (targetNick) => targetNick.toLowerCase() === newNick.toLowerCase(),
});
// return error if found
@@ -50,82 +50,83 @@ exports.run = async (core, server, socket, data) => {
// That nickname is already in that channel
return server.reply({
cmd: 'warn',
- text: 'Nickname taken'
+ text: 'Nickname taken',
}, socket);
}
// build join and leave notices
// TODO: this is a legacy client holdover, name changes in the future will
// have thieir own event
- let leaveNotice = {
+ const leaveNotice = {
cmd: 'onlineRemove',
- nick: socket.nick
+ nick: socket.nick,
};
- let joinNotice = {
+ const joinNotice = {
cmd: 'onlineAdd',
nick: newNick,
trip: socket.trip || 'null',
- hash: socket.hash
+ hash: socket.hash,
};
// broadcast remove event and join event with new name, this is to support legacy clients and bots
- server.broadcast( leaveNotice, { channel: socket.channel });
- server.broadcast( joinNotice, { channel: socket.channel });
+ server.broadcast(leaveNotice, { channel: socket.channel });
+ server.broadcast(joinNotice, { channel: socket.channel });
// notify channel that the user has changed their name
- server.broadcast( {
+ server.broadcast({
cmd: 'info',
- text: `${socket.nick} is now ${newNick}`
+ text: `${socket.nick} is now ${newNick}`,
}, { channel: socket.channel });
// commit change to nickname
socket.nick = newNick;
-};
+
+ return true;
+}
// module hook functions
-exports.initHooks = (server) => {
+export function initHooks(server) {
server.registerHook('in', 'chat', this.nickCheck, 29);
-};
+}
// hooks chat commands checking for /nick
-exports.nickCheck = (core, server, socket, payload) => {
+export function nickCheck(core, server, socket, payload) {
if (typeof payload.text !== 'string') {
return false;
}
if (payload.text.startsWith('/nick')) {
- let input = payload.text.split(' ');
+ const input = payload.text.split(' ');
// If there is no nickname target parameter
if (input[1] === undefined) {
server.reply({
cmd: 'warn',
- text: 'Refer to `/help nick` for instructions on how to use this command.'
+ text: 'Refer to `/help nick` for instructions on how to use this command.',
}, socket);
return false;
}
- let newNick = input[1].replace(/@/g, '');
+ const newNick = input[1].replace(/@/g, '');
this.run(core, server, socket, {
cmd: 'changenick',
- nick: newNick
+ nick: newNick,
});
return false;
}
return payload;
-};
+}
-// module meta
-exports.requiredData = ['nick'];
-exports.info = {
+export const requiredData = ['nick'];
+export const info = {
name: 'changenick',
description: 'This will change your current connections nickname',
usage: `
API: { cmd: 'changenick', nick: '<new nickname>' }
- Text: /nick <new nickname>`
+ Text: /nick <new nickname>`,
};
diff --git a/server/src/commands/core/chat.js b/server/src/commands/core/chat.js
index 7b7e79e..8d0098b 100644
--- a/server/src/commands/core/chat.js
+++ b/server/src/commands/core/chat.js
@@ -9,43 +9,45 @@ const parseText = (text) => {
return false;
}
+ let sanitizedText = text;
+
// strip newlines from beginning and end
- text = text.replace(/^\s*\n|^\s+$|\n\s*$/g, '');
+ sanitizedText = sanitizedText.replace(/^\s*\n|^\s+$|\n\s*$/g, '');
// replace 3+ newlines with just 2 newlines
- text = text.replace(/\n{3,}/g, "\n\n");
+ sanitizedText = sanitizedText.replace(/\n{3,}/g, '\n\n');
- return text;
+ return sanitizedText;
};
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// check user input
- let text = parseText(data.text);
+ const text = parseText(data.text);
if (!text) {
// lets not send objects or empty text, yea?
- return server.police.frisk(socket.remoteAddress, 13);
+ return server.police.frisk(socket.address, 13);
}
// check for spam
- let score = text.length / 83 / 4;
- if (server.police.frisk(socket.remoteAddress, score)) {
+ const score = text.length / 83 / 4;
+ if (server.police.frisk(socket.address, score)) {
return server.reply({
cmd: 'warn',
- text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.'
+ text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.',
}, socket);
}
// build chat payload
- let payload = {
+ const payload = {
cmd: 'chat',
nick: socket.nick,
- text: text
+ text,
};
- if (socket.uType == 'admin') {
+ if (socket.uType === 'admin') {
payload.admin = true;
- } else if (socket.uType == 'mod') {
+ } else if (socket.uType === 'mod') {
payload.mod = true;
}
@@ -54,20 +56,22 @@ exports.run = async (core, server, socket, data) => {
}
// broadcast to channel peers
- server.broadcast( payload, { channel: socket.channel});
+ server.broadcast(payload, { channel: socket.channel });
// stats are fun
core.stats.increment('messages-sent');
-};
+
+ return true;
+}
// module hook functions
-exports.initHooks = (server) => {
+export function initHooks(server) {
server.registerHook('in', 'chat', this.commandCheckIn, 20);
server.registerHook('in', 'chat', this.finalCmdCheck, 254);
-};
+}
// checks for miscellaneous '/' based commands
-exports.commandCheckIn = (core, server, socket, payload) => {
+export function commandCheckIn(core, server, socket, payload) {
if (typeof payload.text !== 'string') {
return false;
}
@@ -75,16 +79,16 @@ exports.commandCheckIn = (core, server, socket, payload) => {
if (payload.text.startsWith('/myhash')) {
server.reply({
cmd: 'info',
- text: `Your hash: ${socket.hash}`
+ text: `Your hash: ${socket.hash}`,
}, socket);
return false;
}
return payload;
-};
+}
-exports.finalCmdCheck = (core, server, socket, payload) => {
+export function finalCmdCheck(core, server, socket, payload) {
if (typeof payload.text !== 'string') {
return false;
}
@@ -97,26 +101,23 @@ exports.finalCmdCheck = (core, server, socket, payload) => {
payload.text = payload.text.substr(1);
return payload;
- } else {
- server.reply({
- cmd: 'warn',
- text: `Unknown command: ${payload.text}`
- }, socket);
-
- return false;
}
- return payload;
-};
+ server.reply({
+ cmd: 'warn',
+ text: `Unknown command: ${payload.text}`,
+ }, socket);
+
+ return false;
+}
-// module meta
-exports.requiredData = ['text'];
-exports.info = {
+export const requiredData = ['text'];
+export const info = {
name: 'chat',
description: 'Broadcasts passed `text` field to the calling users channel',
usage: `
API: { cmd: 'chat', text: '<text to send>' }
Text: Uuuuhm. Just kind type in that little box at the bottom and hit enter.\n
Bonus super secret hidden commands:
- /myhash`
+ /myhash`,
};
diff --git a/server/src/commands/core/emote.js b/server/src/commands/core/emote.js
index b0203cc..f244d74 100644
--- a/server/src/commands/core/emote.js
+++ b/server/src/commands/core/emote.js
@@ -9,91 +9,94 @@ const parseText = (text) => {
return false;
}
+ let sanitizedText = text;
+
// strip newlines from beginning and end
- text = text.replace(/^\s*\n|^\s+$|\n\s*$/g, '');
+ sanitizedText = sanitizedText.replace(/^\s*\n|^\s+$|\n\s*$/g, '');
// replace 3+ newlines with just 2 newlines
- text = text.replace(/\n{3,}/g, "\n\n");
+ sanitizedText = sanitizedText.replace(/\n{3,}/g, '\n\n');
- return text;
+ return sanitizedText;
};
// module main
-exports.run = async (core, server, socket, payload) => {
+export async function run(core, server, socket, payload) {
// check user input
- let text = parseText(payload.text);
+ const text = parseText(payload.text);
if (!text) {
// lets not send objects or empty text, yea?
- return server.police.frisk(socket.remoteAddress, 8);
+ return server.police.frisk(socket.address, 8);
}
// check for spam
- let score = text.length / 83 / 4;
- if (server.police.frisk(socket.remoteAddress, score)) {
+ const score = text.length / 83 / 4;
+ if (server.police.frisk(socket.address, score)) {
return server.reply({
cmd: 'warn',
- text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.'
+ text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.',
}, socket);
}
- let newPayload = {
+ const newPayload = {
cmd: 'info',
type: 'emote',
nick: socket.nick,
- text: `@${socket.nick} ${text}`
+ text: `@${socket.nick} ${text}`,
};
if (socket.trip) {
newPayload.trip = socket.trip;
}
// broadcast to channel peers
- server.broadcast( newPayload, { channel: socket.channel});
-};
+ server.broadcast(newPayload, { channel: socket.channel });
+
+ return true;
+}
// module hook functions
-exports.initHooks = (server) => {
+export function initHooks(server) {
server.registerHook('in', 'chat', this.emoteCheck, 30);
-};
+}
// hooks chat commands checking for /me
-exports.emoteCheck = (core, server, socket, payload) => {
+export function emoteCheck(core, server, socket, payload) {
if (typeof payload.text !== 'string') {
return false;
}
if (payload.text.startsWith('/me ')) {
- let input = payload.text.split(' ');
+ const input = payload.text.split(' ');
// If there is no emote target parameter
if (input[1] === undefined) {
server.reply({
cmd: 'warn',
- text: 'Refer to `/help emote` for instructions on how to use this command.'
+ text: 'Refer to `/help emote` for instructions on how to use this command.',
}, socket);
return false;
}
input.splice(0, 1);
- let actionText = input.join(' ');
+ const actionText = input.join(' ');
this.run(core, server, socket, {
cmd: 'emote',
- text: actionText
+ text: actionText,
});
return false;
}
return payload;
-};
+}
-// module meta
-exports.requiredData = ['text'];
-exports.info = {
+export const requiredData = ['text'];
+export const info = {
name: 'emote',
description: 'Typical emote / action text',
usage: `
API: { cmd: 'emote', text: '<emote/action text>' }
- Text: /me <emote/action text>`
+ Text: /me <emote/action text>`,
};
diff --git a/server/src/commands/core/help.js b/server/src/commands/core/help.js
index 8eccdb6..25f8844 100644
--- a/server/src/commands/core/help.js
+++ b/server/src/commands/core/help.js
@@ -3,21 +3,21 @@
*/
// module support functions
-const stripIndents = require('common-tags').stripIndents;
+const { stripIndents } = require('common-tags');
// module main
-exports.run = async (core, server, socket, payload) => {
+export async function run(core, server, socket, payload) {
// check for spam
- if (server.police.frisk(socket.remoteAddress, 2)) {
+ if (server.police.frisk(socket.address, 2)) {
return server.reply({
cmd: 'warn',
- text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.'
+ text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.',
}, socket);
}
// verify user input
if (typeof payload.command !== 'undefined' && typeof payload.command !== 'string') {
- return;
+ return true;
}
let reply = '';
@@ -27,21 +27,21 @@ exports.run = async (core, server, socket, payload) => {
API: {cmd: 'help', command: '<command name>'}`;
reply += '\n\n-------------------------------------\n\n';
- let categories = core.commands.categoriesList.sort();
- for (let i = 0, j = categories.length; i < j; i++) {
- reply += `${categories[i].replace('../src/commands/', '').replace(/^\w/, c => c.toUpperCase())} Commands:\n`;
- let catCommands = core.commands.all(categories[i]).sort((a, b) => a.info.name.localeCompare(b.info.name));
- reply += ` ${catCommands.map(c => `${c.info.name}`).join(', ')}\n\n`;
+ const categories = core.commands.categoriesList.sort();
+ for (let i = 0, j = categories.length; i < j; i += 1) {
+ reply += `${categories[i].replace('../src/commands/', '').replace(/^\w/, (c) => c.toUpperCase())} Commands:\n`;
+ const catCommands = core.commands.all(categories[i]).sort((a, b) => a.info.name.localeCompare(b.info.name));
+ reply += ` ${catCommands.map((c) => `${c.info.name}`).join(', ')}\n\n`;
}
} else {
- let command = core.commands.get(payload.command);
+ const command = core.commands.get(payload.command);
if (typeof command === 'undefined') {
reply = 'Unknown command';
} else {
reply = stripIndents`Name: ${command.info.name}
Aliases: ${typeof command.info.aliases !== 'undefined' ? command.info.aliases.join(', ') : 'None'}
- Category: ${command.info.category.replace('../src/commands/', '').replace(/^\w/, c => c.toUpperCase())}
+ Category: ${command.info.category.replace('../src/commands/', '').replace(/^\w/, (c) => c.toUpperCase())}
Required Parameters: ${command.requiredData || 'None'}\n
Description: ${command.info.description || '¯\_(ツ)_/¯'}\n
Usage: ${command.info.usage || command.info.name}`;
@@ -51,40 +51,41 @@ exports.run = async (core, server, socket, payload) => {
// output reply
server.reply({
cmd: 'info',
- text: reply
+ text: reply,
}, socket);
-};
+
+ return true;
+}
// module hook functions
-exports.initHooks = (server) => {
+export function initHooks(server) {
server.registerHook('in', 'chat', this.helpCheck, 28);
-};
+}
// hooks chat commands checking for /whisper
-exports.helpCheck = (core, server, socket, payload) => {
+export function helpCheck(core, server, socket, payload) {
if (typeof payload.text !== 'string') {
return false;
}
if (payload.text.startsWith('/help')) {
- let input = payload.text.substr(1).split(' ', 2);
+ const input = payload.text.substr(1).split(' ', 2);
this.run(core, server, socket, {
cmd: input[0],
- command: input[1]
+ command: input[1],
});
return false;
}
return payload;
-};
+}
-// module meta
-exports.info = {
+export const info = {
name: 'help',
description: 'Outputs information about the servers current protocol',
usage: `
API: { cmd: 'help', command: '<optional command name>' }
- Text: /help <optional command name>`
+ Text: /help <optional command name>`,
};
diff --git a/server/src/commands/core/invite.js b/server/src/commands/core/invite.js
index 70393b1..1811e8b 100644
--- a/server/src/commands/core/invite.js
+++ b/server/src/commands/core/invite.js
@@ -6,47 +6,47 @@
const verifyNickname = (nick) => /^[a-zA-Z0-9_]{1,24}$/.test(nick);
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// check for spam
- if (server.police.frisk(socket.remoteAddress, 2)) {
+ if (server.police.frisk(socket.address, 2)) {
return server.reply({
cmd: 'warn',
- text: 'You are sending invites too fast. Wait a moment before trying again.'
+ text: 'You are sending invites too fast. Wait a moment before trying again.',
}, socket);
}
// verify user input
if (typeof data.nick !== 'string' || !verifyNickname(data.nick)) {
- return;
+ return true;
}
// why would you invite yourself?
- if (data.nick == socket.nick) {
- return;
+ if (data.nick === socket.nick) {
+ return true;
}
// generate common channel
- let channel = Math.random().toString(36).substr(2, 8);
+ const channel = Math.random().toString(36).substr(2, 8);
// build and send invite
- let payload = {
+ const payload = {
cmd: 'info',
type: 'invite',
from: socket.nick,
invite: channel,
- text: `${socket.nick} invited you to ?${channel}`
+ text: `${socket.nick} invited you to ?${channel}`,
};
- let inviteSent = server.broadcast( payload, {
+ const inviteSent = server.broadcast(payload, {
channel: socket.channel,
- nick: data.nick
+ nick: data.nick,
});
// server indicates the user was not found
if (!inviteSent) {
return server.reply({
cmd: 'warn',
- text: 'Could not find user in channel'
+ text: 'Could not find user in channel',
}, socket);
}
@@ -55,18 +55,19 @@ exports.run = async (core, server, socket, data) => {
cmd: 'info',
type: 'invite',
invite: channel,
- text: `You invited ${data.nick} to ?${channel}`
+ text: `You invited ${data.nick} to ?${channel}`,
}, socket);
// stats are fun
core.stats.increment('invites-sent');
-};
-// module meta
-exports.requiredData = ['nick'];
-exports.info = {
+ return true;
+}
+
+export const requiredData = ['nick'];
+export const info = {
name: 'invite',
description: 'Generates a unique (more or less) room name and passes it to two clients',
usage: `
- API: { cmd: 'invite', nick: '<target nickname>' }`
+ API: { cmd: 'invite', nick: '<target nickname>' }`,
};
diff --git a/server/src/commands/core/join.js b/server/src/commands/core/join.js
index 965a8bc..644470e 100644
--- a/server/src/commands/core/join.js
+++ b/server/src/commands/core/join.js
@@ -6,7 +6,7 @@
const crypto = require('crypto');
const hash = (password) => {
- let sha = crypto.createHash('sha256');
+ const sha = crypto.createHash('sha256');
sha.update(password);
return sha.digest('base64').substr(0, 6);
};
@@ -15,15 +15,15 @@ const verifyNickname = (nick) => /^[a-zA-Z0-9_]{1,24}$/.test(nick);
// exposed "login" function to allow hooks to verify user join events
// returns object containing user info or string if error
-exports.parseNickname = (core, data) => {
- let userInfo = {
+export function parseNickname(core, data) {
+ const userInfo = {
nick: '',
uType: 'user',
trip: null,
};
// seperate nick from password
- let nickArray = data.nick.split('#', 2);
+ const nickArray = data.nick.split('#', 2);
userInfo.nick = nickArray[0].trim();
if (!verifyNickname(userInfo.nick)) {
@@ -31,90 +31,92 @@ exports.parseNickname = (core, data) => {
return 'Nickname must consist of up to 24 letters, numbers, and underscores';
}
- let password = nickArray[1];
+ const password = nickArray[1];
if (hash(password + core.config.tripSalt) === core.config.adminTrip) {
userInfo.uType = 'admin';
userInfo.trip = 'Admin';
- } else if (userInfo.nick.toLowerCase() == core.config.adminName.toLowerCase()) { // they've got the main-admin name while not being an admin
+ } else if (userInfo.nick.toLowerCase() === core.config.adminName.toLowerCase()) {
+ // they've got the main-admin name while not being an admin
return 'You are not the admin, liar!';
} else if (password) {
userInfo.trip = hash(password + core.config.tripSalt);
}
// TODO: disallow moderator impersonation
- for (let mod of core.config.mods) {
+ // for (const mod of core.config.mods) {
+ core.config.mods.forEach((mod) => {
if (userInfo.trip === mod.trip) {
userInfo.uType = 'mod';
}
- }
+ });
return userInfo;
-};
+}
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// check for spam
- if (server.police.frisk(socket.remoteAddress, 3)) {
+ if (server.police.frisk(socket.address, 3)) {
return server.reply({
cmd: 'warn',
- text: 'You are joining channels too fast. Wait a moment and try again.'
+ text: 'You are joining channels too fast. Wait a moment and try again.',
}, socket);
}
// calling socket already in a channel
if (typeof socket.channel !== 'undefined') {
- return;
+ return true;
}
// check user input
if (typeof data.channel !== 'string' || typeof data.nick !== 'string') {
- return;
+ return true;
}
- let channel = data.channel.trim();
+ const channel = data.channel.trim();
if (!channel) {
// must join a non-blank channel
- return;
+ return true;
}
- let userInfo = this.parseNickname(core, data);
+ const userInfo = this.parseNickname(core, data);
if (typeof userInfo === 'string') {
return server.reply({
cmd: 'warn',
- text: userInfo
+ text: userInfo,
}, socket);
}
// check if the nickname already exists in the channel
- let userExists = server.findSockets({
+ const userExists = server.findSockets({
channel: data.channel,
- nick: (targetNick) => targetNick.toLowerCase() === userInfo.nick.toLowerCase()
+ nick: (targetNick) => targetNick.toLowerCase() === userInfo.nick.toLowerCase(),
});
if (userExists.length > 0) {
// that nickname is already in that channel
return server.reply({
cmd: 'warn',
- text: 'Nickname taken'
+ text: 'Nickname taken',
}, socket);
}
userInfo.userHash = server.getSocketHash(socket);
// prepare to notify channel peers
- let newPeerList = server.findSockets({ channel: data.channel });
- let nicks = [];
+ const newPeerList = server.findSockets({ channel: data.channel });
+ const nicks = [];
- let joinAnnouncement = {
+ const joinAnnouncement = {
cmd: 'onlineAdd',
nick: userInfo.nick,
trip: userInfo.trip || 'null',
- hash: userInfo.userHash
+ hash: userInfo.userHash,
};
// send join announcement and prep online set
- for (let i = 0, l = newPeerList.length; i < l; i++) {
+ for (let i = 0, l = newPeerList.length; i < l; i += 1) {
server.reply(joinAnnouncement, newPeerList[i]);
nicks.push(newPeerList[i].nick);
}
@@ -131,18 +133,19 @@ exports.run = async (core, server, socket, data) => {
// reply with channel peer list
server.reply({
cmd: 'onlineSet',
- nicks: nicks
+ nicks,
}, socket);
// stats are fun
core.stats.increment('users-joined');
-};
-// module meta
-exports.requiredData = ['channel', 'nick'];
-exports.info = {
+ return true;
+}
+
+export const requiredData = ['channel', 'nick'];
+export const info = {
name: 'join',
description: 'Place calling socket into target channel with target nick & broadcast event to channel',
usage: `
- API: { cmd: 'join', nick: '<your nickname>', channel: '<target channel>' }`
+ API: { cmd: 'join', nick: '<your nickname>', channel: '<target channel>' }`,
};
diff --git a/server/src/commands/core/morestats.js b/server/src/commands/core/morestats.js
index a71729c..3cbf8f3 100644
--- a/server/src/commands/core/morestats.js
+++ b/server/src/commands/core/morestats.js
@@ -3,37 +3,38 @@
*/
// module support functions
-const stripIndents = require('common-tags').stripIndents;
+const { stripIndents } = require('common-tags');
const formatTime = (time) => {
let seconds = time[0] + time[1] / 1e9;
let minutes = Math.floor(seconds / 60);
- seconds = seconds % 60;
+ seconds %= 60;
let hours = Math.floor(minutes / 60);
- minutes = minutes % 60;
+ minutes %= 60;
- let days = Math.floor(hours / 24);
- hours = hours % 24;
+ const days = Math.floor(hours / 24);
+ hours %= 24;
return `${days.toFixed(0)}d ${hours.toFixed(0)}h ${minutes.toFixed(0)}m ${seconds.toFixed(0)}s`;
};
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket) {
// gather connection and channel count
let ips = {};
let channels = {};
- for (let client of server.clients) {
+ // for (const client of server.clients) {
+ this.clients.forEach((client) => {
if (client.channel) {
channels[client.channel] = true;
- ips[client.remoteAddress] = true;
+ ips[client.address] = true;
}
- }
+ });
- let uniqueClientCount = Object.keys(ips).length;
- let uniqueChannels = Object.keys(channels).length;
+ const uniqueClientCount = Object.keys(ips).length;
+ const uniqueChannels = Object.keys(channels).length;
ips = null;
channels = null;
@@ -49,40 +50,39 @@ exports.run = async (core, server, socket, data) => {
users-banned: ${(core.stats.get('users-banned') || 0)}
users-kicked: ${(core.stats.get('users-kicked') || 0)}
stats-requested: ${(core.stats.get('stats-requested') || 0)}
- server-uptime: ${formatTime(process.hrtime(core.stats.get('start-time')))}`
+ server-uptime: ${formatTime(process.hrtime(core.stats.get('start-time')))}`,
}, socket);
// stats are fun
core.stats.increment('stats-requested');
-};
+}
// module hook functions
-exports.initHooks = (server) => {
+export function initHooks(server) {
server.registerHook('in', 'chat', this.statsCheck, 26);
-};
+}
// hooks chat commands checking for /stats
-exports.statsCheck = (core, server, socket, payload) => {
+export function statsCheck(core, server, socket, payload) {
if (typeof payload.text !== 'string') {
return false;
}
if (payload.text.startsWith('/stats')) {
this.run(core, server, socket, {
- cmd: 'morestats'
+ cmd: 'morestats',
});
return false;
}
return payload;
-};
+}
-// module meta
-exports.info = {
+export const info = {
name: 'morestats',
description: 'Sends back current server stats to the calling client',
usage: `
API: { cmd: 'morestats' }
- Text: /stats`
+ Text: /stats`,
};
diff --git a/server/src/commands/core/move.js b/server/src/commands/core/move.js
index 8e97a06..7eda88c 100644
--- a/server/src/commands/core/move.js
+++ b/server/src/commands/core/move.js
@@ -3,67 +3,67 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// check for spam
- if (server.police.frisk(socket.remoteAddress, 6)) {
+ if (server.police.frisk(socket.address, 6)) {
return server.reply({
cmd: 'warn',
- text: 'You are changing channels too fast. Wait a moment before trying again.'
+ text: 'You are changing channels too fast. Wait a moment before trying again.',
}, socket);
}
// check user input
if (typeof data.channel !== 'string') {
- return;
+ return true;
}
if (data.channel === socket.channel) {
// they are trying to rejoin the channel
- return;
+ return true;
}
// check that the nickname isn't already in target channel
const currentNick = socket.nick.toLowerCase();
- let userExists = server.findSockets({
+ const userExists = server.findSockets({
channel: data.channel,
- nick: (targetNick) => targetNick.toLowerCase() === currentNick
+ nick: (targetNick) => targetNick.toLowerCase() === currentNick,
});
if (userExists.length > 0) {
// That nickname is already in that channel
- return;
+ return true;
}
// broadcast leave notice to peers
- let peerList = server.findSockets({ channel: socket.channel });
+ const peerList = server.findSockets({ channel: socket.channel });
if (peerList.length > 1) {
- for (let i = 0, l = peerList.length; i < l; i++) {
+ for (let i = 0, l = peerList.length; i < l; i += 1) {
server.reply({
cmd: 'onlineRemove',
- nick: peerList[i].nick
+ nick: peerList[i].nick,
}, socket);
- if (socket.nick !== peerList[i].nick){
+ if (socket.nick !== peerList[i].nick) {
server.reply({
cmd: 'onlineRemove',
- nick: socket.nick
+ nick: socket.nick,
}, peerList[i]);
}
}
}
// broadcast join notice to new peers
- let newPeerList = server.findSockets({ channel: data.channel });
- let moveAnnouncement = {
+ const newPeerList = server.findSockets({ channel: data.channel });
+ const moveAnnouncement = {
cmd: 'onlineAdd',
nick: socket.nick,
trip: socket.trip || 'null',
- hash: socket.hash
+ hash: socket.hash,
};
- let nicks = [];
+ const nicks = [];
- for (let i = 0, l = newPeerList.length; i < l; i++) {
+ for (let i = 0, l = newPeerList.length; i < l; i += 1) {
server.reply(moveAnnouncement, newPeerList[i]);
nicks.push(newPeerList[i].nick);
}
@@ -73,18 +73,19 @@ exports.run = async (core, server, socket, data) => {
// reply with new user list
server.reply({
cmd: 'onlineSet',
- nicks: nicks
+ nicks,
}, socket);
// commit change
socket.channel = data.channel;
-};
-// module meta
-exports.requiredData = ['channel'];
-exports.info = {
+ return true;
+}
+
+export const requiredData = ['channel'];
+export const info = {
name: 'move',
description: 'This will change your current channel to the new one provided',
usage: `
- API: { cmd: 'move', channel: '<target channel>' }`
+ API: { cmd: 'move', channel: '<target channel>' }`,
};
diff --git a/server/src/commands/core/ping.js b/server/src/commands/core/ping.js
index 1e710e5..7d8623d 100644
--- a/server/src/commands/core/ping.js
+++ b/server/src/commands/core/ping.js
@@ -3,12 +3,11 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
- return;
-};
+export async function run() {
+
+}
-// module meta
-exports.info = {
+export const info = {
name: 'ping',
- description: 'This module is only in place to supress error notices legacy sources may get'
+ description: 'This module is only in place to supress error notices legacy sources may get',
};
diff --git a/server/src/commands/core/stats.js b/server/src/commands/core/stats.js
index ff4b1ef..8badd5b 100644
--- a/server/src/commands/core/stats.js
+++ b/server/src/commands/core/stats.js
@@ -3,19 +3,20 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket) {
// gather connection and channel count
let ips = {};
let channels = {};
- for (let client of server.clients) {
+ // for (const client of server.clients) {
+ this.clients.forEach((client) => {
if (client.channel) {
channels[client.channel] = true;
- ips[client.remoteAddress] = true;
+ ips[client.address] = true;
}
- }
+ });
- let uniqueClientCount = Object.keys(ips).length;
- let uniqueChannels = Object.keys(channels).length;
+ const uniqueClientCount = Object.keys(ips).length;
+ const uniqueChannels = Object.keys(channels).length;
ips = null;
channels = null;
@@ -23,17 +24,16 @@ exports.run = async (core, server, socket, data) => {
// dispatch info
server.reply({
cmd: 'info',
- text: `${uniqueClientCount} unique IPs in ${uniqueChannels} channels`
+ text: `${uniqueClientCount} unique IPs in ${uniqueChannels} channels`,
}, socket);
// stats are fun
core.stats.increment('stats-requested');
-};
+}
-// module meta
-exports.info = {
+export const info = {
name: 'stats',
description: 'Sends back legacy server stats to the calling client',
usage: `
- API: { cmd: 'stats' }`
+ API: { cmd: 'stats' }`,
};
diff --git a/server/src/commands/core/whisper.js b/server/src/commands/core/whisper.js
index 109889d..1cfa157 100644
--- a/server/src/commands/core/whisper.js
+++ b/server/src/commands/core/whisper.js
@@ -11,36 +11,38 @@ const parseText = (text) => {
return false;
}
+ let sanitizedText = text;
+
// strip newlines from beginning and end
- text = text.replace(/^\s*\n|^\s+$|\n\s*$/g, '');
+ sanitizedText = sanitizedText.replace(/^\s*\n|^\s+$|\n\s*$/g, '');
// replace 3+ newlines with just 2 newlines
- text = text.replace(/\n{3,}/g, "\n\n");
+ sanitizedText = sanitizedText.replace(/\n{3,}/g, '\n\n');
- return text;
+ return sanitizedText;
};
// module main
-exports.run = async (core, server, socket, payload) => {
+export async function run(core, server, socket, payload) {
// check user input
- let text = parseText(payload.text);
+ const text = parseText(payload.text);
if (!text) {
// lets not send objects or empty text, yea?
- return server.police.frisk(socket.remoteAddress, 13);
+ return server.police.frisk(socket.address, 13);
}
// check for spam
- let score = text.length / 83 / 4;
- if (server.police.frisk(socket.remoteAddress, score)) {
+ const score = text.length / 83 / 4;
+ if (server.police.frisk(socket.address, score)) {
return server.reply({
cmd: 'warn',
- text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.'
+ text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.',
}, socket);
}
- let targetNick = payload.nick;
+ const targetNick = payload.nick;
if (!verifyNickname(targetNick)) {
- return;
+ return true;
}
// find target user
@@ -49,18 +51,18 @@ exports.run = async (core, server, socket, payload) => {
if (targetClient.length === 0) {
return server.reply({
cmd: 'warn',
- text: 'Could not find user in channel'
+ text: 'Could not find user in channel',
}, socket);
}
- targetClient = targetClient[0];
+ [targetClient] = targetClient;
server.reply({
cmd: 'info',
type: 'whisper',
from: socket.nick,
trip: socket.trip || 'null',
- text: `${socket.nick} whispered: ${text}`
+ text: `${socket.nick} whispered: ${text}`,
}, targetClient);
targetClient.whisperReply = socket.nick;
@@ -68,42 +70,44 @@ exports.run = async (core, server, socket, payload) => {
server.reply({
cmd: 'info',
type: 'whisper',
- text: `You whispered to @${targetNick}: ${text}`
+ text: `You whispered to @${targetNick}: ${text}`,
}, socket);
-};
+
+ return true;
+}
// module hook functions
-exports.initHooks = (server) => {
+export function initHooks(server) {
server.registerHook('in', 'chat', this.whisperCheck, 20);
-};
+}
// hooks chat commands checking for /whisper
-exports.whisperCheck = (core, server, socket, payload) => {
+export function whisperCheck(core, server, socket, payload) {
if (typeof payload.text !== 'string') {
return false;
}
if (payload.text.startsWith('/whisper')) {
- let input = payload.text.split(' ');
+ const input = payload.text.split(' ');
// If there is no nickname target parameter
if (input[1] === undefined) {
server.reply({
cmd: 'warn',
- text: 'Refer to `/help whisper` for instructions on how to use this command.'
+ text: 'Refer to `/help whisper` for instructions on how to use this command.',
}, socket);
return false;
}
- let target = input[1].replace(/@/g, '');
+ const target = input[1].replace(/@/g, '');
input.splice(0, 2);
- let whisperText = input.join(' ');
+ const whisperText = input.join(' ');
this.run(core, server, socket, {
cmd: 'whisper',
nick: target,
- text: whisperText
+ text: whisperText,
});
return false;
@@ -113,35 +117,34 @@ exports.whisperCheck = (core, server, socket, payload) => {
if (typeof socket.whisperReply === 'undefined') {
server.reply({
cmd: 'warn',
- text: 'Cannot reply to nobody'
+ text: 'Cannot reply to nobody',
}, socket);
return false;
}
- let input = payload.text.split(' ');
+ const input = payload.text.split(' ');
input.splice(0, 1);
- let whisperText = input.join(' ');
+ const whisperText = input.join(' ');
this.run(core, server, socket, {
cmd: 'whisper',
nick: socket.whisperReply,
- text: whisperText
+ text: whisperText,
});
return false;
}
return payload;
-};
+}
-// module meta
-exports.requiredData = ['nick', 'text'];
-exports.info = {
+export const requiredData = ['nick', 'text'];
+export const info = {
name: 'whisper',
description: 'Display text on targets screen that only they can see',
usage: `
API: { cmd: 'whisper', nick: '<target name>', text: '<text to whisper>' }
Text: /whisper <target name> <text to whisper>
- Alt Text: /r <text to whisper, this will auto reply to the last person who whispered to you>`
+ Alt Text: /r <text to whisper, this will auto reply to the last person who whispered to you>`,
};
diff --git a/server/src/commands/internal/disconnect.js b/server/src/commands/internal/disconnect.js
index 520f8cb..07a125e 100644
--- a/server/src/commands/internal/disconnect.js
+++ b/server/src/commands/internal/disconnect.js
@@ -4,28 +4,29 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
if (data.cmdKey !== server.cmdKey) {
// internal command attempt by client, increase rate limit chance and ignore
- return server.police.frisk(socket.remoteAddress, 20);
+ return server.police.frisk(socket.address, 20);
}
// send leave notice to client peers
if (socket.channel) {
server.broadcast({
cmd: 'onlineRemove',
- nick: socket.nick
+ nick: socket.nick,
}, { channel: socket.channel });
}
// commit close just in case
socket.terminate();
-};
-// module meta
-exports.requiredData = ['cmdKey'];
-exports.info = {
+ return true;
+}
+
+export const requiredData = ['cmdKey'];
+export const info = {
name: 'disconnect',
usage: 'Internal Use Only',
- description: 'Internally used to relay `onlineRemove` event to clients'
+ description: 'Internally used to relay `onlineRemove` event to clients',
};
diff --git a/server/src/commands/internal/legacylayer.js b/server/src/commands/internal/legacylayer.js
index 50f5fd7..c0daa13 100644
--- a/server/src/commands/internal/legacylayer.js
+++ b/server/src/commands/internal/legacylayer.js
@@ -3,18 +3,19 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
- return;
-};
+export async function run(core, server, socket, data) {
+ /**
+ * @todo
+ */
+}
// module hook functions
-exports.initHooks = (server) => {
+export function initHooks(server) {
// module is only a placeholder
- //server.registerHook('out', '', this.);
-};
+ // server.registerHook('out', '', this.);
+}
-// module meta
-exports.info = {
+export const info = {
name: 'legacylayer',
- description: 'This module adjusts outgoing data, making it compatible with legacy clients'
+ description: 'This module adjusts outgoing data, making it compatible with legacy clients',
};
diff --git a/server/src/commands/internal/socketreply.js b/server/src/commands/internal/socketreply.js
index 5dadaf6..1ba8df2 100644
--- a/server/src/commands/internal/socketreply.js
+++ b/server/src/commands/internal/socketreply.js
@@ -3,20 +3,21 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
if (data.cmdKey !== server.cmdKey) {
// internal command attempt by client, increase rate limit chance and ignore
- return server.police.frisk(socket.remoteAddress, 20);
+ return server.police.frisk(socket.address, 20);
}
// send warning to target socket
server.reply({ cmd: 'warn', text: data.text }, socket);
-};
-// module meta
-exports.requiredData = ['cmdKey', 'text'];
-exports.info = {
+ return true;
+}
+
+export const requiredData = ['cmdKey', 'text'];
+export const info = {
name: 'socketreply',
usage: 'Internal Use Only',
- description: 'Internally used to relay warnings to clients'
+ description: 'Internally used to relay warnings to clients',
};
diff --git a/server/src/commands/mod/ban.js b/server/src/commands/mod/ban.js
index 9c8eb4f..dd5f01e 100644
--- a/server/src/commands/mod/ban.js
+++ b/server/src/commands/mod/ban.js
@@ -3,53 +3,53 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// increase rate limit chance and ignore if not admin or mod
if (socket.uType === 'user') {
- return server.police.frisk(socket.remoteAddress, 10);
+ return server.police.frisk(socket.address, 10);
}
// check user input
if (typeof data.nick !== 'string') {
- return;
+ return true;
}
// find target user
- let targetNick = data.nick;
+ const targetNick = data.nick;
let badClient = server.findSockets({ channel: socket.channel, nick: targetNick });
if (badClient.length === 0) {
return server.reply({
cmd: 'warn',
- text: 'Could not find user in channel'
+ text: 'Could not find user in channel',
}, socket);
}
- badClient = badClient[0];
+ [badClient] = badClient;
// i guess banning mods or admins isn't the best idea?
if (badClient.uType !== 'user') {
return server.reply({
cmd: 'warn',
- text: 'Cannot ban other mods, how rude'
+ text: 'Cannot ban other mods, how rude',
}, socket);
}
// commit arrest record
- server.police.arrest(badClient.remoteAddress, badClient.hash);
+ server.police.arrest(badClient.address, badClient.hash);
console.log(`${socket.nick} [${socket.trip}] banned ${targetNick} in ${socket.channel}`);
// notify normal users
server.broadcast({
cmd: 'info',
- text: `Banned ${targetNick}`
+ text: `Banned ${targetNick}`,
}, { channel: socket.channel, uType: 'user' });
// notify mods
server.broadcast({
cmd: 'info',
- text: `${socket.nick} banned ${targetNick} in ${socket.channel}, userhash: ${badClient.hash}`
+ text: `${socket.nick} banned ${targetNick} in ${socket.channel}, userhash: ${badClient.hash}`,
}, { uType: 'mod' });
// force connection closed
@@ -57,13 +57,14 @@ exports.run = async (core, server, socket, data) => {
// stats are fun
core.stats.increment('users-banned');
-};
-// module meta
-exports.requiredData = ['nick'];
-exports.info = {
+ return true;
+}
+
+export const requiredData = ['nick'];
+export const info = {
name: 'ban',
description: 'Disconnects the target nickname in the same channel as calling socket & adds to ratelimiter',
usage: `
- API: { cmd: 'ban', nick: '<target nickname>' }`
+ API: { cmd: 'ban', nick: '<target nickname>' }`,
};
diff --git a/server/src/commands/mod/dumb.js b/server/src/commands/mod/dumb.js
index d5e8fee..644bd4f 100644
--- a/server/src/commands/mod/dumb.js
+++ b/server/src/commands/mod/dumb.js
@@ -4,22 +4,22 @@
*/
// module constructor
-exports.init = (core) => {
+export function init(core) {
if (typeof core.muzzledHashes === 'undefined') {
core.muzzledHashes = {};
}
-};
+}
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// increase rate limit chance and ignore if not admin or mod
if (socket.uType === 'user') {
- return server.police.frisk(socket.remoteAddress, 10);
+ return server.police.frisk(socket.address, 10);
}
// check user input
if (typeof data.nick !== 'string') {
- return;
+ return true;
}
// find target user
@@ -28,56 +28,58 @@ exports.run = async (core, server, socket, data) => {
if (badClient.length === 0) {
return server.reply({
cmd: 'warn',
- text: 'Could not find user in channel'
+ text: 'Could not find user in channel',
}, socket);
}
- badClient = badClient[0];
+ [badClient] = badClient;
// likely dont need this, muting mods and admins is fine
if (badClient.uType !== 'user') {
return server.reply({
cmd: 'warn',
- text: 'This trick wont work on mods and admin'
+ text: 'This trick wont work on mods and admin',
}, socket);
}
// store hash in mute list
- let record = core.muzzledHashes[badClient.hash] = {
- dumb: true
- }
+ const record = core.muzzledHashes[badClient.hash] = {
+ dumb: true,
+ };
// store allies if needed
- if(data.allies && Array.isArray(data.allies)){
- record.allies = data.allies;
+ if (data.allies && Array.isArray(data.allies)) {
+ record.allies = data.allies;
}
// notify mods
server.broadcast({
cmd: 'info',
- text: `${socket.nick} muzzled ${data.nick} in ${socket.channel}, userhash: ${badClient.hash}`
+ text: `${socket.nick} muzzled ${data.nick} in ${socket.channel}, userhash: ${badClient.hash}`,
}, { uType: 'mod' });
-};
+
+ return true;
+}
// module hook functions
-exports.initHooks = (server) => {
+export function initHooks(server) {
server.registerHook('in', 'chat', this.chatCheck, 25);
server.registerHook('in', 'invite', this.inviteCheck, 25);
// TODO: add whisper hook, need hook priorities todo finished first
-};
+}
// hook incoming chat commands, shadow-prevent chat if they are muzzled
-exports.chatCheck = (core, server, socket, payload) => {
+export function chatCheck(core, server, socket, payload) {
if (typeof payload.text !== 'string') {
return false;
}
- if(core.muzzledHashes[socket.hash]){
+ if (core.muzzledHashes[socket.hash]) {
// build fake chat payload
- mutedPayload = {
+ const mutedPayload = {
cmd: 'chat',
nick: socket.nick,
- text: payload.text
+ text: payload.text,
};
if (socket.trip) {
@@ -85,50 +87,59 @@ exports.chatCheck = (core, server, socket, payload) => {
}
// broadcast to any duplicate connections in channel
- server.broadcast( mutedPayload, { channel: socket.channel, hash: socket.hash });
+ server.broadcast(mutedPayload, { channel: socket.channel, hash: socket.hash });
// broadcast to allies, if any
- if(core.muzzledHashes[socket.hash].allies){
- server.broadcast( mutedPayload, { channel: socket.channel, nick: core.muzzledHashes[socket.hash].allies });
+ if (core.muzzledHashes[socket.hash].allies) {
+ server.broadcast(
+ mutedPayload,
+ {
+ channel: socket.channel,
+ nick: core.muzzledHashes[socket.hash].allies,
+ },
+ );
}
- // blanket "spam" protection, may expose the ratelimiting lines from `chat` and use that, TODO: one day #lazydev
- server.police.frisk(socket.remoteAddress, 9);
+ /**
+ * Blanket "spam" protection.
+ * May expose the ratelimiting lines from `chat` and use that
+ * @todo one day #lazydev
+ */
+ server.police.frisk(socket.address, 9);
return false;
}
return payload;
-};
+}
// shadow-prevent all invites from muzzled users
-exports.inviteCheck = (core, server, socket, payload) => {
+export function inviteCheck(core, server, socket, payload) {
if (typeof payload.nick !== 'string') {
return false;
}
- if(core.muzzledHashes[socket.hash]){
+ if (core.muzzledHashes[socket.hash]) {
// generate common channel
- let channel = Math.random().toString(36).substr(2, 8);
+ const channel = Math.random().toString(36).substr(2, 8);
// send fake reply
server.reply({
cmd: 'info',
- text: `You invited ${payload.nick} to ?${channel}`
+ text: `You invited ${payload.nick} to ?${channel}`,
}, socket);
return false;
}
return payload;
-};
+}
-// module meta
-exports.requiredData = ['nick'];
-exports.info = {
+export const requiredData = ['nick'];
+export const info = {
name: 'dumb',
description: 'Globally shadow mute a connection. Optional allies array will see muted messages.',
usage: `
- API: { cmd: 'dumb', nick: '<target nick>', allies: ['<optional nick array>', ...] }`
+ API: { cmd: 'dumb', nick: '<target nick>', allies: ['<optional nick array>', ...] }`,
};
-exports.info.aliases = ['muzzle', 'mute'];
+info.aliases = ['muzzle', 'mute'];
diff --git a/server/src/commands/mod/kick.js b/server/src/commands/mod/kick.js
index f3bc7ca..cb01d5c 100644
--- a/server/src/commands/mod/kick.js
+++ b/server/src/commands/mod/kick.js
@@ -3,37 +3,37 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// increase rate limit chance and ignore if not admin or mod
if (socket.uType === 'user') {
- return server.police.frisk(socket.remoteAddress, 10);
+ return server.police.frisk(socket.address, 10);
}
// check user input
if (typeof data.nick !== 'string') {
if (typeof data.nick !== 'object' && !Array.isArray(data.nick)) {
- return;
+ return true;
}
}
// find target user(s)
- let badClients = server.findSockets({ channel: socket.channel, nick: data.nick });
+ const badClients = server.findSockets({ channel: socket.channel, nick: data.nick });
if (badClients.length === 0) {
return server.reply({
cmd: 'warn',
- text: 'Could not find user(s) in channel'
+ text: 'Could not find user(s) in channel',
}, socket);
}
// check if found targets are kickable, commit kick
let newChannel = '';
- let kicked = [];
- for (let i = 0, j = badClients.length; i < j; i++) {
+ const kicked = [];
+ for (let i = 0, j = badClients.length; i < j; i += 1) {
if (badClients[i].uType !== 'user') {
server.reply({
cmd: 'warn',
- text: 'Cannot kick other mods, how rude'
+ text: 'Cannot kick other mods, how rude',
}, socket);
} else {
newChannel = Math.random().toString(36).substr(2, 8);
@@ -42,7 +42,7 @@ exports.run = async (core, server, socket, data) => {
// inform mods with where they were sent
server.broadcast({
cmd: 'info',
- text: `${badClients[i].nick} was banished to ?${newChannel}`
+ text: `${badClients[i].nick} was banished to ?${newChannel}`,
}, { channel: socket.channel, uType: 'mod' });
kicked.push(badClients[i].nick);
@@ -51,32 +51,33 @@ exports.run = async (core, server, socket, data) => {
}
if (kicked.length === 0) {
- return;
+ return true;
}
// broadcast client leave event
- for (let i = 0, j = kicked.length; i < j; i++) {
+ for (let i = 0, j = kicked.length; i < j; i += 1) {
server.broadcast({
cmd: 'onlineRemove',
- nick: kicked[i]
+ nick: kicked[i],
}, { channel: socket.channel });
}
// publicly broadcast kick event
server.broadcast({
cmd: 'info',
- text: `Kicked ${kicked.join(', ')}`
+ text: `Kicked ${kicked.join(', ')}`,
}, { channel: socket.channel, uType: 'user' });
// stats are fun
core.stats.increment('users-kicked', kicked.length);
-};
-// module meta
-exports.requiredData = ['nick'];
-exports.info = {
+ return true;
+}
+
+export const requiredData = ['nick'];
+export const info = {
name: 'kick',
description: 'Silently forces target client(s) into another channel. `nick` may be string or array of strings',
usage: `
- API: { cmd: 'kick', nick: '<target nick>' }`
+ API: { cmd: 'kick', nick: '<target nick>' }`,
};
diff --git a/server/src/commands/mod/moveuser.js b/server/src/commands/mod/moveuser.js
index c7fc4bf..b55c207 100644
--- a/server/src/commands/mod/moveuser.js
+++ b/server/src/commands/mod/moveuser.js
@@ -3,79 +3,79 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// increase rate limit chance and ignore if not admin or mod
if (socket.uType === 'user') {
- return server.police.frisk(socket.remoteAddress, 10);
+ return server.police.frisk(socket.address, 10);
}
// check user input
if (typeof data.nick !== 'string' || typeof data.channel !== 'string') {
- return;
+ return true;
}
if (data.channel === socket.channel) {
// moving them into the same channel? y u do this?
- return;
+ return true;
}
- let badClients = server.findSockets({ channel: socket.channel, nick: data.nick });
+ const badClients = server.findSockets({ channel: socket.channel, nick: data.nick });
if (badClients.length === 0) {
return server.reply({
cmd: 'warn',
- text: 'Could not find user in channel'
+ text: 'Could not find user in channel',
}, socket);
}
- let badClient = badClients[0];
+ const badClient = badClients[0];
if (badClient.uType !== 'user') {
return server.reply({
cmd: 'warn',
- text: 'Cannot move other mods, how rude'
+ text: 'Cannot move other mods, how rude',
}, socket);
}
const currentNick = badClient.nick.toLowerCase();
- let userExists = server.findSockets({
+ const userExists = server.findSockets({
channel: data.channel,
- nick: (targetNick) => targetNick.toLowerCase() === currentNick
+ nick: (targetNick) => targetNick.toLowerCase() === currentNick,
});
if (userExists.length > 0) {
// That nickname is already in that channel
- return;
+ return true;
}
- let peerList = server.findSockets({ channel: socket.channel });
+ const peerList = server.findSockets({ channel: socket.channel });
if (peerList.length > 1) {
- for (let i = 0, l = peerList.length; i < l; i++) {
+ for (let i = 0, l = peerList.length; i < l; i += 1) {
server.reply({
cmd: 'onlineRemove',
- nick: peerList[i].nick
+ nick: peerList[i].nick,
}, badClient);
- if (badClient.nick !== peerList[i].nick){
+ if (badClient.nick !== peerList[i].nick) {
server.reply({
cmd: 'onlineRemove',
- nick: badClient.nick
+ nick: badClient.nick,
}, peerList[i]);
}
}
}
- let newPeerList = server.findSockets({ channel: data.channel });
- let moveAnnouncement = {
+ const newPeerList = server.findSockets({ channel: data.channel });
+ const moveAnnouncement = {
cmd: 'onlineAdd',
nick: badClient.nick,
trip: badClient.trip || 'null',
- hash: server.getSocketHash(badClient)
+ hash: server.getSocketHash(badClient),
};
- let nicks = [];
+ const nicks = [];
- for (let i = 0, l = newPeerList.length; i < l; i++) {
+ for (let i = 0, l = newPeerList.length; i < l; i += 1) {
server.reply(moveAnnouncement, newPeerList[i]);
nicks.push(newPeerList[i].nick);
}
@@ -84,22 +84,23 @@ exports.run = async (core, server, socket, data) => {
server.reply({
cmd: 'onlineSet',
- nicks: nicks
+ nicks,
}, badClient);
badClient.channel = data.channel;
- server.broadcast( {
+ server.broadcast({
cmd: 'info',
- text: `${badClient.nick} was moved into ?${data.channel}`
+ text: `${badClient.nick} was moved into ?${data.channel}`,
}, { channel: data.channel });
-};
-// module meta
-exports.requiredData = ['nick', 'channel'];
-exports.info = {
+ return true;
+}
+
+export const requiredData = ['nick', 'channel'];
+export const info = {
name: 'moveuser',
description: 'This will move the target user nick into another channel',
usage: `
- API: { cmd: 'moveuser', nick: '<target nick>', channel: '<new channel>' }`
+ API: { cmd: 'moveuser', nick: '<target nick>', channel: '<new channel>' }`,
};
diff --git a/server/src/commands/mod/speak.js b/server/src/commands/mod/speak.js
index 23fc4de..5514545 100644
--- a/server/src/commands/mod/speak.js
+++ b/server/src/commands/mod/speak.js
@@ -3,32 +3,32 @@
* Author: simple
*/
- // module constructor
- exports.init = (core) => {
- if (typeof core.muzzledHashes === 'undefined') {
- core.muzzledHashes = {};
- }
- };
+// module constructor
+export function init(core) {
+ if (typeof core.muzzledHashes === 'undefined') {
+ core.muzzledHashes = {};
+ }
+}
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// increase rate limit chance and ignore if not admin or mod
if (socket.uType === 'user') {
- return server.police.frisk(socket.remoteAddress, 10);
+ return server.police.frisk(socket.address, 10);
}
// check user input
if (typeof data.ip !== 'string' && typeof data.hash !== 'string') {
return server.reply({
cmd: 'warn',
- text: "hash:'targethash' or ip:'1.2.3.4' is required"
+ text: "hash:'targethash' or ip:'1.2.3.4' is required",
}, socket);
}
// find target & remove mute status
let target;
if (typeof data.ip === 'string') {
- target = getSocketHash(data.ip);
+ target = server.getSocketHash(data.ip);
} else {
target = data.hash;
}
@@ -38,15 +38,16 @@ exports.run = async (core, server, socket, data) => {
// notify mods
server.broadcast({
cmd: 'info',
- text: `${socket.nick} unmuzzled : ${target}`
+ text: `${socket.nick} unmuzzled : ${target}`,
}, { uType: 'mod' });
-};
-// module meta
-exports.info = {
+ return true;
+}
+
+export const info = {
name: 'speak',
description: 'Pardon a dumb user to be able to speak again',
usage: `
- API: { cmd: 'speak', ip/hash: '<target ip or hash' }`
+ API: { cmd: 'speak', ip/hash: '<target ip or hash' }`,
};
-exports.info.aliases = ['unmuzzle', 'unmute'];
+info.aliases = ['unmuzzle', 'unmute'];
diff --git a/server/src/commands/mod/unban.js b/server/src/commands/mod/unban.js
index 6744d9d..0d1e469 100644
--- a/server/src/commands/mod/unban.js
+++ b/server/src/commands/mod/unban.js
@@ -3,22 +3,23 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket, data) {
// increase rate limit chance and ignore if not admin or mod
if (socket.uType === 'user') {
- return server.police.frisk(socket.remoteAddress, 10);
+ return server.police.frisk(socket.address, 10);
}
// check user input
if (typeof data.ip !== 'string' && typeof data.hash !== 'string') {
return server.reply({
cmd: 'warn',
- text: "hash:'targethash' or ip:'1.2.3.4' is required"
+ text: "hash:'targethash' or ip:'1.2.3.4' is required",
}, socket);
}
// find target
- let mode, target;
+ let mode; let
+ target;
if (typeof data.ip === 'string') {
mode = 'ip';
target = data.ip;
@@ -39,23 +40,24 @@ exports.run = async (core, server, socket, data) => {
// reply with success
server.reply({
cmd: 'info',
- text: `Unbanned ${target}`
+ text: `Unbanned ${target}`,
}, socket);
// notify mods
server.broadcast({
cmd: 'info',
- text: `${socket.nick} unbanned: ${target}`
+ text: `${socket.nick} unbanned: ${target}`,
}, { uType: 'mod' });
// stats are fun
core.stats.decrement('users-banned');
-};
-// module meta
-exports.info = {
+ return true;
+}
+
+export const info = {
name: 'unban',
description: 'Removes target ip from the ratelimiter',
usage: `
- API: { cmd: 'unban', ip/hash: '<target ip or hash>' }`
+ API: { cmd: 'unban', ip/hash: '<target ip or hash>' }`,
};
diff --git a/server/src/commands/mod/unbanall.js b/server/src/commands/mod/unbanall.js
index c285b80..49eeee5 100644
--- a/server/src/commands/mod/unbanall.js
+++ b/server/src/commands/mod/unbanall.js
@@ -3,34 +3,35 @@
*/
// module main
-exports.run = async (core, server, socket, data) => {
+export async function run(core, server, socket) {
// increase rate limit chance and ignore if not admin or mod
if (socket.uType === 'user') {
- return server.police.frisk(socket.remoteAddress, 10);
+ return server.police.frisk(socket.address, 10);
}
// remove arrest records
- server.police.records = {};
+ server.police.clear();
console.log(`${socket.nick} [${socket.trip}] unbanned all`);
// reply with success
server.reply({
cmd: 'info',
- text: `Unbanned all ip addresses`
+ text: 'Unbanned all ip addresses',
}, socket);
// notify mods
server.broadcast({
cmd: 'info',
- text: `${socket.nick} unbanned all ip addresses`
+ text: `${socket.nick} unbanned all ip addresses`,
}, { uType: 'mod' });
-};
-// module meta
-exports.info = {
+ return true;
+}
+
+export const info = {
name: 'unbanall',
description: 'Clears all banned ip addresses',
usage: `
- API: { cmd: 'unbanall' }`
+ API: { cmd: 'unbanall' }`,
};
diff --git a/server/src/scripts/configLib/SetupWizard.js b/server/src/scripts/configLib/SetupWizard.js
index bd6ef24..ac2f3a0 100644
--- a/server/src/scripts/configLib/SetupWizard.js
+++ b/server/src/scripts/configLib/SetupWizard.js
@@ -1,40 +1,36 @@
+import {
+ start as _start,
+ get,
+} from 'prompt';
+
/**
* Server setup wizard, quick server setup and all that jazz. . .
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
+ * @author Marzavec ( https://github.com/marzavec )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
*/
-
-const fse = require('fs-extra');
-const prompt = require('prompt');
-const path = require('path');
-
class SetupWizard {
/**
* Create a `SetupWizard` instance for initializing the server's config.json
- *
* @param {Object} serverConfig reference to the server config class
*/
- constructor (serverConfig) {
+ constructor(serverConfig) {
this.serverConfig = serverConfig;
}
/**
* Roll a d20 and begin the wizarding process
- *
*/
- async start () {
+ async start() {
// load the current config to use as defaults, if available
- let currentConfig = await this.serverConfig.load() || {};
+ const currentConfig = await this.serverConfig.load() || {};
// auto generate the salt if not currrently created
- currentConfig.tripSalt = currentConfig.tripSalt ||
- [...Array(Math.floor(Math.random()*1024)+1024)].map(i=>(~~(Math.random()*36)).toString(36)).join('');
+ currentConfig.tripSalt = currentConfig.tripSalt
+ || [...Array(Math.floor(Math.random() * 1024) + 1024)].map(() => (~~(Math.random() * 36)).toString(36)).join('');
// load the setup questions & set their defaults
- let questions = require('../setupSchema/Questions.js');
+ const questions = require('../setupSchema/Questions.js');
questions.properties = this.setQuestionDefaults(questions.properties, currentConfig);
// force password re-entry
@@ -45,19 +41,18 @@ class SetupWizard {
require('../setupSchema/Banner.js');
// let's start playing 20 questions
- prompt.start();
- prompt.get(questions, (err, result) => this.finalize(err, result));
+ _start();
+ get(questions, (err, result) => this.finalize(err, result));
}
/**
* Compares the currently loaded config with the stock questions, adds a default
* and required option to the question
- *
* @param {Object} questions the set of questions from /setupSchema
* @param {Object} currentConfig the current server options
*/
- setQuestionDefaults (questions, currentConfig) {
- Object.keys(questions).forEach(qName => {
+ setQuestionDefaults(questions, currentConfig) {
+ Object.keys(questions).forEach((qName) => {
if (typeof currentConfig[qName] !== 'undefined') {
questions[qName].default = currentConfig[qName];
questions[qName].required = false;
@@ -76,7 +71,7 @@ class SetupWizard {
* @param {Object} err any errors generated by Prompt
* @param {Object} result the answers / new config setup
*/
- async finalize (err, result) {
+ async finalize(err, result) {
// output errors and die if needed
if (err) {
console.error(err);
@@ -87,7 +82,7 @@ class SetupWizard {
if (typeof result.mods === 'undefined') {
result.mods = [];
}
-
+
// If we should log errors with the err stack when they occur.
// See: CommandManager.js
if (typeof result.logErrDetailed === 'undefined') {
@@ -110,4 +105,4 @@ class SetupWizard {
}
}
-module.exports = SetupWizard;
+export default SetupWizard;
diff --git a/server/src/scripts/configure.js b/server/src/scripts/configure.js
index d7f2bf2..d96e0df 100644
--- a/server/src/scripts/configure.js
+++ b/server/src/scripts/configure.js
@@ -1,21 +1,17 @@
/**
* Server configuration script, to (re)configure server options
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
+ * @author Marzavec ( https://github.com/marzavec )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
*/
-'use strict';
-
// import required classes
-const path = require('path');
-const ConfigManager = require('../serverLib/ConfigManager');
-const SetupWizard = require('./configLib/SetupWizard');
+import { join } from 'path';
+import ConfigManager from '../serverLib/ConfigManager';
+import SetupWizard from './configLib/SetupWizard';
// import and initialize configManager & dependencies
-const serverConfig = new ConfigManager(path.join(__dirname, '../..'));
+const serverConfig = new ConfigManager(join(__dirname, '../..'));
const setup = new SetupWizard(serverConfig);
setup.start();
diff --git a/server/src/scripts/setupSchema/Banner.js b/server/src/scripts/setupSchema/Banner.js
index 823f0fe..f13fde7 100644
--- a/server/src/scripts/setupSchema/Banner.js
+++ b/server/src/scripts/setupSchema/Banner.js
@@ -5,8 +5,8 @@
*
*/
-const stripIndents = require('common-tags').stripIndents;
-const chalk = require('chalk');
+import { stripIndents } from 'common-tags';
+import chalk from 'chalk';
// gotta have that sexy console
console.log(stripIndents`
@@ -20,9 +20,9 @@ console.log(stripIndents`
${chalk.white('Note:')} ${chalk.green('npm/yarn run config')} will re-run this utility.
You will now be asked for the following:
- - ${chalk.magenta(' Salt')}, the salt for username trip
- - ${chalk.magenta('Admin Name')}, the initial admin username
- - ${chalk.magenta('Admin Pass')}, the initial admin password
- - ${chalk.magenta(' Port')}, the port for the websocket
+ - ${chalk.magenta(' Salt')}, the salt for username trip
+ - ${chalk.magenta('Admin Name')}, the initial admin username
+ - ${chalk.magenta('Admin Pass')}, the initial admin password
+ - ${chalk.magenta(' Port')}, the port for the websocket
\u200b
`);
diff --git a/server/src/scripts/setupSchema/Questions.js b/server/src/scripts/setupSchema/Questions.js
index f84d32f..532ba67 100644
--- a/server/src/scripts/setupSchema/Questions.js
+++ b/server/src/scripts/setupSchema/Questions.js
@@ -15,10 +15,10 @@ const Questions = {
type: 'string',
hidden: true,
replace: '*',
- before: value => {
+ before: (value) => {
salt = value;
return value;
- }
+ },
},
adminName: {
@@ -26,7 +26,7 @@ const Questions = {
pattern: /^"?[a-zA-Z0-9_]+"?$/,
type: 'string',
message: 'Nicks can only contain letters, numbers and underscores',
- before: value => value.replace(/"/g, '')
+ before: (value) => value.replace(/"/g, ''),
},
adminTrip: {
@@ -35,21 +35,21 @@ const Questions = {
replace: '*',
description: 'Admin Password',
message: 'You must enter or re-enter a password',
- before: value => {
+ before: (value) => {
const crypto = require('crypto');
- let sha = crypto.createHash('sha256');
+ const sha = crypto.createHash('sha256');
sha.update(value + salt);
return sha.digest('base64').substr(0, 6);
- }
+ },
},
websocketPort: {
type: 'integer',
message: 'The port may only be a number!',
description: 'Websocket Port',
- default: '6060'
- }
- }
-}
+ default: '6060',
+ },
+ },
+};
module.exports = Questions;
diff --git a/server/src/serverLib/CommandManager.js b/server/src/serverLib/CommandManager.js
index 0c4f0aa..e715c6b 100644
--- a/server/src/serverLib/CommandManager.js
+++ b/server/src/serverLib/CommandManager.js
@@ -1,47 +1,71 @@
-/**
- * Commands / protocol manager- loads, validates and handles command execution
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
- */
-
-const path = require('path');
-const didYouMean = require('didyoumean2').default;
+import {
+ basename,
+ join,
+ sep,
+ dirname,
+ relative,
+} from 'path';
+import didYouMean from 'didyoumean2';
// default command modules path
const CmdDir = 'src/commands';
+/**
+ * Commands / protocol manager- loads, validates and handles command execution
+ * @property {Array} commands - Array of currently loaded command modules
+ * @property {Array} categories - Array of command modules categories
+ * @author Marzavec ( https://github.com/marzavec )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
+ */
class CommandManager {
/**
* Create a `CommandManager` instance for handling commands/protocol
*
* @param {Object} core Reference to the global core object
*/
- constructor (core) {
+ constructor(core) {
+ /**
+ * Stored reference to the core
+ * @type {CoreApp}
+ */
this.core = core;
+
+ /**
+ * Command module storage
+ * @type {Array}
+ */
this.commands = [];
+
+ /**
+ * Command module category names (based off directory or module meta)
+ * @type {Array}
+ */
this.categories = [];
- if (!this.core.config.hasOwnProperty('logErrDetailed')) {
+
+ /**
+ * Full path to config.json file
+ * @type {String}
+ */
+ if (typeof this.core.config.logErrDetailed === 'undefined') {
this.core.config.logErrDetailed = false;
}
}
/**
* (Re)initializes name spaces for commands and starts load routine
- *
+ * @public
* @return {String} Module errors or empty if none
*/
- loadCommands () {
+ loadCommands() {
this.commands = [];
this.categories = [];
const commandImports = this.core.dynamicImports.getImport(CmdDir);
let cmdErrors = '';
- Object.keys(commandImports).forEach(file => {
- let command = commandImports[file];
- let name = path.basename(file);
+ Object.keys(commandImports).forEach((file) => {
+ const command = commandImports[file];
+ const name = basename(file);
cmdErrors += this.validateAndLoad(command, file, name);
});
@@ -50,29 +74,28 @@ class CommandManager {
/**
* Checks the module after having been `require()`ed in and reports errors
- *
* @param {Object} command reference to the newly loaded object
* @param {String} file file path to the module
* @param {String} name command (`cmd`) name
- *
+ * @private
* @return {String} Module errors or empty if none
*/
- validateAndLoad (command, file, name) {
- let error = this.validateCommand(command);
+ validateAndLoad(command, file, name) {
+ const error = this.validateCommand(command);
if (error) {
- let errText = `Failed to load '${name}': ${error}`;
+ const errText = `Failed to load command module '${name}': ${error}`;
console.log(errText);
return errText;
}
if (!command.category) {
- let base = path.join(this.core.dynamicImports.base, 'commands');
+ const base = join(this.core.dynamicImports.base, 'commands');
let category = 'Uncategorized';
- if (file.indexOf(path.sep) > -1) {
- category = path.dirname(path.relative(base, file))
- .replace(new RegExp(path.sep.replace('\\', '\\\\'), 'g'), '/');
+ if (file.indexOf(sep) > -1) {
+ category = dirname(relative(base, file))
+ .replace(new RegExp(sep.replace('\\', '\\\\'), 'g'), '/');
}
command.info.category = category;
@@ -86,7 +109,7 @@ class CommandManager {
try {
command.init(this.core);
} catch (err) {
- let errText = `Failed to initialize '${name}': ${err}`;
+ const errText = `Failed to initialize '${name}': ${err}`;
console.log(errText);
return errText;
}
@@ -99,121 +122,109 @@ class CommandManager {
/**
* Checks the module after having been `require()`ed in and reports errors
- *
* @param {Object} object reference to the newly loaded object
- *
+ * @private
* @return {String} Module errors or null if none
*/
- validateCommand (object) {
- if (typeof object !== 'object')
- return 'command setup is invalid';
-
- if (typeof object.run !== 'function')
- return 'run function is missing';
-
- if (typeof object.info !== 'object')
- return 'info object is missing';
-
- if (typeof object.info.name !== 'string')
- return 'info object is missing a valid name field';
+ validateCommand(object) {
+ if (typeof object !== 'object') { return 'command setup is invalid'; }
+ if (typeof object.run !== 'function') { return 'run function is missing'; }
+ if (typeof object.info !== 'object') { return 'info object is missing'; }
+ if (typeof object.info.name !== 'string') { return 'info object is missing a valid name field'; }
return null;
}
/**
* Pulls all command names from a passed `category`
- *
* @param {String} category [Optional] filter return results by this category
- *
+ * @public
* @return {Array} Array of command modules matching the category
*/
- all (category) {
+ all(category) {
return !category ? this.commands : this.commands.filter(
- c => c.info.category.toLowerCase() === category.toLowerCase()
- );
+ (c) => c.info.category.toLowerCase() === category.toLowerCase(),
+ );
}
/**
- * Pulls all category names
- *
- * @return {Array} Array of sub directories under CmdDir
+ * All category names
+ * @public
+ * @readonly
+ * @return {Array} Array of command category names
*/
- get categoriesList () {
+ get categoriesList() {
return this.categories;
}
/**
- * Pulls command by name or alia(s)
- *
+ * Pulls command by name or alias
* @param {String} name name or alias of command
- *
+ * @public
* @return {Object} Target command module object
*/
- get (name) {
+ get(name) {
return this.findBy('name', name)
|| this.commands.find(
- command => command.info.aliases instanceof Array &&
- command.info.aliases.indexOf(name) > -1
+ (command) => command.info.aliases instanceof Array
+ && command.info.aliases.indexOf(name) > -1,
);
}
/**
* Pulls command by arbitrary search of the `module.info` attribute
- *
* @param {String} key name or alias of command
* @param {String} value name or alias of command
- *
+ * @public
* @return {Object} Target command module object
*/
- findBy (key, value) {
- return this.commands.find(c => c.info[key] === value);
+ findBy(key, value) {
+ return this.commands.find((c) => c.info[key] === value);
}
/**
* Runs `initHooks` function on any modules that utilize the event
- *
+ * @private
* @param {Object} server main server object
*/
- initCommandHooks (server) {
- this.commands.filter(c => typeof c.initHooks !== 'undefined').forEach(
- c => c.initHooks(server)
- );
+ initCommandHooks(server) {
+ this.commands.filter((c) => typeof c.initHooks !== 'undefined').forEach(
+ (c) => c.initHooks(server),
+ );
}
/**
* Finds and executes the requested command, or fails with semi-intelligent error
- *
* @param {Object} server main server reference
* @param {Object} socket calling socket reference
* @param {Object} data command structure passed by socket (client)
- *
+ * @public
* @return {*} Arbitrary module return data
*/
- handleCommand (server, socket, data) {
+ handleCommand(server, socket, data) {
// Try to find command first
- let command = this.get(data.cmd);
+ const command = this.get(data.cmd);
if (command) {
return this.execute(command, server, socket, data);
- } else {
- // Then fail with helpful (sorta) message
- return this.handleFail(server, socket, data);
}
+
+ // Then fail with helpful (sorta) message
+ return this.handleFail(server, socket, data);
}
/**
* Requested command failure handler, attempts to find command and reports back
- *
* @param {Object} server main server reference
* @param {Object} socket calling socket reference
* @param {Object} data command structure passed by socket (client)
- *
+ * @private
* @return {*} Arbitrary module return data
*/
- handleFail (server, socket, data) {
- const maybe = didYouMean(data.cmd, this.all().map(c => c.info.name), {
+ handleFail(server, socket, data) {
+ const maybe = didYouMean(data.cmd, this.all().map((c) => c.info.name), {
threshold: 5,
- thresholdType: 'edit-distance'
+ thresholdType: 'edit-distance',
});
if (maybe) {
@@ -221,7 +232,7 @@ class CommandManager {
return this.handleCommand(server, socket, {
cmd: 'socketreply',
cmdKey: server.cmdKey,
- text: `Command not found, did you mean: \`${maybe}\`?`
+ text: `Command not found, did you mean: \`${maybe}\`?`,
});
}
@@ -229,39 +240,37 @@ class CommandManager {
return this.handleCommand(server, socket, {
cmd: 'socketreply',
cmdKey: server.cmdKey,
- text: 'Unknown command'
+ text: 'Unknown command',
});
}
/**
* Attempt to execute the requested command, fail if err or bad params
- *
* @param {Object} command target command module
* @param {Object} server main server reference
* @param {Object} socket calling socket reference
* @param {Object} data command structure passed by socket (client)
- *
+ * @private
* @return {*} Arbitrary module return data
*/
- async execute (command, server, socket, data) {
+ async execute(command, server, socket, data) {
if (typeof command.requiredData !== 'undefined') {
- let missing = [];
- for (let i = 0, len = command.requiredData.length; i < len; i++) {
- if (typeof data[command.requiredData[i]] === 'undefined')
- missing.push(command.requiredData[i]);
+ const missing = [];
+ for (let i = 0, len = command.requiredData.length; i < len; i += 1) {
+ if (typeof data[command.requiredData[i]] === 'undefined') { missing.push(command.requiredData[i]); }
}
if (missing.length > 0) {
console.log(`Failed to execute '${
- command.info.name
- }': missing required ${missing.join(', ')}\n\n`);
+ command.info.name
+ }': missing required ${missing.join(', ')}\n\n`);
this.handleCommand(server, socket, {
cmd: 'socketreply',
cmdKey: server.cmdKey,
text: `Failed to execute '${
- command.info.name
- }': missing required ${missing.join(', ')}\n\n`
+ command.info.name
+ }': missing required ${missing.join(', ')}\n\n`,
});
return null;
@@ -271,20 +280,20 @@ class CommandManager {
try {
return await command.run(this.core, server, socket, data);
} catch (err) {
- let errText = `Failed to execute '${command.info.name}': `;
-
+ const errText = `Failed to execute '${command.info.name}': `;
+
// If we have more detail enabled, then we get the trace
// if it isn't, or the property doesn't exist, then we'll get only the message
if (this.core.config.logErrDetailed === true) {
console.log(errText + err.stack);
} else {
- console.log(errText + err.toString())
+ console.log(errText + err.toString());
}
this.handleCommand(server, socket, {
cmd: 'socketreply',
cmdKey: server.cmdKey,
- text: errText + err.toString()
+ text: errText + err.toString(),
});
return null;
@@ -292,4 +301,4 @@ class CommandManager {
}
}
-module.exports = CommandManager;
+export default CommandManager;
diff --git a/server/src/serverLib/ConfigManager.js b/server/src/serverLib/ConfigManager.js
index e29a0e7..bb414be 100644
--- a/server/src/serverLib/ConfigManager.js
+++ b/server/src/serverLib/ConfigManager.js
@@ -1,38 +1,47 @@
+import dateFormat from 'dateformat';
+import {
+ existsSync,
+ ensureFileSync,
+ readJsonSync,
+ copySync,
+ writeJSONSync,
+ removeSync,
+} from 'fs-extra';
+import { resolve } from 'path';
+
/**
* Server configuration manager, handling loading, creation, parsing and saving
* of the main config.json file
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
+ * @property {String} base - Base path that all imports are required in from
+ * @author Marzavec ( https://github.com/marzavec )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
*/
-const dateFormat = require('dateformat');
-const fse = require('fs-extra');
-const path = require('path');
-
class ConfigManager {
/**
* Create a `ConfigManager` instance for managing application settings
- *
* @param {String} basePath executing directory name; __dirname
*/
- constructor (basePath = __dirname) {
- this.configPath = path.resolve(basePath, 'config/config.json');
+ constructor(basePath = __dirname) {
+ /**
+ * Full path to config.json file
+ * @type {String}
+ */
+ this.configPath = resolve(basePath, 'config/config.json');
- if (!fse.existsSync(this.configPath)){
- fse.ensureFileSync(this.configPath);
+ if (!existsSync(this.configPath)) {
+ ensureFileSync(this.configPath);
}
}
/**
- * Loads config.json (main server config) into mem
- *
- * @return {Object || Boolean} False if the config.json could not be loaded
+ * Loads config.json (main server config) into memory
+ * @public
+ * @return {(JSON|Boolean)} False if the config.json could not be loaded
*/
- async load () {
+ async load() {
try {
- this.config = fse.readJsonSync(this.configPath);
+ this.config = readJsonSync(this.configPath);
} catch (e) {
return false;
}
@@ -42,12 +51,12 @@ class ConfigManager {
/**
* Creates backup of current config into configPath
- *
+ * @private
* @return {String} Backed up config.json path
*/
- async backup () {
+ backup() {
const backupPath = `${this.configPath}.${dateFormat('dd-mm-yy-HH-MM-ss')}.bak`;
- fse.copySync(this.configPath, backupPath);
+ copySync(this.configPath, backupPath);
return backupPath;
}
@@ -55,18 +64,18 @@ class ConfigManager {
/**
* First makes a backup of the current `config.json`, then writes current config
* to disk
- *
+ * @public
* @return {Boolean} False on failure
*/
- async save () {
- const backupPath = await this.backup();
+ save() {
+ const backupPath = this.backup();
try {
- fse.writeJSONSync(this.configPath, this.config, {
- // Indent with two spaces
+ writeJSONSync(this.configPath, this.config, {
+ // Indent with two spaces
spaces: 2,
});
- fse.removeSync(backupPath);
+ removeSync(backupPath);
return true;
} catch (err) {
@@ -78,18 +87,17 @@ class ConfigManager {
/**
* Updates current config[`key`] with `value` then writes changes to disk
- *
* @param {*} key arbitrary configuration key
* @param {*} value new value to change `key` to
- *
+ * @public
* @return {Boolean} False on failure
*/
- async set (key, value) {
+ set(key, value) {
const realKey = `${key}`;
this.config[realKey] = value;
- return await this.save();
+ return this.save();
}
}
-module.exports = ConfigManager;
+export default ConfigManager;
diff --git a/server/src/serverLib/CoreApp.js b/server/src/serverLib/CoreApp.js
index 6bab090..8c2225d 100644
--- a/server/src/serverLib/CoreApp.js
+++ b/server/src/serverLib/CoreApp.js
@@ -1,30 +1,32 @@
-/**
- * The core / global reference object
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
- */
-
-const path = require('path');
-const {
+import { join } from 'path';
+import {
CommandManager,
ConfigManager,
ImportsManager,
MainServer,
- StatsManager
-} = require('./');
+ StatsManager,
+} from '.';
+/**
+ * The core app builds all required classes and maintains a central
+ * reference point across the app
+ * @property {ConfigManager} configManager - Provides loading and saving of the server config
+ * @property {Object} config - The current json config object
+ * @property {ImportsManager} dynamicImports - Dynamic require interface allowing hot reloading
+ * @property {CommandManager} commands - Manages and executes command modules
+ * @property {StatsManager} stats - Stores and adjusts arbritary stat data
+ * @property {MainServer} server - Main websocket server reference
+ * @author Marzavec ( https://github.com/marzavec )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
+ */
class CoreApp {
/**
- * Create the main core instance.
- */
- constructor () {
-
- }
-
- async init () {
+ * Load config then initialize children
+ * @public
+ * @return {void}
+ */
+ async init() {
await this.buildConfigManager();
this.buildImportManager();
@@ -33,8 +35,14 @@ class CoreApp {
this.buildMainServer();
}
- async buildConfigManager () {
- this.configManager = new ConfigManager(path.join(__dirname, '../..'));
+ /**
+ * Creates a new instance of the ConfigManager, loads and checks
+ * the server config
+ * @private
+ * @return {void}
+ */
+ async buildConfigManager() {
+ this.configManager = new ConfigManager(join(__dirname, '../..'));
this.config = await this.configManager.load();
if (this.config === false) {
@@ -43,23 +51,43 @@ class CoreApp {
}
}
- buildImportManager () {
- this.dynamicImports = new ImportsManager(path.join(__dirname, '../..'));
+ /**
+ * Creates a new instance of the ImportsManager
+ * @private
+ * @return {void}
+ */
+ buildImportManager() {
+ this.dynamicImports = new ImportsManager(join(__dirname, '../..'));
}
- buildCommandsManager () {
+ /**
+ * Creates a new instance of the CommandManager and loads the command modules
+ * @private
+ * @return {void}
+ */
+ buildCommandsManager() {
this.commands = new CommandManager(this);
this.commands.loadCommands();
}
- buildStatsManager () {
+ /**
+ * Creates a new instance of the StatsManager and sets the server start time
+ * @private
+ * @return {void}
+ */
+ buildStatsManager() {
this.stats = new StatsManager(this);
this.stats.set('start-time', process.hrtime());
}
- buildMainServer () {
+ /**
+ * Creates a new instance of the MainServer
+ * @private
+ * @return {void}
+ */
+ buildMainServer() {
this.server = new MainServer(this);
}
}
-module.exports = CoreApp;
+export { CoreApp };
diff --git a/server/src/serverLib/ImportsManager.js b/server/src/serverLib/ImportsManager.js
index 8db7b68..ac1fc4c 100644
--- a/server/src/serverLib/ImportsManager.js
+++ b/server/src/serverLib/ImportsManager.js
@@ -1,69 +1,77 @@
+import {
+ resolve,
+ basename as _basename,
+ relative,
+} from 'path';
+import RecursiveRead from 'readdir-recursive';
+
/**
* Import managment base, used to load commands/protocol and configuration objects
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
+ * @property {String} base - Base path that all imports are required in from
+ * @author Marzavec ( https://github.com/marzavec )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
*/
-
-const read = require('readdir-recursive');
-const path = require('path');
-
class ImportsManager {
/**
- * Create a `ImportsManager` instance for (re)loading classes and config
- *
+ * Create an `ImportsManager` instance for (re)loading classes and config
* @param {String} basePath executing directory name; default __dirname
*/
- constructor (basePath) {
+ constructor(basePath) {
+ /**
+ * Stored reference to the base directory path
+ * @type {String}
+ */
this.basePath = basePath;
+
+ /**
+ * Data holder for imported modules
+ * @type {Object}
+ */
this.imports = {};
}
/**
* Pull base path that all imports are required in from
- *
+ * @public
* @type {String} readonly
*/
- get base () {
+ get base() {
return this.basePath;
}
/**
* Gather all js files from target directory, then verify and load
- *
- * @param {String} dirName The name of the dir to load, relative to the basePath.
- *
+ * @param {String} dirName The name of the dir to load, relative to the basePath
+ * @private
* @return {String} Load errors or empty if none
*/
- loadDir (dirName) {
- const dir = path.resolve(this.basePath, dirName);
+ loadDir(dirName) {
+ const dir = resolve(this.basePath, dirName);
let errorText = '';
try {
- read.fileSync(dir).forEach(file => {
- const basename = path.basename(file);
+ RecursiveRead.fileSync(dir).forEach((file) => {
+ const basename = _basename(file);
if (basename.startsWith('_') || !basename.endsWith('.js')) return;
let imported;
try {
imported = require(file);
+
+ if (!this.imports[dirName]) {
+ this.imports[dirName] = {};
+ }
+
+ this.imports[dirName][file] = imported;
} catch (e) {
- let err = `Unable to load modules from ${dirName} (${path.relative(dir, file)})\n${e}`;
+ const err = `Unable to load modules from ${dirName} (${relative(dir, file)})\n${e}`;
errorText += err;
console.error(err);
- return errorText;
- }
-
- if (!this.imports[dirName]) {
- this.imports[dirName] = {};
}
-
- this.imports[dirName][file] = imported;
});
} catch (e) {
- let err = `Unable to load modules from ${dirName}\n${e}`;
+ const err = `Unable to load modules from ${dirName}\n${e}`;
errorText += err;
console.error(err);
return errorText;
@@ -75,15 +83,13 @@ class ImportsManager {
/**
* Unlink references to each loaded module, pray to google that gc knows it's job,
* then reinitialize this class to start the reload
- *
- * @param {Array} dirName The name of the dir to load, relative to the _base path.
- *
+ * @public
* @return {String} Load errors or empty if none
*/
- reloadDirCache () {
+ reloadDirCache() {
let errorText = '';
- Object.keys(this.imports).forEach(dir => {
+ Object.keys(this.imports).forEach((dir) => {
Object.keys(this.imports[dir]).forEach((mod) => {
delete require.cache[require.resolve(mod)];
});
@@ -97,20 +103,19 @@ class ImportsManager {
/**
* Pull reference to imported modules that were imported from dirName, or
* load required directory if not found
- *
* @param {String} dirName The name of the dir to load, relative to the _base path.
- *
+ * @public
* @return {Object} Object containing command module paths and structs
*/
- getImport (dirName) {
- let imported = this.imports[dirName];
+ getImport(dirName) {
+ const imported = this.imports[dirName];
if (!imported) {
this.loadDir(dirName);
}
- return Object.assign({}, this.imports[dirName]);
+ return { ...this.imports[dirName] };
}
}
-module.exports = ImportsManager;
+export default ImportsManager;
diff --git a/server/src/serverLib/MainServer.js b/server/src/serverLib/MainServer.js
index 8ef5129..35a0d3e 100644
--- a/server/src/serverLib/MainServer.js
+++ b/server/src/serverLib/MainServer.js
@@ -1,58 +1,96 @@
+import {
+ Server as WsServer,
+ OPEN as SocketReady,
+} from 'ws';
+import { createHash } from 'crypto';
+import RateLimiter from './RateLimiter';
+
+import { ServerConst } from '../utility/Constants';
+
/**
* Main websocket server handling communications and connection events
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
+ * @property {RateLimiter} police - Main rate limit handler
+ * @property {String} cmdKey - Internal use command key
+ * @author Marzavec ( https://github.com/marzavec )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
*/
-
-const WsServer = require('ws').Server;
-const SocketReady = require('ws').OPEN;
-const Crypto = require('crypto');
-const RateLimiter = require('./RateLimiter');
-const PulseSpeed = 16000; // ping all clients every X ms
-const IpSalt = [...Array(Math.floor(Math.random()*128)+128)].map(i=>(~~(Math.random()*36)).toString(36)).join('');
-const InternalCmdKey = [...Array(Math.floor(Math.random()*128)+128)].map(i=>(~~(Math.random()*36)).toString(36)).join('');
-
class MainServer extends WsServer {
/**
- * Create a HackChat server instance.
- *
- * @param {Object} core Reference to the global core object
- */
- constructor (core) {
+ * Create a HackChat server instance
+ * @param {CoreApp} core Reference to the global core object
+ */
+ constructor(core) {
super({ port: core.config.websocketPort });
+ /**
+ * Stored reference to the core
+ * @type {CoreApp}
+ */
this.core = core;
+
+ /**
+ * Command key used to verify internal commands
+ * @type {String}
+ */
+ this.internalCmdKey = [...Array(Math.floor(Math.random() * 128) + 128)].map(() => (~~(Math.random() * 36)).toString(36)).join('');
+
+ /**
+ * Salt used to hash a clients ip
+ * @type {String}
+ */
+ this.ipSalt = [...Array(Math.floor(Math.random() * 128) + 128)].map(() => (~~(Math.random() * 36)).toString(36)).join('');
+
+ /**
+ * Data store for command hooks
+ * @type {Object}
+ */
this.hooks = {};
+
+ /**
+ * Main rate limit tracker
+ * @type {RateLimiter}
+ */
this.police = new RateLimiter();
+
+ /**
+ * Black listed command names
+ * @type {Object}
+ */
this.cmdBlacklist = {};
+ /**
+ * Stored info about the last server error
+ * @type {ErrorEvent}
+ */
+ this.lastErr = null;
+
this.setupServer();
this.loadHooks();
}
/**
* Internal command key getter. Used to verify that internal only commands
- * originate internally and not from a connected client.
- * TODO: update to a structure that cannot be passed through json
- *
- * @type {String} readonly
+ * originate internally and not from a connected client
+ * @todo Update to a structure that cannot be passed through json
+ * @type {String}
+ * @public
+ * @readonly
*/
- get cmdKey () {
- return InternalCmdKey;
+ get cmdKey() {
+ return this.internalCmdKey;
}
/**
* Create ping interval and setup server event listeners
- *
+ * @private
+ * @return {void}
*/
- setupServer () {
- this.heartBeat = setInterval(() => this.beatHeart(), PulseSpeed);
+ setupServer() {
+ this.heartBeat = setInterval(() => this.beatHeart(), ServerConst.PulseSpeed);
this.on('error', (err) => {
- this.handleError('server', err);
+ this.handleError(err);
});
this.on('connection', (socket, request) => {
@@ -62,66 +100,71 @@ class MainServer extends WsServer {
/**
* Send empty `ping` frame to each client
- *
+ * @private
+ * @return {void}
*/
- beatHeart () {
- let targetSockets = this.findSockets({});
+ beatHeart() {
+ const targetSockets = this.findSockets({});
if (targetSockets.length === 0) {
return;
}
- for (let i = 0, l = targetSockets.length; i < l; i++) {
+ for (let i = 0, l = targetSockets.length; i < l; i += 1) {
try {
if (targetSockets[i].readyState === SocketReady) {
targetSockets[i].ping();
}
- } catch (e) { }
+ } catch (e) { /* yolo */ }
}
}
/**
* Bind listeners for the new socket created on connection to this class
- *
- * @param {Object} socket New socket object
+ * @param {ws#WebSocket} socket New socket object
* @param {Object} request Initial headers of the new connection
+ * @private
+ * @return {void}
*/
- newConnection (socket, request) {
- socket.remoteAddress = request.headers['x-forwarded-for'] || request.connection.remoteAddress;
+ newConnection(socket, request) {
+ const newSocket = socket;
- socket.on('message', (data) => {
+ newSocket.address = request.headers['x-forwarded-for'] || request.connection.remoteAddress;
+
+ newSocket.on('message', (data) => {
this.handleData(socket, data);
});
- socket.on('close', () => {
+ newSocket.on('close', () => {
this.handleClose(socket);
});
- socket.on('error', (err) => {
- this.handleError(socket, err);
+ newSocket.on('error', (err) => {
+ this.handleError(err);
});
}
/**
* Handle incoming messages from clients, parse and check command, then hand-off
- *
- * @param {Object} socket Calling socket object
+ * @param {ws#WebSocket} socket Calling socket object
* @param {String} data Message sent from client
+ * @private
+ * @return {void}
*/
- handleData (socket, data) {
+ handleData(socket, data) {
// Don't penalize yet, but check whether IP is rate-limited
- if (this.police.frisk(socket.remoteAddress, 0)) {
+ if (this.police.frisk(socket.address, 0)) {
this.core.commands.handleCommand(this, socket, {
cmd: 'socketreply',
cmdKey: this.cmdKey,
- text: 'You are being rate-limited or blocked.'
+ text: 'You are being rate-limited or blocked.',
});
return;
}
// Penalize here, but don't do anything about it
- this.police.frisk(socket.remoteAddress, 1);
+ this.police.frisk(socket.address, 1);
// Ignore ridiculously large packets
if (data.length > 65536) {
@@ -141,11 +184,11 @@ class MainServer extends WsServer {
return;
}
- // TODO: make this more flexible
- /*
- * Issue #1: hard coded `cmd` check
- * Issue #2: hard coded `cmd` value checks
- */
+ /**
+ * @todo make the following more flexible
+ * Issue #1: hard coded `cmd` check
+ * Issue #2: hard coded `cmd` value checks
+ */
if (typeof payload.cmd === 'undefined') {
return;
}
@@ -161,7 +204,7 @@ class MainServer extends WsServer {
if (typeof this.cmdBlacklist[payload.cmd] === 'function') {
return;
}
- // End TODO //
+ // End @todo //
// Execute `in` (incoming data) hooks and process results
payload = this.executeHooks('in', socket, payload);
@@ -171,11 +214,11 @@ class MainServer extends WsServer {
this.core.commands.handleCommand(this, socket, {
cmd: 'socketreply',
cmdKey: this.cmdKey,
- text: payload
+ text: payload,
});
return;
- } else if (payload === false) {
+ } if (payload === false) {
// A hook requested this data be dropped
return;
}
@@ -185,87 +228,107 @@ class MainServer extends WsServer {
}
/**
- * Handle socket close from clients
- *
- * @param {Object} socket Closing socket object
+ * Pass socket close event to disconnection command module
+ * @param {ws#WebSocket} socket Closing socket object
+ * @private
+ * @return {void}
*/
- handleClose (socket) {
+ handleClose(socket) {
this.core.commands.handleCommand(this, socket, {
cmd: 'disconnect',
- cmdKey: this.cmdKey
+ cmdKey: this.cmdKey,
});
}
/**
* "Handle" server or socket errors
- *
- * @param {Object||String} socket Calling socket object, or 'server'
- * @param {String} err The sad stuff
+ * @param {ErrorEvent} err The sad stuff
+ * @private
+ * @return {void}
*/
- handleError (socket, err) {
+ handleError(err) {
+ this.lastErr = err;
console.log(`Server error: ${err}`);
}
/**
* Send data payload to specific socket/client
- *
* @param {Object} payload Object to convert to json for transmission
- * @param {Object} socket The target client
+ * @param {ws#WebSocket} socket The target client
+ * @example
+ * server.send({
+ * cmd: 'info',
+ * text: 'Only targetSocket will see this'
+ * }, targetSocket);
+ * @public
+ * @return {void}
*/
- send (payload, socket) {
+ send(payload, socket) {
+ let outgoingPayload = payload;
+
// Add timestamp to command
- payload.time = Date.now();
+ outgoingPayload.time = Date.now();
// Execute `in` (incoming data) hooks and process results
- payload = this.executeHooks('out', socket, payload);
+ outgoingPayload = this.executeHooks('out', socket, outgoingPayload);
- if (typeof payload === 'string') {
+ if (typeof outgoingPayload === 'string') {
// A hook malfunctioned, reply with error
this.core.commands.handleCommand(this, socket, {
cmd: 'socketreply',
cmdKey: this.cmdKey,
- text: payload
+ text: outgoingPayload,
});
return;
- } else if (payload === false) {
+ } if (outgoingPayload === false) {
// A hook requested this data be dropped
return;
}
try {
if (socket.readyState === SocketReady) {
- socket.send(JSON.stringify(payload));
+ socket.send(JSON.stringify(outgoingPayload));
}
- } catch (e) { }
+ } catch (e) { /* yolo */ }
}
/**
* Overload function for `this.send()`
- *
* @param {Object} payload Object to convert to json for transmission
- * @param {Object} socket The target client
+ * @param {ws#WebSocket} socket The target client
+ * @example
+ * server.reply({
+ * cmd: 'info',
+ * text: 'Only targetSocket will see this'
+ * }, targetSocket);
+ * @public
+ * @return {void}
*/
- reply (payload, socket) {
+ reply(payload, socket) {
this.send(payload, socket);
}
/**
* Finds sockets/clients that meet the filter requirements, then passes the data to them
- *
* @param {Object} payload Object to convert to json for transmission
* @param {Object} filter see `this.findSockets()`
- *
+ * @example
+ * server.broadcast({
+ * cmd: 'info',
+ * text: 'Everyone in "programming" will see this'
+ * }, { channel: 'programming' });
+ * @public
* @return {Boolean} False if no clients matched the filter, true if data sent
*/
- broadcast (payload, filter) {
- let targetSockets = this.findSockets(filter);
+ broadcast(payload, filter) {
+ const targetSockets = this.findSockets(filter);
if (targetSockets.length === 0) {
return false;
}
- for (let i = 0, l = targetSockets.length; i < l; i++) {
+ for (let i = 0, l = targetSockets.length; i < l; i += 1) {
this.send(payload, targetSockets[i]);
}
@@ -274,51 +337,54 @@ class MainServer extends WsServer {
/**
* Finds sockets/clients that meet the filter requirements, returns result as array
- *
* @param {Object} data Object to convert to json for transmission
* @param {Object} filter The socket must of equal or greater attribs matching `filter`
- * = {} // matches all
- * = { channel: 'programming' } // matches any socket where (`socket.channel` === 'programming')
- * = { channel: 'programming', nick: 'Marzavec' } // matches any socket where (`socket.channel` === 'programming' && `socket.nick` === 'Marzavec')
- *
+ * @example
+ * // match all sockets:
+ * `filter` = {}
+ * // match any socket where socket.channel === 'programming'
+ * `filter` = { channel: 'programming' }
+ * // match any socket where
+ * // socket.channel === 'programming' && socket.nick === 'Marzavec'
+ * `filter` = { channel: 'programming', nick: 'Marzavec' }
+ * @public
* @return {Array} Clients who matched the filter requirements
*/
- findSockets (filter) {
- let filterAttribs = Object.keys(filter);
- let reqCount = filterAttribs.length;
+ findSockets(filter) {
+ const filterAttribs = Object.keys(filter);
+ const reqCount = filterAttribs.length;
let curMatch;
- let matches = [];
- for ( let socket of this.clients ) {
+ const matches = [];
+ this.clients.forEach((socket) => {
+ // for (const socket of this.clients) {
curMatch = 0;
- for (let i = 0; i < reqCount; i++) {
+ for (let i = 0; i < reqCount; i += 1) {
if (typeof socket[filterAttribs[i]] !== 'undefined') {
- switch(typeof filter[filterAttribs[i]]) {
+ switch (typeof filter[filterAttribs[i]]) {
case 'object': {
if (Array.isArray(filter[filterAttribs[i]])) {
if (filter[filterAttribs[i]].indexOf(socket[filterAttribs[i]]) !== -1) {
- curMatch++;
- }
- } else {
- if (socket[filterAttribs[i]] === filter[filterAttribs[i]]) {
- curMatch++;
+ curMatch += 1;
}
+ } else if (socket[filterAttribs[i]] === filter[filterAttribs[i]]) {
+ curMatch += 1;
}
- break;
+ break;
}
case 'function': {
if (filter[filterAttribs[i]](socket[filterAttribs[i]])) {
- curMatch++;
+ curMatch += 1;
}
- break;
+ break;
}
default: {
if (socket[filterAttribs[i]] === filter[filterAttribs[i]]) {
- curMatch++;
+ curMatch += 1;
}
- break;
+ break;
}
}
}
@@ -327,7 +393,7 @@ class MainServer extends WsServer {
if (curMatch === reqCount) {
matches.push(socket);
}
- }
+ });
return matches;
}
@@ -335,18 +401,20 @@ class MainServer extends WsServer {
/**
* Hashes target socket's remote address using non-static variable length salt
* encodes and shortens the output, returns that value
- *
- * @param {Object||String} target Either the target socket or ip as string
- *
+ * @param {(ws#WebSocket|String)} target Either the target socket or ip as string
+ * @example
+ * let userHash = server.getSocketHash('1.2.3.4');
+ * let userHash = server.getSocketHash(client);
+ * @public
* @return {String} Hashed client connection string
*/
- getSocketHash (target) {
- let sha = Crypto.createHash('sha256');
+ getSocketHash(target) {
+ const sha = createHash('sha256');
if (typeof target === 'string') {
- sha.update(target + IpSalt);
+ sha.update(target + this.ipSalt);
} else {
- sha.update(target.remoteAddress + IpSalt);
+ sha.update(target.address + this.ipSalt);
}
return sha.digest('base64').substr(0, 15);
@@ -355,9 +423,10 @@ class MainServer extends WsServer {
/**
* (Re)loads all command module hooks, then sorts their order of operation by
* priority, ascending (0 being highest priority)
- *
+ * @public
+ * @return {void}
*/
- loadHooks () {
+ loadHooks() {
// clear current hooks (if any)
this.clearHooks();
// notify each module to register their hooks (if any)
@@ -366,23 +435,23 @@ class MainServer extends WsServer {
let curHooks = [];
let hookObj = [];
- if (typeof this.hooks['in'] !== 'undefined') {
+ if (typeof this.hooks.in !== 'undefined') {
// start sorting, with incoming first
- curHooks = [ ...this.hooks['in'].keys() ];
- for (let i = 0, j = curHooks.length; i < j; i++) {
- hookObj = this.hooks['in'].get(curHooks[i]);
- hookObj.sort( (h1, h2) => h1.priority - h2.priority );
- this.hooks['in'].set(hookObj);
+ curHooks = [...this.hooks.in.keys()];
+ for (let i = 0, j = curHooks.length; i < j; i += 1) {
+ hookObj = this.hooks.in.get(curHooks[i]);
+ hookObj.sort((h1, h2) => h1.priority - h2.priority);
+ this.hooks.in.set(hookObj);
}
}
- if (typeof this.hooks['out'] !== 'undefined') {
+ if (typeof this.hooks.out !== 'undefined') {
// then outgoing
- curHooks = [ ...this.hooks['out'].keys() ];
- for (let i = 0, j = curHooks.length; i < j; i++) {
- hookObj = this.hooks['out'].get(curHooks[i]);
- hookObj.sort( (h1, h2) => h1.priority - h2.priority );
- this.hooks['out'].set(hookObj);
+ curHooks = [...this.hooks.out.keys()];
+ for (let i = 0, j = curHooks.length; i < j; i += 1) {
+ hookObj = this.hooks.out.get(curHooks[i]);
+ hookObj.sort((h1, h2) => h1.priority - h2.priority);
+ this.hooks.out.set(hookObj);
}
}
}
@@ -391,17 +460,19 @@ class MainServer extends WsServer {
* Adds a target function to an array of hooks. Hooks are executed either before
* processing user input (`in`) or before sending data back to the client (`out`)
* and allows a module to modify each payload before moving forward
- *
* @param {String} type The type of event, typically `in` (incoming) or `out` (outgoing)
* @param {String} command Should match the desired `cmd` attrib of the payload
- * @param {Function} hookFunction Target function to execute, should accept `server`, `socket` and `payload` as parameters
- * @param {Number} priority Execution priority, hooks with priority 1 will be executed before hooks with priority 200 for example
+ * @param {Function} hookFunction Target function to execute, should accept
+ * `server`, `socket` and `payload` as parameters
+ * @param {Number} priority Execution priority, hooks with priority 1 will be executed before
+ * hooks with priority 200 for example
+ * @example
+ * // Create hook to add "and stuff" to every chat line
+ * server.registerHook('in', 'chat', (server, socket, payload) => payload.text += ' and stuff');
+ * @public
+ * @return {void}
*/
- registerHook (type, command, hookFunction, priority) {
- if (typeof priority === 'undefined') {
- priority = 25;
- }
-
+ registerHook(type, command, hookFunction, priority = 25) {
if (typeof this.hooks[type] === 'undefined') {
this.hooks[type] = new Map();
}
@@ -412,7 +483,7 @@ class MainServer extends WsServer {
this.hooks[type].get(command).push({
run: hookFunction,
- priority: priority
+ priority,
});
}
@@ -422,25 +493,25 @@ class MainServer extends WsServer {
* A payload (modified or not) that will continue through the data flow
* A boolean false to indicate halting the data through flow
* A string which indicates an error occured in executing the hook
- *
* @param {String} type The type of event, typically `in` (incoming) or `out` (outgoing)
- * @param {Object} socket Either the target client or the client triggering the hook (depending on `type`)
- * @param {Object} payload Either incoming data from client or outgoing data (depending on `type`)
- *
- * @return {Object || Boolean}
+ * @param {ws#WebSocket} socket Either target client or client (depends on `type`)
+ * @param {Object} payload Either incoming data from client or outgoing data (depends on `type`)
+ * @private
+ * @return {Object|Boolean}
*/
- executeHooks (type, socket, payload) {
- let command = payload.cmd;
+ executeHooks(type, socket, payload) {
+ const command = payload.cmd;
+ let newPayload = payload;
if (typeof this.hooks[type] !== 'undefined') {
if (this.hooks[type].has(command)) {
- let hooks = this.hooks[type].get(command);
+ const hooks = this.hooks[type].get(command);
- for (let i = 0, j = hooks.length; i < j; i++) {
+ for (let i = 0, j = hooks.length; i < j; i += 1) {
try {
- payload = hooks[i].run(this.core, this, socket, payload);
+ newPayload = hooks[i].run(this.core, this, socket, newPayload);
} catch (err) {
- let errText = `Hook failure, '${type}', '${command}': `;
+ const errText = `Hook failure, '${type}', '${command}': `;
if (this.core.config.logErrDetailed === true) {
console.log(errText + err.stack);
} else {
@@ -450,23 +521,24 @@ class MainServer extends WsServer {
}
// A hook function may choose to return false to prevent all further processing
- if (payload === false) {
+ if (newPayload === false) {
return false;
}
}
}
}
- return payload;
+ return newPayload;
}
/**
* Wipe server hooks to make ready for module reload calls
- *
+ * @public
+ * @return {void}
*/
- clearHooks () {
+ clearHooks() {
this.hooks = {};
}
}
-module.exports = MainServer;
+export default MainServer;
diff --git a/server/src/serverLib/RateLimiter.js b/server/src/serverLib/RateLimiter.js
index 43cf077..3f9bc27 100644
--- a/server/src/serverLib/RateLimiter.js
+++ b/server/src/serverLib/RateLimiter.js
@@ -1,39 +1,60 @@
+import { RateLimits } from '../utility/Constants';
+
/**
* Tracks frequency of occurances based on `id` (remote address), then allows or
* denies command execution based on comparison with `threshold`
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
+ * @property {Object} data - The current stats data
+ * @author Marzavec ( https://github.com/marzavec )
+ * @author Andrew Belt ( https://github.com/AndrewBelt )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
*/
-
class RateLimiter {
/**
- * Create a ratelimiter instance.
- */
- constructor () {
+ * Create a ratelimiter instance
+ */
+ constructor() {
+ /**
+ * Data holder rate limit records
+ * @type {Object}
+ */
this.records = {};
- this.halflife = 30 * 1000; // milliseconds
- this.threshold = 25;
+
+ /**
+ * Time in milliseconds to decrement ratelimit weight
+ * @type {Number}
+ */
+ this.halflife = RateLimits.halflife;
+
+ /**
+ * Weight until ratelimited
+ * @type {Number}
+ */
+ this.threshold = RateLimits.threshold;
+
+ /**
+ * Stores the associated connection fingerprint with record id
+ * @type {Array}
+ */
this.hashes = [];
}
/**
* Finds current score by `id`
- *
* @param {String} id target id / address
- *
+ * @private
* @return {Object} Object containing the record meta
*/
- search (id) {
+ search(id) {
let record = this.records[id];
if (!record) {
- record = this.records[id] = {
+ this.records[id] = {
time: Date.now(),
- score: 0
- }
+ score: 0,
+ };
+
+ record = this.records[id];
}
return record;
@@ -41,20 +62,22 @@ class RateLimiter {
/**
* Adjusts the current ratelimit score by `deltaScore`
- *
* @param {String} id target id / address
* @param {Number} deltaScore amount to adjust current score by
- *
+ * @example
+ * // Penalize by 1 and store if connection is ratelimited or not
+ * let isLimited = police.frisk(socket.address, 1);
+ * @public
* @return {Boolean} True if record threshold has been exceeded
*/
- frisk (id, deltaScore) {
- let record = this.search(id);
+ frisk(id, deltaScore) {
+ const record = this.search(id);
if (record.arrested) {
return true;
}
- record.score *= Math.pow(2, -(Date.now() - record.time ) / this.halflife);
+ record.score *= 2 ** -(Date.now() - record.time) / this.halflife;
record.score += deltaScore;
record.time = Date.now();
@@ -67,11 +90,16 @@ class RateLimiter {
/**
* Statically set server to no longer accept traffic from `id`
- *
* @param {String} id target id / address
+ * @example
+ * // Usage within a command module:
+ * let badClient = server.findSockets({ channel: socket.channel, nick: targetNick });
+ * server.police.arrest(badClient[0].address, badClient[0].hash);
+ * @public
+ * @return {void}
*/
- arrest (id, hash) {
- let record = this.search(id);
+ arrest(id, hash) {
+ const record = this.search(id);
record.arrested = true;
this.hashes[hash] = id;
@@ -79,17 +107,32 @@ class RateLimiter {
/**
* Remove statically assigned limit from `id`
- *
* @param {String} id target id / address
+ * @example
+ * // Usage within a command module:
+ * server.police.pardon('targetHashOrIP');
+ * @public
+ * @return {void}
*/
- pardon (id) {
- if (typeof this.hashes[id] !== 'undefined') {
- id = this.hashes[id];
+ pardon(id) {
+ let targetId = id;
+ if (typeof this.hashes[targetId] !== 'undefined') {
+ targetId = this.hashes[targetId];
}
- let record = this.search(id);
+ const record = this.search(targetId);
record.arrested = false;
}
+
+ /**
+ * Clear all records
+ * @public
+ * @return {void}
+ */
+ clear() {
+ this.records = {};
+ this.hashes = [];
+ }
}
-module.exports = RateLimiter;
+export default RateLimiter;
diff --git a/server/src/serverLib/StatsManager.js b/server/src/serverLib/StatsManager.js
index e472504..b6e4f97 100644
--- a/server/src/serverLib/StatsManager.js
+++ b/server/src/serverLib/StatsManager.js
@@ -1,60 +1,79 @@
/**
* Simple generic stats collection script for events occurances (etc)
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
+ * @property {Object} data - The current stats data
+ * @author Marzavec ( https://github.com/marzavec )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
*/
-
class StatsManager {
/**
- * Create a stats instance.
- *
+ * Create a stats instance
*/
- constructor () {
+ constructor() {
+ /**
+ * Data holder for the stats class
+ * @type {Object}
+ */
this.data = {};
}
/**
* Retrieve value of arbitrary `key` reference
- *
* @param {String} key Reference to the arbitrary store name
- *
+ * @example
+ * // Find previously set `start-time`
+ * stats.get('start-time');
+ * @public
* @return {*} Data referenced by `key`
*/
- get (key) {
+ get(key) {
return this.data[key];
}
/**
* Set value of arbitrary `key` reference
- *
* @param {String} key Reference to the arbitrary store name
* @param {Number} value New value for `key`
+ * @example
+ * // Set `start-time`
+ * stats.set('start-time', process.hrtime());
+ * @public
+ * @return {void}
*/
- set (key, value) {
+ set(key, value) {
this.data[key] = value;
}
/**
* Increase value of arbitrary `key` reference, by 1 or `amount`
- *
* @param {String} key Reference to the arbitrary store name
- * @param {Number} amount Value to increase `key` by, or 1 if omitted
+ * @param {?Number} [amount=1] Value to increase `key` by, or 1 if omitted
+ * @example
+ * // Increment by `amount`
+ * stats.increment('users', 6);
+ * // Increment by 1
+ * stats.increment('users');
+ * @public
+ * @return {void}
*/
- increment (key, amount) {
- this.set(key, (this.get(key) || 0) + (amount || 1));
+ increment(key, amount = 1) {
+ this.set(key, (this.get(key) || 0) + amount);
}
/**
* Reduce value of arbitrary `key` reference, by 1 or `amount`
- *
* @param {String} key Reference to the arbitrary store name
- * @param {Number} amount Value to decrease `key` by, or 1 if omitted
+ * @param {?Number} [amount=1] Value to decrease `key` by, or 1 if omitted
+ * @example
+ * // Decrement by `amount`
+ * stats.decrement('users', 6);
+ * // Decrement by 1
+ * stats.decrement('users');
+ * @public
+ * @return {void}
*/
- decrement (key, amount) {
- this.set(key, (this.get(key) || 0) - (amount || 1));
+ decrement(key, amount = 1) {
+ this.set(key, (this.get(key) || 0) - amount);
}
}
diff --git a/server/src/serverLib/index.js b/server/src/serverLib/index.js
index 4583de6..a820588 100644
--- a/server/src/serverLib/index.js
+++ b/server/src/serverLib/index.js
@@ -1,8 +1,6 @@
-module.exports = {
- CommandManager: require('./CommandManager'),
- ConfigManager: require('./ConfigManager'),
- ImportsManager: require('./ImportsManager'),
- MainServer: require('./MainServer'),
- RateLimiter: require('./RateLimiter'),
- StatsManager: require('./StatsManager')
-};
+export const CommandManager = require('./CommandManager').default;
+export const ConfigManager = require('./ConfigManager').default;
+export const ImportsManager = require('./ImportsManager').default;
+export const MainServer = require('./MainServer').default;
+export const RateLimiter = require('./RateLimiter').default;
+export const StatsManager = require('./StatsManager');
diff --git a/server/src/utility/Constants.js b/server/src/utility/Constants.js
new file mode 100644
index 0000000..6836421
--- /dev/null
+++ b/server/src/utility/Constants.js
@@ -0,0 +1,19 @@
+/**
+ * Rate limit options
+ * @typedef {Object} RateLimits
+ * @property {number} halflife Time in milliseconds to decrement ratelimit weight
+ * @property {number} threshold Weight until ratelimited
+ */
+exports.RateLimits = {
+ halflife: 30 * 1000,
+ threshold: 25,
+};
+
+/**
+ * Websocket server options
+ * @typedef {Object} ServerConst
+ * @property {number} PulseSpeed Time in milliseconds to ping each client
+ */
+exports.ServerConst = {
+ PulseSpeed: 16 * 1000,
+};