diff --git a/.editorconfig b/.editorconfig index 5370727..9d08a1a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,14 +1,9 @@ -# editorconfig.org - root = true [*] charset = utf-8 -end_of_line = lf -insert_final_newline = true indent_style = space indent_size = 2 +end_of_line = lf +insert_final_newline = true trim_trailing_whitespace = true - -[*.md] -trim_trailing_whitespace = false diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..ebc367f --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +/test/*.js +/client/* +/documentation/* diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..24182a1 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,33 @@ +module.exports = { + env: { + es2021: true, + node: true, + }, + extends: [ + 'airbnb-base', + ], + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + }, + rules: { + "no-console": 0, + "no-param-reassign": [ + "error", + { + "props": false, + } + ], + "import/extensions": [ + "error", + "ignorePackages", + { + js: "always", + jsx: "always", + ts: "always", + tsx: "always", + mjs: "always", + } + ] + }, +}; diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index a55639c..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - env: { - browser: true, - commonjs: true, - es2021: true, - }, - extends: [ - 'airbnb-base', - ], - parserOptions: { - ecmaVersion: 12, - }, - rules: { - }, -}; diff --git a/.gitignore b/.gitignore index 4bf93f7..a93c6d0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,11 @@ logs npm-debug.log* yarn-debug.log* yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json # Runtime data pids @@ -15,12 +20,13 @@ pids lib-cov # Coverage directory used by tools like istanbul -coverage +.coverage +*.lcov # nyc test coverage .nyc_output -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) @@ -36,8 +42,11 @@ build/Release node_modules/ jspm_packages/ -# Typescript v1 declaration files -typings/ +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo # Optional npm cache directory .npm @@ -45,6 +54,15 @@ typings/ # Optional eslint cache .eslintcache +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + # Optional REPL history .node_repl_history @@ -54,10 +72,63 @@ typings/ # Yarn Integrity file .yarn-integrity -# dotenv environment variables file +# dotenv environment variable files .env +.env.development.local +.env.test.local +.env.production.local +.env.local -# next.js build output +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output .next +out -server/config/ \ No newline at end of file +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +session.key +salt.key +config.json diff --git a/.hcserver.json b/.hcserver.json new file mode 100644 index 0000000..eb59264 --- /dev/null +++ b/.hcserver.json @@ -0,0 +1 @@ +{"modulesPath":"./commands","websocketPort":"6060","rateLimit":{"halflife":"30000","threshold":"25"},"pulseSpeed":"16000"} diff --git a/.nycrc b/.nycrc new file mode 100644 index 0000000..9328f12 --- /dev/null +++ b/.nycrc @@ -0,0 +1,29 @@ +{ + "check-coverage": true, + "per-file": true, + "lines": 80, + "statements": 80, + "functions": 80, + "branches": 80, + "include": [ + "commands/**/*.js" + ], + "exclude": [ + "commands/**/*.spec.js" + ], + "ignore-class-method": "methodToIgnore", + "reporter": [ + "html", + "lcov", + "text", + "text-summary" + ], + "require": [ + "dotenv/config" + ], + "extension": [], + "cache": true, + "all": true, + "temp-dir": "", + "report-dir": "./.coverage" +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index f52afd7..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,147 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. - -## [Unreleased] - -## [2.1.93 pre 2.2] - 2020-03-12 -### Added -- (Source) `./pm2.config.js` PM2 ecosystem config handling both http-server and the websocket -- (Source) NPM new commands: -- "start": Starts or reloads the dev environment -- "stop": Stops and clears the dev environment -- "logs": Show / watch http & websocket logs for errors and events -- "clear": Clear all logged data -- "status": Show status of http and websocket -- "refresh": Clears logged data and stops http and websocket -- (Server) Numeric user levels / UAC, related to issue #86 -- (Server) `join` module password property, related to V2 protocol update -- (Server) `users` array to `onlineSet` structure, related to V2 protocol update -- (Server) `session` module, related to V2 protocol update -- (Server) `/move` chat hook to `move` module - -### Removed -- (Source) `./clientSource/` directory - -### Changed -- (Server) Minor bug fixes -- (Server) Increased module abstraction to remove duplicate code (thanks @MinusGix) - -## [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 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 -- (Client) Fixed firefox drop down menu bug -- (Client) Updated Katex lib - -### Stretched -- The term "minimal" - -## [2.1.9 pre 2.2] - 2019-03-18 -### Changed -- Configuration script setup, making it more portable/sane -- Refactored naming scheme and entry point - -### Removed -- Configuration setup from `./serverLib/ConfigManager` -- Unused feature allowing command modules to add to the configuration/setup process -- `deasync` dependency - -## [2.1.9] - 2019-02-21 -### Added -- `./server/src/commands/core/emote.js` module to provide action text -- `./server/src/core/server.js` priorities to command hooking -- Priority levels to all command modules -- `./server/src/commands/core/chat.js` Unknown '/' commands will now return a warning -- `./server/src/commands/internal/legacylayer.js` to provide compatibility to legacy connections - -### Changed -- Updated all libraries to latest -- `./server/src/core/server.js` Removed unneeded function bindings -- `./server/src/core/server.js` Hook function layout -- `./server/src/managers/config.js` Documentation wording - -## [2.1.0] - 2018-09-29 -### Added -- Module hook framework, isolating modules and making them truly drop-to-install -- `./server/src/commands/core/whisper.js` module to send in-channel private messages, `/whisper` hook -- `muzzle` and `mute` aliases to `./server/src/commands/mod/dumb.js` -- `unmuzzle` and `unmute` aliases to `./server/src/commands/mod/speak.js` -- `./server/src/commands/admin/removemod.js` module to remove mods -- `./server/src/commands/mod/unbanall.js` module to clear all bans and ratelimiting - -### Changed -- Further code cleanup on all modules -- Adjusted `ipSalt` entropy -- `./server/src/commands/core/help.js` output is now helpful, added `/help` hook -- `./server/src/commands/core/chat.js` added `/myhash` and `/me` hooks -- `./server/src/commands/core/morestats.js` added `/stats` hook - -## [2.0.3] - 2018-06-03 -### Added -- `./server/src/commands/mod/dumb.js` module for server-wide shadow muting -- `./server/src/commands/mod/speak.js` module unmuting -- `./server/src/commands/internal/socketreply.js` module to route warning to clients -- `./server/src/commands/core/ping.js` module to prevent `didYouMean` errors on legacy sources - -### Changed -- Moved `disconnect.js` into servers internal modules directory -- Restructured `server.js` and `commands.js`, removing hardcoded protocol use - -## [2.0.2] - 2018-05-19 -### Added -- `./documentation/DOCUMENTATION.md` document which gives overview of the applications protocol -- `./documentation/DEPLOY.md` document which gives overview of deploying the server live -- `./LICENSE` License file -- Code highlighting, triggered with # - -### Changed -- `README.md` wording and layout - -### Removed -- Unneeded `use strict` - -## [2.0.1] - 2018-04-18 -### Added -- `users-kicked` tracking to `morestats` command -- Server-side ping interval -- `move` command to change channels without reconnecting -- `disconnect` command module to free core server from protocol dependency -- `changenick` command to change client nick without reconnecting - -### Changed -- Filter object of the `findSockets` function now accepts more complex parameters, including functions and arrays -- `kick` command now accepts an array as the `nick` argument allowing multiple simultaneous kicks -- `join` command now takes advantage of the new filter object -- Core server disconnect handler now calls the `disconnect` module instead of broadcasting hard coded `onlineRemove` - -### Removed -- Client-side ping interval - -## [2.0.0] - 2018-04-12 -### Added -- CHANGELOG.md -- `index.html` files to `katex` directories - -### Changed -- Updated client html KaTeX libraries to v0.9.0 - -### Removed -- Uneeded files under `katex` directories diff --git a/LICENSE b/LICENSE index 5c93f45..f0e18e1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,13 +1,21 @@ - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 +MIT License - Copyright (C) 2004 Sam Hocevar +Copyright (c) 2022 marzavec - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - 0. You just DO WHAT THE FUCK YOU WANT TO. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 2208ea6..d3a2cb4 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ A list of software developed for the hack.chat framework can be found at the [3rd party software list](https://github.com/hack-chat/3rd-party-software-list) repository. This includes bots, clients, docker containers, etc. -This is a backwards compatible continuation of the [work by Andrew Belt](https://github.com/AndrewBelt/hack.chat). The server code has been updated to ES6 along with several new features including new commands and hot-reload of the commands/protocol. There is also [documentation](documentation/DOCUMENTATION.md) and a [changelog](CHANGELOG.md). +This is a backwards compatible continuation of the [work by Andrew Belt](https://github.com/AndrewBelt/hack.chat). The server code has been updated to ES6 along with several new features including new commands and hot-reload of the commands/protocol. There is also [documentation](documentation/index.html). # Installation ## Prerequisites -- [node.js 8.10.0](https://nodejs.org/en/download/package-manager/#windows) or higher -- [npm 5.7.1](https://nodejs.org/en/download/package-manager/#windows) or higher +- [node.js v16.14.0](https://nodejs.org/) or higher +- [npm 8.5.4](https://nodejs.org/) or higher ## Developer Installation @@ -20,19 +20,14 @@ This is a backwards compatible continuation of the [work by Andrew Belt](https:/ 1. Install the dependencies: `npm install` 1. Launch: `npm start` - If you change the `websocketPort` option during the config setup then these changes will need to be reflected on [line 60 of client.js](https://github.com/hack-chat/main/blob/master/client/client.js#L60). - ## Live Deployment Installation See [DEPLOY.md](documentation/DEPLOY.md) # Contributing -- If you are modifying commands, make sure it is backwards compatible with the legacy client and you update the documentation accordingly. -- Use [the template](documentation/templateCommand.js) to learn how to create new commands. - Use two space indents. - Name files in camelCase. -- Scripts that do not default to strict mode (such as modules) must use the `'use strict'` directive. # Credits @@ -41,10 +36,10 @@ See [DEPLOY.md](documentation/DEPLOY.md) * [**Neel Kamath**](https://github.com/neelkamath) - *Base Documentation* * [**Carlos Villavicencio**](https://github.com/po5i) - *Syntax Highlighting Integration* * [**OpSimple**](https://github.com/OpSimple) - *Modules Added: dumb.js & speak.js* -* Andrew Belt, https://github.com/AndrewBelt, for original base work -* [wwandrew](https://github.com/wwandrew), for finding server flaws (including attack vectors) and submitting ~~___incredibly detailed___~~ bug reports -* [Everyone else](https://github.com/hack-chat/main/graphs/contributors) who participated in this project. +* [**Andrew Belt**](https://github.com/AndrewBelt), for original base work +* [**wwandrew**](https://github.com/wwandrew), for finding server flaws (including attack vectors) and submitting ~~___incredibly detailed___~~ bug reports +* [**Everyone else**](https://github.com/hack-chat/main/graphs/contributors) who participated in this project. # License -This project is licensed under the [WTFPL License](LICENSE). +This project is licensed under the [MIT License](LICENSE). diff --git a/commands/admin/addmod.js b/commands/admin/addmod.js index 3a6b140..204c38f 100644 --- a/commands/admin/addmod.js +++ b/commands/admin/addmod.js @@ -1,15 +1,24 @@ -/* - Description: Adds the target trip to the mod list then elevates the uType -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Create a new mod trip + * @version 1.0.0 + * @description Adds target trip to the config as a mod and upgrades the socket type + * @module addmod + */ import { isAdmin, isModerator, levels, getUserDetails, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket, payload, }) { @@ -19,7 +28,7 @@ export async function run({ } // add new trip to config - core.config.mods.push({ trip: payload.trip }); + core.appConfig.data.globalMods.push({ trip: payload.trip }); // find targets current connections const newMod = server.findSockets({ trip: payload.trip }); @@ -35,7 +44,7 @@ export async function run({ }; for (let i = 0, l = newMod.length; i < l; i += 1) { - // upgrade privilages + // upgrade privileges newMod[i].uType = 'mod'; // @todo use legacyLevelToLabel from _LegacyFunctions.js newMod[i].level = levels.moderator; @@ -73,9 +82,26 @@ export async function run({ return true; } +/** + * The following payload properties are required to invoke this module: + * "trip" + * @public + * @typedef {Array} addmod/requiredData + */ export const requiredData = ['trip']; + +/** + * Module meta information + * @public + * @typedef {Object} addmod/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'addmod', + category: 'admin', description: 'Adds target trip to the config as a mod and upgrades the socket type', usage: ` API: { cmd: 'addmod', trip: '' }`, diff --git a/commands/admin/listusers.js b/commands/admin/listusers.js index 850ae75..f5081f0 100644 --- a/commands/admin/listusers.js +++ b/commands/admin/listusers.js @@ -2,15 +2,24 @@ /* eslint no-restricted-syntax: 0 */ /* eslint guard-for-in: 0 */ -/* - Description: Outputs all current channels and their user nicks -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Show users and channels + * @version 1.0.0 + * @description Outputs all current channels and sockets in those channels + * @module listusers + */ import { isAdmin, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ server, socket }) { // increase rate limit chance and ignore if not admin if (!isAdmin(socket.level)) { @@ -50,8 +59,18 @@ export async function run({ server, socket }) { return true; } +/** + * Module meta information + * @public + * @typedef {Object} listusers/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'listusers', + category: 'admin', description: 'Outputs all current channels and sockets in those channels', usage: ` API: { cmd: 'listusers' }`, diff --git a/commands/admin/reload.js b/commands/admin/reload.js index 32ca04f..aa4d212 100644 --- a/commands/admin/reload.js +++ b/commands/admin/reload.js @@ -1,13 +1,22 @@ -/* - Description: Clears and resets the command modules, outputting any errors -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Refresh modules + * @version 1.0.0 + * @description Allows a remote user to clear and re-import the server command modules + * @module reload + */ import { isAdmin, isModerator, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket, payload, }) { @@ -17,8 +26,7 @@ export async function run({ } // do command reload and store results - let loadResult = core.dynamicImports.reloadDirCache(); - loadResult += core.commands.loadCommands(); + let loadResult = await core.commands.reloadCommands(); // clear and rebuild all module hooks server.loadHooks(); @@ -45,9 +53,19 @@ export async function run({ return true; } +/** + * Module meta information + * @public + * @typedef {Object} reload/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'reload', - description: '(Re)loads any new commands into memory, outputs errors if any', + category: 'admin', + description: 'Allows a remote user to clear and re-import the server command modules', usage: ` API: { cmd: 'reload', reason: '' }`, }; diff --git a/commands/admin/removemod.js b/commands/admin/removemod.js index e1ab7af..fe7c28c 100644 --- a/commands/admin/removemod.js +++ b/commands/admin/removemod.js @@ -1,15 +1,24 @@ -/* - Description: Removes target trip from the config as a mod and downgrades the socket type -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Removes a mod + * @version 1.0.0 + * @description Removes target trip from the config as a mod and downgrades the socket type + * @module removemod + */ import { isAdmin, isModerator, levels, getUserDetails, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket, payload, }) { @@ -20,7 +29,9 @@ export async function run({ // remove trip from config // eslint-disable-next-line no-param-reassign - core.config.mods = core.config.mods.filter((mod) => mod.trip !== payload.trip); + core.appConfig.data.globalMods = core.appConfig.data.globalMods.filter( + (mod) => mod.trip !== payload.trip, + ); // find targets current connections const targetMod = server.findSockets({ trip: payload.trip }); @@ -36,8 +47,8 @@ export async function run({ }; for (let i = 0, l = targetMod.length; i < l; i += 1) { - // downgrade privilages - targetMod[i].uType = 'user'; + // downgrade privileges + targetMod[i].uType = 'user'; /* @legacy */ targetMod[i].level = levels.default; // inform ex-mod @@ -76,9 +87,26 @@ export async function run({ return true; } +/** + * The following payload properties are required to invoke this module: + * "trip" + * @public + * @typedef {Array} removemod/requiredData + */ export const requiredData = ['trip']; + +/** + * Module meta information + * @public + * @typedef {Object} removemod/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'removemod', + category: 'admin', description: 'Removes target trip from the config as a mod and downgrades the socket type', usage: ` API: { cmd: 'removemod', trip: '' }`, diff --git a/commands/admin/saveconfig.js b/commands/admin/saveconfig.js index a24f422..1407c94 100644 --- a/commands/admin/saveconfig.js +++ b/commands/admin/saveconfig.js @@ -1,13 +1,22 @@ -/* - Description: Writes the current config to disk -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Saves the config + * @version 1.0.0 + * @description Writes the current config to disk + * @module saveconfig + */ import { isAdmin, isModerator, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket }) { // increase rate limit chance and ignore if not admin if (!isAdmin(socket.level)) { @@ -15,7 +24,9 @@ export async function run({ core, server, socket }) { } // attempt save, notify of failure - if (!core.configManager.save()) { + try { + await core.appConfig.write(); + } catch (err) { return server.reply({ cmd: 'warn', // @todo Add numeric error code as `id` text: 'Failed to save config, check logs.', @@ -33,8 +44,18 @@ export async function run({ core, server, socket }) { return true; } +/** + * Module meta information + * @public + * @typedef {Object} saveconfig/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'saveconfig', + category: 'admin', description: 'Writes the current config to disk', usage: ` API: { cmd: 'saveconfig' }`, diff --git a/commands/admin/shout.js b/commands/admin/shout.js index fa75058..3e5914a 100644 --- a/commands/admin/shout.js +++ b/commands/admin/shout.js @@ -1,12 +1,21 @@ -/* - Description: Emmits a server-wide message as `info` -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Emit text everywhere + * @version 1.0.0 + * @description Displays passed text to every client connected + * @module shout + */ import { isAdmin, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ server, socket, payload }) { // increase rate limit chance and ignore if not admin if (!isAdmin(socket.level)) { @@ -23,9 +32,26 @@ export async function run({ server, socket, payload }) { return true; } +/** + * The following payload properties are required to invoke this module: + * "text" + * @public + * @typedef {Array} shout/requiredData + */ export const requiredData = ['text']; + +/** + * Module meta information + * @public + * @typedef {Object} shout/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'shout', + category: 'admin', description: 'Displays passed text to every client connected', usage: ` API: { cmd: 'shout', text: '' }`, diff --git a/commands/core/changecolor.js b/commands/core/changecolor.js index 0eecdcd..5143c7b 100644 --- a/commands/core/changecolor.js +++ b/commands/core/changecolor.js @@ -1,19 +1,34 @@ -/* - Description: Allows calling client to change their nickname color -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Update name color + * @version 1.0.0 + * @description Allows calling client to change their nickname color + * @module changecolor + */ import { getUserDetails, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module support functions +/** + * Validate a string as a valid hex color string + * @param {string} color - Color string to validate + * @private + * @todo Move into utility module + * @return {boolean} + */ const verifyColor = (color) => /(^[0-9A-F]{6}$)|(^[0-9A-F]{3}$)/i.test(color); -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ server, socket, payload, }) { - const channel = socket.channel; + const { channel } = socket; if (server.police.frisk(socket.address, 1)) { return server.reply({ @@ -25,7 +40,7 @@ export async function run({ // verify user data is string if (typeof payload.color !== 'string') { - return true; + return false; } // make sure requested nickname meets standards @@ -60,12 +75,24 @@ export async function run({ return true; } -// module hook functions +/** + * Automatically executes once after server is ready to register this modules hooks + * @param {Object} server - Reference to server enviroment object + * @public + * @return {void} + */ export function initHooks(server) { server.registerHook('in', 'chat', this.colorCheck.bind(this), 29); } -// hooks chat commands checking for /color +/** + * Executes every time an incoming chat command is invoked + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function colorCheck({ core, server, socket, payload, }) { @@ -103,11 +130,27 @@ export function colorCheck({ return payload; } -// module meta +/** + * The following payload properties are required to invoke this module: + * "color" + * @public + * @typedef {Array} changecolor/requiredData + */ export const requiredData = ['color']; + +/** + * Module meta information + * @public + * @typedef {Object} changecolor/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'changecolor', - description: 'This will change your nickname color', + category: 'core', + description: 'Allows calling client to change their nickname color', usage: ` API: { cmd: 'changecolor', color: '' } Text: /color diff --git a/commands/core/changenick.js b/commands/core/changenick.js index 8bc3b6d..664561e 100644 --- a/commands/core/changenick.js +++ b/commands/core/changenick.js @@ -1,19 +1,28 @@ /* eslint eqeqeq: 0 */ -/* - Description: Allows calling client to change their current nickname -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Update nickname + * @version 1.0.0 + * @description Allows calling client to change their current nickname + * @module changenick + */ import { verifyNickname, getUserDetails, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ - core, server, socket, payload, + server, socket, payload, }) { - const channel = socket.channel; + const { channel } = socket; if (server.police.frisk(socket.address, 6)) { return server.reply({ @@ -40,18 +49,6 @@ export async function run({ }, socket); } - // prevent admin impersonation - // @todo prevent mod impersonation - if (newNick.toLowerCase() === core.config.adminName.toLowerCase()) { - server.police.frisk(socket.address, 4); - - return server.reply({ - cmd: 'warn', // @todo Add numeric error code as `id` - text: 'You are not the admin, liar!', - channel, // @todo Multichannel - }, socket); - } - if (newNick == previousNick) { return server.reply({ cmd: 'warn', // @todo Add numeric error code as `id` @@ -132,12 +129,24 @@ export async function run({ return true; } -// module hook functions +/** + * Automatically executes once after server is ready to register this modules hooks + * @param {Object} server - Reference to server enviroment object + * @public + * @return {void} + */ export function initHooks(server) { server.registerHook('in', 'chat', this.nickCheck.bind(this), 29); } -// hooks chat commands checking for /nick +/** + * Executes every time an incoming chat command is invoked + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function nickCheck({ core, server, socket, payload, }) { @@ -149,7 +158,7 @@ export function nickCheck({ const input = payload.text.split(' '); // If there is no nickname target parameter - if (input[1] === undefined) { + if (!input[1]) { server.reply({ cmd: 'warn', // @todo Add numeric error code as `id` text: 'Refer to `/help nick` for instructions on how to use this command.', @@ -177,10 +186,27 @@ export function nickCheck({ return payload; } +/** + * The following payload properties are required to invoke this module: + * "nick" + * @public + * @typedef {Array} changenick/requiredData + */ export const requiredData = ['nick']; + +/** + * Module meta information + * @public + * @typedef {Object} changenick/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'changenick', - description: 'This will change your current connections nickname', + category: 'core', + description: 'Allows calling client to change their current nickname', usage: ` API: { cmd: 'changenick', nick: '' } Text: /nick `, diff --git a/commands/core/chat.js b/commands/core/chat.js index 65e26c4..fdd8eb9 100644 --- a/commands/core/chat.js +++ b/commands/core/chat.js @@ -1,13 +1,23 @@ -/* - Description: Rebroadcasts any `text` to all clients in a `channel` -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Send chat messages + * @version 1.0.0 + * @description Broadcasts passed `text` field to the calling users channel + * @module chat + */ import { isAdmin, isModerator, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module support functions +/** + * Check and trim string provided by remote client + * @param {string} text - Subject string + * @private + * @todo Move into utility module + * @return {string|boolean} + */ const parseText = (text) => { // verifies user input is text if (typeof text !== 'string') { @@ -24,7 +34,12 @@ const parseText = (text) => { return sanitizedText; }; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket, payload, }) { @@ -80,13 +95,26 @@ export async function run({ return true; } -// module hook functions +/** + * Automatically executes once after server is ready to register this modules hooks + * @param {Object} server - Reference to server enviroment object + * @public + * @return {void} + */ export function initHooks(server) { server.registerHook('in', 'chat', this.commandCheckIn.bind(this), 20); server.registerHook('in', 'chat', this.finalCmdCheck.bind(this), 254); } -// checks for miscellaneous '/' based commands +/** + * Executes every time an incoming chat command is invoked; + * checks for miscellaneous '/' based commands + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function commandCheckIn({ server, socket, payload }) { if (typeof payload.text !== 'string') { return false; @@ -105,6 +133,15 @@ export function commandCheckIn({ server, socket, payload }) { return payload; } +/** + * Executes every time an incoming chat command is invoked; + * assumes a failed chat command invocation and will reject with notice + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function finalCmdCheck({ server, socket, payload }) { if (typeof payload.text !== 'string') { return false; @@ -129,9 +166,26 @@ export function finalCmdCheck({ server, socket, payload }) { return false; } +/** + * The following payload properties are required to invoke this module: + * "text" + * @public + * @typedef {Array} chat/requiredData + */ export const requiredData = ['text']; + +/** + * Module meta information + * @public + * @typedef {Object} chat/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'chat', + category: 'core', description: 'Broadcasts passed `text` field to the calling users channel', usage: ` API: { cmd: 'chat', text: '' } diff --git a/commands/core/emote.js b/commands/core/emote.js index da64596..e080504 100644 --- a/commands/core/emote.js +++ b/commands/core/emote.js @@ -1,8 +1,18 @@ -/* - Description: Broadcasts an emote to the current channel -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Emote / action text + * @version 1.0.0 + * @description Broadcasts an emote to the current channel + * @module emote + */ -// module support functions +/** + * Check and trim string provided by remote client + * @param {string} text - Subject string + * @private + * @todo Move into utility module + * @return {string|boolean} + */ const parseText = (text) => { // verifies user input is text if (typeof text !== 'string') { @@ -19,7 +29,12 @@ const parseText = (text) => { return sanitizedText; }; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ server, socket, payload }) { // check user input let text = parseText(payload.text); @@ -61,12 +76,25 @@ export async function run({ server, socket, payload }) { return true; } -// module hook functions +/** + * Automatically executes once after server is ready to register this modules hooks + * @param {Object} server - Reference to server enviroment object + * @public + * @return {void} + */ export function initHooks(server) { server.registerHook('in', 'chat', this.emoteCheck.bind(this), 30); } -// hooks chat commands checking for /me +/** + * Executes every time an incoming chat command is invoked; + * hooks chat commands checking for /me + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function emoteCheck({ core, server, socket, payload, }) { @@ -107,10 +135,27 @@ export function emoteCheck({ return payload; } +/** + * The following payload properties are required to invoke this module: + * "text" + * @public + * @typedef {Array} emote/requiredData + */ export const requiredData = ['text']; + +/** + * Module meta information + * @public + * @typedef {Object} emote/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'emote', - description: 'Typical emote / action text', + category: 'core', + description: 'Broadcasts an emote to the current channel', usage: ` API: { cmd: 'emote', text: '' } Text: /me `, diff --git a/commands/core/help.js b/commands/core/help.js index ad03ff3..b8e70b2 100644 --- a/commands/core/help.js +++ b/commands/core/help.js @@ -1,8 +1,17 @@ -/* - Description: Outputs the current command module list or command categories -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Get help + * @version 1.0.0 + * @description Outputs information about the servers current protocol + * @module help + */ -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket, payload, }) { @@ -61,12 +70,25 @@ export async function run({ return true; } -// module hook functions +/** + * Automatically executes once after server is ready to register this modules hooks + * @param {Object} server - Reference to server enviroment object + * @public + * @return {void} + */ export function initHooks(server) { server.registerHook('in', 'chat', this.helpCheck.bind(this), 28); } -// hooks chat commands checking for /whisper +/** + * Executes every time an incoming chat command is invoked; + * hooks chat commands checking for /help + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function helpCheck({ core, server, socket, payload, }) { @@ -93,8 +115,18 @@ export function helpCheck({ return payload; } +/** + * Module meta information + * @public + * @typedef {Object} help/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'help', + category: 'core', description: 'Outputs information about the servers current protocol', usage: ` API: { cmd: 'help', command: '' } diff --git a/commands/core/invite.js b/commands/core/invite.js index 092a30f..09b2670 100644 --- a/commands/core/invite.js +++ b/commands/core/invite.js @@ -1,22 +1,26 @@ -/* - Description: Generates a semi-unique channel name then broadcasts it to each client -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Send an invite + * @version 1.0.0 + * @description Sends an invite to the target client with the provided channel, or a random channel + * @module invite + */ import { findUser, -} from '../utility/_Channels'; +} from '../utility/_Channels.js'; import { Errors, -} from '../utility/_Constants'; +} from '../utility/_Constants.js'; import { legacyInviteOut, legacyInviteReply, -} from '../utility/_LegacyFunctions'; +} from '../utility/_LegacyFunctions.js'; -// module support functions /** * Returns the channel that should be invited to. * @param {any} channel + * @private * @return {string} */ export function getChannel(channel = undefined) { @@ -26,7 +30,12 @@ export function getChannel(channel = undefined) { return Math.random().toString(36).substr(2, 8); } -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket, payload, }) { @@ -96,9 +105,18 @@ export async function run({ return true; } -export const requiredData = []; // ['nick']; +/** + * Module meta information + * @public + * @typedef {Object} invite/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'invite', + category: 'core', description: 'Sends an invite to the target client with the provided channel, or a random channel.', usage: ` API: { cmd: 'invite', nick: '', to: '' }`, diff --git a/commands/core/join.js b/commands/core/join.js index 45e6446..8956376 100644 --- a/commands/core/join.js +++ b/commands/core/join.js @@ -1,29 +1,44 @@ /* eslint no-param-reassign: 0 */ +/* eslint import/no-cycle: [0, { ignoreExternal: true }] */ -/* - Description: Adds requested channel into the calling clients "subscribed channels" -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Join target channel + * @version 1.0.0 + * @description Join the target channel using the supplied nick and password + * @module join + */ +import { + getSession, +} from './session.js'; import { canJoinChannel, -} from '../utility/_Channels'; + socketInChannel, +} from '../utility/_Channels.js'; import { Errors, -} from '../utility/_Constants'; +} from '../utility/_Constants.js'; import { upgradeLegacyJoin, legacyLevelToLabel, -} from '../utility/_LegacyFunctions'; +} from '../utility/_LegacyFunctions.js'; import { verifyNickname, getUserPerms, getUserDetails, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket, payload, -}) { // check for spam +}) { + // check for spam if (server.police.frisk(socket.address, 3)) { return server.reply({ cmd: 'warn', @@ -75,7 +90,7 @@ export async function run({ } // get trip and level - const { trip, level } = getUserPerms(pass, core.config, channel); + const { trip, level } = getUserPerms(pass, core.saltKey, core.appConfig.data, channel); // store the user values const userInfo = { @@ -90,13 +105,6 @@ export async function run({ channel, }; - // prevent admin impersonation - if (nick.toLowerCase() === core.config.adminName.toLowerCase()) { - if (userInfo.trip !== 'Admin') { - userInfo.nick = `Fake${userInfo.nick}`; - } - } - // check if the nickname already exists in the channel const userExists = server.findSockets({ channel, @@ -141,6 +149,7 @@ export async function run({ socket.channel = channel; /* @legacy */ // @todo multi-channel patch // socket.channels.push(channel); + socket.channels = [channel]; nicks.push(userInfo.nick); /* @legacy */ users.push({ ...{ isme: true, isBot: socket.isBot }, ...userInfo }); @@ -153,15 +162,110 @@ export async function run({ channel, // @todo Multichannel (?) }, socket); + // update client with new session info + server.reply({ + cmd: 'session', + restored: false, + token: getSession(socket, core), + channels: socket.channels, + }, socket); + // stats are fun core.stats.increment('users-joined'); return true; } -export const requiredData = []; // ['channel', 'nick']; +export function restoreJoin({ + server, socket, channel, +}) { + // check if a client is able to join target channel + const mayJoin = canJoinChannel(channel, socket); + if (mayJoin !== true) { + return server.reply({ + cmd: 'warn', + text: 'You may not join that channel.', + id: mayJoin, + channel: false, // @todo Multichannel, false for global event + }, socket); + } + + // store the user values + const userInfo = { + nick: socket.nick, + trip: socket.trip, + uType: legacyLevelToLabel(socket.level), + hash: socket.hash, + level: socket.level, + userid: socket.userid, + isBot: socket.isBot, + color: socket.color, + channel, + }; + + // prepare to notify channel peers + const newPeerList = server.findSockets({ channel }); + const nicks = []; /* @legacy */ + const users = []; + const joinAnnouncement = { ...{ cmd: 'onlineAdd' }, ...userInfo }; + // build update notice with new privileges + const updateAnnouncement = { + ...getUserDetails(socket), + ...{ + cmd: 'updateUser', + online: true, + }, + }; + + const isDuplicate = socketInChannel(server, channel, socket); + + // send join announcement and prep online set reply + for (let i = 0, l = newPeerList.length; i < l; i += 1) { + if (isDuplicate) { + server.reply(updateAnnouncement, newPeerList[i]); + } else { + server.reply(joinAnnouncement, newPeerList[i]); + } + + nicks.push(newPeerList[i].nick); /* @legacy */ + users.push({ + ...{ + channel, + isme: false, + }, + ...getUserDetails(newPeerList[i]), + }); + } + + nicks.push(userInfo.nick); /* @legacy */ + users.push({ ...{ isme: true, isBot: socket.isBot }, ...userInfo }); + + // reply with channel peer list + server.reply({ + cmd: 'onlineSet', + nicks, /* @legacy */ + users, + channel, // @todo Multichannel (?) + }, socket); + + socket.channel = channel; /* @legacy */ + socket.channels.push(channel); + + return true; +} + +/** + * Module meta information + * @public + * @typedef {Object} join/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'join', + category: 'core', description: 'Join the target channel using the supplied nick and password', usage: ` API: { cmd: 'join', nick: '', pass: '', channel: '' }`, diff --git a/commands/core/morestats.js b/commands/core/morestats.js index f2a9612..93cdc5c 100644 --- a/commands/core/morestats.js +++ b/commands/core/morestats.js @@ -1,10 +1,17 @@ -/* - Description: Outputs more info than the legacy stats command -*/ - -// module support functions -const { stripIndents } = require('common-tags'); +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Get stats + * @version 1.0.0 + * @description Sends back current server stats to the calling client + * @module morestats + */ +/** + * Format input time into string + * @param {Date} time - Subject date + * @private + * @return {string} + */ const formatTime = (time) => { let seconds = time[0] + time[1] / 1e9; @@ -20,50 +27,101 @@ const formatTime = (time) => { return `${days.toFixed(0)}d ${hours.toFixed(0)}h ${minutes.toFixed(0)}m ${seconds.toFixed(0)}s`; }; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket }) { // gather connection and channel count - let ips = {}; - let channels = {}; - // for (const client of server.clients) { + const ips = {}; + const channels = {}; + // @todo use public channels from core.appConfig.data + const publicChanCounts = { + lounge: 0, + meta: 0, + math: 0, + physics: 0, + chemistry: 0, + technology: 0, + programming: 0, + games: 0, + banana: 0, + chinese: 0, + }; + + // @todo code resuage between here and `session`; should share exported function server.clients.forEach((client) => { if (client.channel) { channels[client.channel] = true; ips[client.address] = true; + if (typeof publicChanCounts[client.channel] !== 'undefined') { + publicChanCounts[client.channel] += 1; + } } }); const uniqueClientCount = Object.keys(ips).length; const uniqueChannels = Object.keys(channels).length; - - ips = null; - channels = null; + const joins = core.stats.get('users-joined') || 0; + const invites = core.stats.get('invites-sent') || 0; + const messages = core.stats.get('messages-sent') || 0; + const banned = core.stats.get('users-banned') || 0; + const kicked = core.stats.get('users-kicked') || 0; + const stats = core.stats.get('stats-requested') || 0; + const uptime = formatTime(process.hrtime(core.stats.get('start-time'))); // dispatch info server.reply({ cmd: 'info', - text: stripIndents`current-connections: ${uniqueClientCount} - current-channels: ${uniqueChannels} - users-joined: ${(core.stats.get('users-joined') || 0)} - invites-sent: ${(core.stats.get('invites-sent') || 0)} - messages-sent: ${(core.stats.get('messages-sent') || 0)} - 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')))}`, + users: uniqueClientCount, + chans: uniqueChannels, + joins, + invites, + messages, + banned, + kicked, + stats, + uptime, + public: publicChanCounts, + text: `current-connections: ${uniqueClientCount} +current-channels: ${uniqueChannels} +users-joined: ${joins} +invites-sent: ${invites} +messages-sent: ${messages} +users-banned: ${banned} +users-kicked: ${kicked} +stats-requested: ${stats} +server-uptime: ${uptime}`, channel: socket.channel, // @todo Multichannel }, socket); // stats are fun core.stats.increment('stats-requested'); + + return true; } -// module hook functions +/** + * Automatically executes once after server is ready to register this modules hooks + * @param {Object} server - Reference to server enviroment object + * @public + * @return {void} + */ export function initHooks(server) { server.registerHook('in', 'chat', this.statsCheck.bind(this), 26); } -// hooks chat commands checking for /stats +/** + * Executes every time an incoming chat command is invoked; + * hooks chat commands checking for /stats + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function statsCheck({ core, server, socket, payload, }) { @@ -87,8 +145,18 @@ export function statsCheck({ return payload; } +/** + * Module meta information + * @public + * @typedef {Object} morestats/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'morestats', + category: 'core', description: 'Sends back current server stats to the calling client', usage: ` API: { cmd: 'morestats' } diff --git a/commands/core/move.js b/commands/core/move.js deleted file mode 100644 index de6a4fb..0000000 --- a/commands/core/move.js +++ /dev/null @@ -1,171 +0,0 @@ -/* - Description: Changes the current channel of the calling socket - @deprecated This module will be removed or replaced -*/ -import { - getUserDetails, -} from '../utility/_UAC'; - -// module main -export async function run({ server, socket, payload }) { - // check for spam - if (server.police.frisk(socket.address, 6)) { - return server.reply({ - cmd: 'warn', // @todo Add numeric error code as `id` - text: 'You are changing channels too fast. Wait a moment before trying again.', - channel: socket.channel, // @todo Multichannel - }, socket); - } - - // check user input - if (typeof payload.channel !== 'string') { - return true; - } - - if (payload.channel === '') { - return server.reply({ - cmd: 'warn', // @todo Add numeric error code as `id` - text: 'Cannot move to an empty channel.', - channel: socket.channel, // @todo Multichannel - }, socket); - } - - if (payload.channel === socket.channel) { // @todo Multichannel update - // they are trying to rejoin the channel - return true; - } - - // check that the nickname isn't already in target channel - const currentNick = socket.nick.toLowerCase(); - const userExists = server.findSockets({ - channel: payload.channel, - nick: (targetNick) => targetNick.toLowerCase() === currentNick, - }); - - if (userExists.length > 0) { - // That nickname is already in that channel - return true; - } - - // broadcast leave notice to peers - const peerList = server.findSockets({ channel: socket.channel }); - - if (peerList.length > 1) { - for (let i = 0, l = peerList.length; i < l; i += 1) { - server.reply({ - cmd: 'onlineRemove', - nick: peerList[i].nick, - userid: peerList[i].userid, - channel: socket.channel, // @todo Multichannel - }, socket); - - if (socket.userid !== peerList[i].userid) { - server.reply({ - cmd: 'onlineRemove', - nick: socket.nick, - userid: socket.userid, - channel: socket.channel, // @todo Multichannel - }, peerList[i]); - } - } - } - - // broadcast join notice to new peers - const newPeerList = server.findSockets({ channel: payload.channel }); - const moveAnnouncement = { - ...{ - cmd: 'onlineAdd', - channel: payload.channel, // @todo Multichannel - }, - ...getUserDetails(socket), - }; - - const nicks = []; - const users = []; - - for (let i = 0, l = newPeerList.length; i < l; i += 1) { - server.reply(moveAnnouncement, newPeerList[i]); - - nicks.push(newPeerList[i].nick); /* @legacy */ - users.push({ - ...{ - channel: payload.channel, - isme: false, - }, - ...getUserDetails(newPeerList[i]), - }); - } - - nicks.push(socket.nick); /* @legacy */ - users.push({ - ...{ - channel: payload.channel, - isme: true, - }, - ...getUserDetails(socket), - }); - - // reply with new user list - server.reply({ - cmd: 'onlineSet', - nicks, - users, - channel: socket.channel, // @todo Multichannel (!) - }, socket); - - // commit change - socket.channel = payload.channel; // eslint-disable-line no-param-reassign - - return true; -} - -// module hook functions -export function initHooks(server) { - server.registerHook('in', 'chat', this.moveCheck.bind(this), 29); -} - -export function moveCheck({ - core, server, socket, payload, -}) { - if (typeof payload.text !== 'string') { - return false; - } - - if (payload.text.startsWith('/move ')) { - const input = payload.text.split(' '); - - // If there is no channel target parameter - if (input[1] === undefined) { - server.reply({ - cmd: 'warn', // @todo Add numeric error code as `id` - text: 'Refer to `/help move` for instructions on how to use this command.', - channel: socket.channel, // @todo Multichannel - }, socket); - - return false; - } - - this.run({ - core, - server, - socket, - payload: { - cmd: 'move', - channel: input[1], - }, - }); - - return false; - } - - return payload; -} - -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: '' } - Text: /move `, -}; diff --git a/commands/core/ping.js b/commands/core/ping.js index 642a526..f387bb7 100644 --- a/commands/core/ping.js +++ b/commands/core/ping.js @@ -1,12 +1,32 @@ /* eslint no-empty-function: 0 */ -/* - Description: This module is only in place to supress error notices legacy sources may get -*/ -// module main +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Legacy support module + * @version 1.0.0 + * @description This module is only in place to supress error notices legacy clients may get + * @module ping + */ + +/** + * Executes when invoked by a remote client + * @public + * @return {void} + */ export async function run() { } +/** + * Module meta information + * @public + * @typedef {Object} ping/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'ping', - description: 'This module is only in place to supress error notices legacy sources may get', + category: 'core', + description: 'This module is only in place to supress error notices legacy clients may get', + usage: 'none', }; diff --git a/commands/core/session.js b/commands/core/session.js index 1e4249b..eebed57 100644 --- a/commands/core/session.js +++ b/commands/core/session.js @@ -1,76 +1,193 @@ -/* eslint no-param-reassign: 0 */ +/* eslint import/no-cycle: [0, { ignoreExternal: true }] */ -/* - Description: Create a new socket session or restore previous session -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Restore session + * @version 1.0.0 + * @description Restore previous state by session + * @module session + */ -// module support functions -const createSessionID = () => { - let sessionID = ''; - for (let i = 0, j = 32; i < j; i += 1) { - sessionID += Math.random().toString(36).substr(2, 9); - } - return sessionID; -}; +import fs from 'fs'; +import jsonwebtoken from 'jsonwebtoken'; -// module main -export async function run({ server, socket, payload }) { - // gather connection and channel count - let ips = {}; - let channels = {}; - // @todo use public channel flag - const publicChanCounts = { - lounge: 0, - meta: 0, - math: 0, - physics: 0, - chemistry: 0, - technology: 0, - programming: 0, - games: 0, - banana: 0, - chinese: 0, - }; +import { + verifyNickname, +} from '../utility/_UAC.js'; +import { + Errors, +} from '../utility/_Constants.js'; +import { + restoreJoin, +} from './join.js'; - // todo code resuage between here and `morestats`, export function - server.clients.forEach((client) => { - if (client.channel) { - channels[client.channel] = true; - ips[client.address] = true; - if (typeof publicChanCounts[client.channel] !== 'undefined') { - publicChanCounts[client.channel] += 1; - } - } +const SessionLocation = './session.key'; + +/** + * Get a fresh session string for target socket + * @param {Object} socket + * @param {Object} core + * @returns {object} + */ +export function getSession(socket, core) { + return jsonwebtoken.sign({ + channel: socket.channel, + channels: socket.channels, + color: socket.color, + isBot: socket.isBot, + level: socket.level, + nick: socket.nick, + trip: socket.trip, + userid: socket.userid, + uType: socket.uType, /* @legacy */ + muzzled: socket.muzzled || false, + banned: socket.banned || false, + }, core.sessionKey, { + expiresIn: '7 days', }); - - const uniqueClientCount = Object.keys(ips).length; - const uniqueChannels = Object.keys(channels).length; - - ips = null; - channels = null; - - // @todo restore session - socket.sessionID = createSessionID(); - socket.hcProtocol = 2; - socket.userid = Math.floor(Math.random() * 9999999999999); - socket.hash = server.getSocketHash(socket); - socket.isBot = payload.isBot || false; - socket.color = false; - - // dispatch info - server.reply({ - cmd: 'session', - users: uniqueClientCount, - chans: uniqueChannels, - public: publicChanCounts, - sessionID: socket.sessionID, - restored: false, - }, socket); } +/** + * Reply to target socket with session failure notice + * @param {Object} server + * @param {Object} socket + * @returns {boolean} + */ +function notifyFailure(server, socket) { + server.reply({ + cmd: 'error', + id: Errors.Session.BAD_SESSION, + text: 'Invalid session', + }, socket); + + return false; +} + +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ +export async function run({ + core, server, socket, payload, +}) { + if (typeof payload.token === 'undefined') { + return notifyFailure(server, socket); + } + + let session = false; + try { + session = jsonwebtoken.verify(payload.token, core.sessionKey); + } catch (err) { + return notifyFailure(server, socket); + } + + // validate session + if (typeof session.channel !== 'string') { + return notifyFailure(server, socket); + } + + if (Array.isArray(session.channels) === false) { + return notifyFailure(server, socket); + } + + if (typeof session.color !== 'string' && typeof session.color !== 'boolean') { + return notifyFailure(server, socket); + } + + if (typeof session.isBot !== 'boolean') { + return notifyFailure(server, socket); + } + + if (typeof session.level !== 'number') { + return notifyFailure(server, socket); + } + + if (verifyNickname(session.nick) === false) { + return notifyFailure(server, socket); + } + + if (typeof session.trip !== 'string') { + return notifyFailure(server, socket); + } + + if (typeof session.userid !== 'number') { + return notifyFailure(server, socket); + } + + if (typeof session.uType !== 'string') { + return notifyFailure(server, socket); + } + + if (typeof session.muzzled !== 'boolean') { + return notifyFailure(server, socket); + } + + if (typeof session.banned !== 'boolean') { + return notifyFailure(server, socket); + } + + // populate socket info with validated session + socket.channels = []; + socket.color = session.color; + socket.isBot = session.isBot; + socket.level = session.level; + socket.nick = session.nick; + socket.trip = session.trip; + socket.userid = session.userid; + socket.uType = session.uType; /* @legacy */ + socket.muzzled = session.muzzled; + socket.banned = session.banned; + + socket.hash = server.getSocketHash(socket); + socket.hcProtocol = 2; + + for (let i = 0, j = session.channels.length; i < j; i += 1) { + restoreJoin({ + core, + server, + socket, + channel: session.channels[i], + }, true); + } + + // dispatch updated session + server.reply({ + cmd: 'session', + restored: true, + token: getSession(socket, core), + channels: socket.channels, + }, socket); + + return true; +} + +/** + * Automatically executes once after server is ready + * @param {Object} core - Reference to core enviroment object + * @public + * @return {void} + */ +export function init(core) { + // load the encryption key if required + if (typeof core.sessionKey === 'undefined') { + core.sessionKey = fs.readFileSync(SessionLocation); + } +} + +/** + * Module meta information + * @public + * @typedef {Object} session/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'session', - description: 'Restore previous state by session id or return new session id (currently unavailable)', - usage: ` - API: { cmd: 'session', id: '' }`, + category: 'core', + description: 'Restore previous state by session or create new session', + usage: "API: { cmd: 'session', id: '' }", }; diff --git a/commands/core/stats.js b/commands/core/stats.js index e3e58fa..69f5a07 100644 --- a/commands/core/stats.js +++ b/commands/core/stats.js @@ -1,8 +1,17 @@ -/* - Description: Legacy stats output, kept for compatibility, outputs user and channel count -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Simple stats + * @version 1.0.0 + * @description Sends back legacy server stats to the calling client + * @module stats + */ -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket }) { // gather connection and channel count let ips = {}; @@ -32,8 +41,18 @@ export async function run({ core, server, socket }) { core.stats.increment('stats-requested'); } +/** + * Module meta information + * @public + * @typedef {Object} stats/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'stats', + category: 'core', description: 'Sends back legacy server stats to the calling client', usage: ` API: { cmd: 'stats' }`, diff --git a/commands/core/whisper.js b/commands/core/whisper.js index 3c0b18b..317c756 100644 --- a/commands/core/whisper.js +++ b/commands/core/whisper.js @@ -1,21 +1,31 @@ -/* - Description: Display text on targets screen that only they can see - @todo This should be changed to it's own event type, instead of `info` +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Send whisper + * @version 1.0.0 + * @description Display text on target users screen that only they can see + * @module whisper + * @todo This should be changed to it's own event type, instead of `info` and accept a `userid` rather than `nick` -*/ + */ import { findUser, -} from '../utility/_Channels'; +} from '../utility/_Channels.js'; import { Errors, -} from '../utility/_Constants'; +} from '../utility/_Constants.js'; import { legacyWhisperOut, legacyWhisperReply, -} from '../utility/_LegacyFunctions'; +} from '../utility/_LegacyFunctions.js'; -// module support functions +/** + * Check and trim string provided by remote client + * @param {string} text - Subject string + * @private + * @todo Move into utility module + * @return {string|boolean} + */ const parseText = (text) => { // verifies user input is text if (typeof text !== 'string') { @@ -32,7 +42,12 @@ const parseText = (text) => { return sanitizedText; }; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ server, socket, payload }) { // if this is a legacy client add missing params to payload if (socket.hcProtocol === 1) { @@ -94,12 +109,25 @@ export async function run({ server, socket, payload }) { return true; } -// module hook functions +/** + * Automatically executes once after server is ready to register this modules hooks + * @param {Object} server - Reference to server enviroment object + * @public + * @return {void} + */ export function initHooks(server) { server.registerHook('in', 'chat', this.whisperCheck.bind(this), 20); } -// hooks chat commands checking for /whisper +/** + * Executes every time an incoming chat command is invoked; + * hooks chat commands checking for /whisper + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function whisperCheck({ core, server, socket, payload, }) { @@ -111,7 +139,7 @@ export function whisperCheck({ const input = payload.text.split(' '); // If there is no nickname target parameter - if (input[1] === undefined) { + if (!input[1]) { server.reply({ cmd: 'warn', // @todo Add numeric error code as `id` text: 'Refer to `/help whisper` for instructions on how to use this command.', @@ -173,10 +201,27 @@ export function whisperCheck({ return payload; } +/** + * The following payload properties are required to invoke this module: + * "nick", "text" + * @public + * @typedef {Array} whisper/requiredData + */ export const requiredData = ['nick', 'text']; + +/** + * Module meta information + * @public + * @typedef {Object} whisper/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'whisper', - description: 'Display text on targets screen that only they can see', + category: 'core', + description: 'Display text on target users screen that only they can see', usage: ` API: { cmd: 'whisper', nick: '', text: '' } Text: /whisper diff --git a/commands/internal/disconnect.js b/commands/internal/disconnect.js index 69bb061..cef5913 100644 --- a/commands/internal/disconnect.js +++ b/commands/internal/disconnect.js @@ -1,9 +1,21 @@ -/* - Description: This module will be directly called by the server event handler - when a socket connection is closed or lost. -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Disconnection handler + * @version 1.0.0 + * @description The server invokes this module each time a websocket connection is disconnected + * @module disconnect + */ -// module main +import { + socketInChannel, +} from '../utility/_Channels.js'; + +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ server, socket, payload }) { if (payload.cmdKey !== server.cmdKey) { // internal command attempt by client, increase rate limit chance and ignore @@ -11,13 +23,16 @@ export async function run({ server, socket, payload }) { } // send leave notice to client peers + // @todo Multichannel update if (socket.channel) { - server.broadcast({ - cmd: 'onlineRemove', - userid: socket.userid, - nick: socket.nick, /* @legacy */ - channel: socket.channel, // @todo Multichannel - }, { channel: socket.channel }); + const isDuplicate = socketInChannel(server, socket.channel, socket); + + if (isDuplicate === false) { + server.broadcast({ + cmd: 'onlineRemove', + nick: socket.nick, + }, { channel: socket.channel }); + } } // commit close just in case @@ -26,9 +41,26 @@ export async function run({ server, socket, payload }) { return true; } +/** + * The following payload properties are required to invoke this module: + * "cmdKey" + * @public + * @typedef {Array} disconnect/requiredData + */ export const requiredData = ['cmdKey']; + +/** + * Module meta information + * @public + * @typedef {Object} disconnect/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'disconnect', + category: 'internal', + description: 'Internally used to relay disconnect events to clients', usage: 'Internal Use Only', - description: 'Internally used to relay `onlineRemove` event to clients', }; diff --git a/commands/internal/socketreply.js b/commands/internal/socketreply.js index 22fa5ba..3c4405c 100644 --- a/commands/internal/socketreply.js +++ b/commands/internal/socketreply.js @@ -1,8 +1,18 @@ -/* - Description: Used to relay warnings to clients internally -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Bridge warning events to a user + * @version 1.0.0 + * @description If a warning occurs within the server, this module will relay the warning to the + * client + * @module socketreply + */ -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ server, socket, payload }) { if (payload.cmdKey !== server.cmdKey) { // internal command attempt by client, increase rate limit chance and ignore @@ -10,18 +20,32 @@ export async function run({ server, socket, payload }) { } // send warning to target socket - server.reply({ - cmd: 'warn', // @todo Add numeric error code as `id` + return server.reply({ + cmd: 'warn', text: payload.text, - channel: socket.channel || false, // @todo Multichannel }, socket); - - return true; } +/** + * The following payload properties are required to invoke this module: + * "cmdKey", "text" + * @public + * @typedef {Array} socketreply/requiredData + */ export const requiredData = ['cmdKey', 'text']; + +/** + * Module meta information + * @public + * @typedef {Object} socketreply/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'socketreply', - usage: 'Internal Use Only', + category: 'internal', description: 'Internally used to relay warnings to clients', + usage: 'Internal Use Only', }; diff --git a/commands/mod/ban.js b/commands/mod/ban.js index 2529633..a791ec9 100644 --- a/commands/mod/ban.js +++ b/commands/mod/ban.js @@ -1,21 +1,29 @@ -/* eslint no-console: 0 */ -/* - Description: Adds the target socket's ip to the ratelimiter -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Ban a user + * @version 1.0.0 + * @description Bans target user by name + * @module ban + */ import { isModerator, getUserDetails, levels, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; import { Errors, -} from '../utility/_Constants'; +} from '../utility/_Constants.js'; import { findUser, -} from '../utility/_Channels'; +} from '../utility/_Channels.js'; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket, payload, }) { @@ -27,12 +35,12 @@ export async function run({ // check user input if (socket.hcProtocol === 1) { if (typeof payload.nick !== 'string') { - return true; + return false; } payload.channel = socket.channel; // eslint-disable-line no-param-reassign } else if (typeof payload.userid !== 'number') { - return true; + return false; } // find target user @@ -89,10 +97,19 @@ export async function run({ return true; } -// export const requiredData = ['nick']; +/** + * Module meta information + * @public + * @typedef {Object} ban/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'ban', - description: 'Disconnects the target nickname in the same channel as calling socket & adds to ratelimiter', + category: 'moderators', + description: 'Bans target user by name', usage: ` API: { cmd: 'ban', nick: '' }`, }; diff --git a/commands/mod/dumb.js b/commands/mod/dumb.js index 4625b58..e50df7f 100644 --- a/commands/mod/dumb.js +++ b/commands/mod/dumb.js @@ -1,29 +1,32 @@ /* eslint no-param-reassign: 0 */ /* eslint no-multi-assign: 0 */ -/* - * Description: Make a user (spammer) dumb (mute) - * Author: simple - */ +/** + * @author OpSimple ( https://github.com/OpSimple ) + * @summary Muzzle a user + * @version 1.0.0 + * @description Globally shadow mute a connection. Optional allies array will see muted messages. + * @module dumb + */ import { isModerator, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; import { findUser, -} from '../utility/_Channels'; +} from '../utility/_Channels.js'; import { Errors, -} from '../utility/_Constants'; +} from '../utility/_Constants.js'; import { legacyInviteReply, legacyWhisperReply, -} from '../utility/_LegacyFunctions'; +} from '../utility/_LegacyFunctions.js'; -// module support functions /** * Returns the channel that should be invited to. * @param {any} channel + * @private * @return {string} */ export function getChannel(channel = undefined) { @@ -33,6 +36,13 @@ export function getChannel(channel = undefined) { return Math.random().toString(36).substr(2, 8); } +/** + * Check and trim string provided by remote client + * @param {string} text - Subject string + * @private + * @todo Move into utility module + * @return {string|boolean} + */ const parseText = (text) => { // verifies user input is text if (typeof text !== 'string') { @@ -49,14 +59,24 @@ const parseText = (text) => { return sanitizedText; }; -// module constructor +/** + * Automatically executes once after server is ready + * @param {Object} core - Reference to core enviroment object + * @public + * @return {void} + */ export function init(core) { if (typeof core.muzzledHashes === 'undefined') { core.muzzledHashes = {}; } } -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket, payload, }) { @@ -78,6 +98,7 @@ export async function run({ // find target user const targetUser = findUser(server, payload); + if (!targetUser) { return server.reply({ cmd: 'warn', @@ -117,14 +138,27 @@ export async function run({ return true; } -// module hook functions +/** + * Automatically executes once after server is ready to register this modules hooks + * @param {Object} server - Reference to server enviroment object + * @public + * @return {void} + */ export function initHooks(server) { server.registerHook('in', 'chat', this.chatCheck.bind(this), 10); server.registerHook('in', 'invite', this.inviteCheck.bind(this), 10); server.registerHook('in', 'whisper', this.whisperCheck.bind(this), 10); } -// hook incoming chat commands, shadow-prevent chat if they are muzzled +/** + * Executes every time an incoming chat command is invoked; + * hook incoming chat commands, shadow-prevent chat if they are muzzled + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function chatCheck({ core, server, socket, payload, }) { @@ -179,7 +213,15 @@ export function chatCheck({ return payload; } -// shadow-prevent all invites from muzzled users +/** + * Executes every time an incoming chat command is invoked; + * shadow-prevent all invites from muzzled users + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function inviteCheck({ core, server, socket, payload, }) { @@ -243,7 +285,15 @@ export function inviteCheck({ return payload; } -// shadow-prevent all whispers from muzzled users +/** + * Executes every time an incoming chat command is invoked; + * shadow-prevent all whispers from muzzled users + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function whisperCheck({ core, server, socket, payload, }) { @@ -304,11 +354,20 @@ export function whisperCheck({ return payload; } -// export const requiredData = ['nick']; +/** + * Module meta information + * @public + * @typedef {Object} dumb/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'dumb', + category: 'moderators', description: 'Globally shadow mute a connection. Optional allies array will see muted messages.', + aliases: ['muzzle', 'mute'], usage: ` API: { cmd: 'dumb', nick: '', allies: ['', ...] }`, }; -info.aliases = ['muzzle', 'mute']; diff --git a/commands/mod/forcecolor.js b/commands/mod/forcecolor.js index 9f24d41..c5be5bd 100644 --- a/commands/mod/forcecolor.js +++ b/commands/mod/forcecolor.js @@ -1,21 +1,37 @@ -/* - Description: Forces a change on the target socket's nick color -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Color a user + * @version 1.0.0 + * @description Forces a user nick to become a certain color + * @module forcecolor + */ import { isModerator, getUserDetails, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; import { Errors, -} from '../utility/_Constants'; +} from '../utility/_Constants.js'; import { findUser, -} from '../utility/_Channels'; +} from '../utility/_Channels.js'; +/** + * Validate a string as a valid hex color string + * @param {string} color - Color string to validate + * @private + * @todo Move into utility module + * @return {boolean} + */ const verifyColor = (color) => /(^[0-9A-F]{6}$)|(^[0-9A-F]{3}$)/i.test(color); -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ server, socket, payload, }) { @@ -24,7 +40,7 @@ export async function run({ return server.police.frisk(socket.address, 10); } - const channel = socket.channel; + const { channel } = socket; if (typeof payload.channel === 'undefined') { payload.channel = channel; } @@ -87,12 +103,25 @@ export async function run({ return true; } -// module hook functions +/** + * Automatically executes once after server is ready to register this modules hooks + * @param {Object} server - Reference to server enviroment object + * @public + * @return {void} + */ export function initHooks(server) { server.registerHook('in', 'chat', this.colorCheck.bind(this), 20); } -// hooks chat commands checking for /whisper +/** + * Executes every time an incoming chat command is invoked; + * hooks chat commands checking for /forcecolor + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/altered payload, + * false = suppress action, + * string = error + */ export function colorCheck({ core, server, socket, payload, }) { @@ -143,10 +172,26 @@ export function colorCheck({ return payload; } -// module meta +/** + * The following payload properties are required to invoke this module: + * "nick", "color" + * @public + * @typedef {Array} forcecolor/requiredData + */ export const requiredData = ['nick', 'color']; + +/** + * Module meta information + * @public + * @typedef {Object} forcecolor/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'forcecolor', + category: 'moderators', description: 'Forces a user nick to become a certain color', usage: ` API: { cmd: 'forcecolor', nick: '', color: '' } diff --git a/commands/mod/kick.js b/commands/mod/kick.js index 183c05f..7520c86 100644 --- a/commands/mod/kick.js +++ b/commands/mod/kick.js @@ -1,22 +1,29 @@ -/* eslint no-console: 0 */ - -/* - Description: Forces a change on the target(s) socket's channel, then broadcasts event -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Give da boot + * @version 1.0.0 + * @description Silently forces target client(s) into another channel + * @module kick + */ import { isModerator, levels, getUserDetails, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; import { Errors, -} from '../utility/_Constants'; +} from '../utility/_Constants.js'; import { findUsers, -} from '../utility/_Channels'; +} from '../utility/_Channels.js'; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket, payload, }) { @@ -127,9 +134,18 @@ export async function run({ return true; } -// export const requiredData = ['nick']; +/** + * Module meta information + * @public + * @typedef {Object} kick/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'kick', + category: 'moderators', description: 'Silently forces target client(s) into another channel. `nick` may be string or array of strings', usage: ` API: { cmd: 'kick', nick: '', to: '' }`, diff --git a/commands/mod/moveuser.js b/commands/mod/moveuser.js deleted file mode 100644 index edae2aa..0000000 --- a/commands/mod/moveuser.js +++ /dev/null @@ -1,136 +0,0 @@ -/* - Description: Removes the target socket from the current channel and forces a join event in another - @deprecated This module will be removed or replaced -*/ - -import { - isModerator, - getUserDetails, -} from '../utility/_UAC'; - -// module main -export async function run({ server, socket, payload }) { - // increase rate limit chance and ignore if not admin or mod - if (!isModerator(socket.level)) { - return server.police.frisk(socket.address, 10); - } - - // check user input - if (typeof payload.nick !== 'string' || typeof payload.channel !== 'string') { - return true; - } - - if (payload.channel === socket.channel) { - // moving them into the same channel? y u do this? - return true; - } - - const badClients = server.findSockets({ channel: socket.channel, nick: payload.nick }); - - if (badClients.length === 0) { - return server.reply({ - cmd: 'warn', // @todo Add numeric error code as `id` - text: 'Could not find user in channel', - channel: socket.channel, // @todo Multichannel - }, socket); - } - - const badClient = badClients[0]; - - if (badClient.level >= socket.level) { - return server.reply({ - cmd: 'warn', // @todo Add numeric error code as `id` - text: 'Cannot move other users of the same level, how rude', - channel: socket.channel, // @todo Multichannel - }, socket); - } - - const currentNick = badClient.nick.toLowerCase(); - const userExists = server.findSockets({ - channel: payload.channel, - nick: (targetNick) => targetNick.toLowerCase() === currentNick, - }); - - if (userExists.length > 0) { - // That nickname is already in that channel - return true; - } - - const peerList = server.findSockets({ channel: socket.channel }); - - if (peerList.length > 1) { - for (let i = 0, l = peerList.length; i < l; i += 1) { - server.reply({ - cmd: 'onlineRemove', - userid: peerList[i].userid, - nick: peerList[i].nick, - channel: socket.channel, // @todo Multichannel - }, badClient); - - if (badClient.nick !== peerList[i].nick) { - server.reply({ - cmd: 'onlineRemove', - userid: badClient.userid, - nick: badClient.nick, - channel: socket.channel, // @todo Multichannel - }, peerList[i]); - } - } - } - - const newPeerList = server.findSockets({ channel: payload.channel }); - const moveAnnouncement = { - ...getUserDetails(badClient), - ...{ - cmd: 'onlineAdd', - channel: payload.channel, // @todo Multichannel - }, - }; - const nicks = []; - const users = []; - for (let i = 0, l = newPeerList.length; i < l; i += 1) { - server.reply(moveAnnouncement, newPeerList[i]); - - nicks.push(newPeerList[i].nick); /* @legacy */ - users.push({ - ...{ - channel: payload.channel, - isme: false, - }, - ...getUserDetails(newPeerList[i]), - }); - } - - nicks.push(badClient.nick); /* @legacy */ - users.push({ - ...{ - isme: true, - }, - ...getUserDetails(badClient), - }); - - server.reply({ - cmd: 'onlineSet', - nicks, /* @legacy */ - users, - channel: payload.channel, // @todo Multichannel (?) - }, badClient); - - badClient.channel = payload.channel; - - server.broadcast({ - cmd: 'info', - text: `${badClient.nick} was moved into ?${payload.channel}`, - channel: payload.channel, // @todo Multichannel - }, { channel: payload.channel }); - - 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: '', channel: '' }`, -}; diff --git a/commands/mod/speak.js b/commands/mod/speak.js index 15b3c10..69330ad 100644 --- a/commands/mod/speak.js +++ b/commands/mod/speak.js @@ -1,22 +1,35 @@ /* eslint no-param-reassign: 0 */ -/* - * Description: Pardon a dumb user to be able to speak again - * Author: simple - */ +/** + * @author OpSimple ( https://github.com/OpSimple ) + * @summary Unmuzzle a user + * @version 1.0.0 + * @description Pardon a dumb user to be able to speak again + * @module speak + */ import { isModerator, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module constructor +/** + * Automatically executes once after server is ready + * @param {Object} core - Reference to core enviroment object + * @public + * @return {void} + */ export function init(core) { if (typeof core.muzzledHashes === 'undefined') { core.muzzledHashes = {}; } } -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket, payload, }) { @@ -74,10 +87,20 @@ export async function run({ return true; } +/** + * Module meta information + * @public + * @typedef {Object} speak/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'speak', + category: 'moderators', description: 'Pardon a dumb user to be able to speak again', + aliases: ['unmuzzle', 'unmute'], usage: ` API: { cmd: 'speak', ip/hash: '' }`, }; diff --git a/commands/mod/unbanall.js b/commands/mod/unbanall.js index 5705704..83f5afc 100644 --- a/commands/mod/unbanall.js +++ b/commands/mod/unbanall.js @@ -1,14 +1,21 @@ -/* eslint no-console: 0 */ - -/* - Description: Clears all bans and ratelimits -*/ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Released them from the void + * @version 1.0.0 + * @description Clears all banned ip addresses + * @module unbanall + */ import { isModerator, -} from '../utility/_UAC'; +} from '../utility/_UAC.js'; -// module main +/** + * Executes when invoked by a remote client + * @param {Object} env - Enviroment object with references to core, server, socket & payload + * @public + * @return {void} + */ export async function run({ core, server, socket }) { // increase rate limit chance and ignore if not admin or mod if (!isModerator(socket.level)) { @@ -39,8 +46,18 @@ export async function run({ core, server, socket }) { return true; } +/** + * Module meta information + * @public + * @typedef {Object} unbanall/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ export const info = { name: 'unbanall', + category: 'moderators', description: 'Clears all banned ip addresses', usage: ` API: { cmd: 'unbanall' }`, diff --git a/commands/utility/_Channels.js b/commands/utility/_Channels.js index 15ba3f4..bf8074a 100644 --- a/commands/utility/_Channels.js +++ b/commands/utility/_Channels.js @@ -1,6 +1,14 @@ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Channel helper + * @version 1.0.0 + * @description Functions to assist with channel manipulation + * @module Channels + */ + import { Errors, -} from './_Constants'; +} from './_Constants.js'; /** * Checks if a client can join `channel`, returns numeric error code or true if @@ -10,12 +18,13 @@ import { * @param {object} socket Target client to evaluate * @return {boolean||error id} */ -// eslint-disable-next-line no-unused-vars export function canJoinChannel(channel, socket) { if (typeof channel !== 'string') return Errors.Channel.INVALID_NAME; if (channel === '') return Errors.Channel.INVALID_NAME; if (channel.length > 120) return Errors.Channel.INVALID_LENGTH; + if (typeof socket.banned !== 'undefined' && socket.banned) return Errors.Channel.DEY_BANNED; + return true; } @@ -28,9 +37,9 @@ export function canJoinChannel(channel, socket) { * @return {object} */ export function getChannelSettings(config, channel) { - if (typeof config.channels !== 'undefined') { - if (typeof config.channels[channel] !== 'undefined') { - return config.channels[channel]; + if (typeof config.permissions !== 'undefined') { + if (typeof config.permissions[channel] !== 'undefined') { + return config.permissions[channel]; } } @@ -83,3 +92,17 @@ export function findUsers(server, payload, limit = 0) { export function findUser(server, payload) { return findUsers(server, payload, 1)[0] || false; } + +/** + * Check if the target socket's userid is already in target channel + * @param {MainServer} server Main server reference + * @param {string} channel Target channel + * @param {object} socket Target client to evaluate + * @return {boolean||object} + */ +export function socketInChannel(server, channel, socket) { + return findUser(server, { + channel, + userid: socket.userid, + }); +} diff --git a/commands/utility/_Constants.js b/commands/utility/_Constants.js index bac25fd..7f567ef 100644 --- a/commands/utility/_Constants.js +++ b/commands/utility/_Constants.js @@ -1,14 +1,23 @@ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Error ID list + * @version 1.0.0 + * @description Exports an object that hold common global error IDs + * @module Constants + */ + /* Base error ranges */ const GlobalErrors = 10; const JoinErrors = 20; const ChannelErrors = 30; const InviteErrors = 40; +const SessionErrors = 50; /** * Holds the numeric id values for each error type * @typedef {object} Errors */ -exports.Errors = { +export const Errors = { Global: { RATELIMIT: GlobalErrors + 1, UNKNOWN_USER: GlobalErrors + 2, @@ -25,9 +34,16 @@ exports.Errors = { Channel: { INVALID_NAME: ChannelErrors + 1, INVALID_LENGTH: ChannelErrors + 2, + DEY_BANNED: ChannelErrors + 3, }, Invite: { RATELIMIT: InviteErrors + 1, }, + + Session: { + BAD_SESSION: SessionErrors + 1, + }, }; + +export default Errors; diff --git a/commands/utility/_LegacyFunctions.js b/commands/utility/_LegacyFunctions.js index 4fa9891..bb9f518 100644 --- a/commands/utility/_LegacyFunctions.js +++ b/commands/utility/_LegacyFunctions.js @@ -1,9 +1,17 @@ /* eslint no-param-reassign: 0 */ +/** + * @author Marzavec ( https://github.com/marzavec ) + * @summary Support functions for old clients + * @version 1.0.0 + * @description Functions to bridge the older v1 clients with the latest protocol + * @module LegacyFunctions + */ + import { isAdmin, isModerator, -} from './_UAC'; +} from './_UAC.js'; /** * Marks the socket as using the legacy protocol and diff --git a/commands/utility/_UAC.js b/commands/utility/_UAC.js index 52e5e7a..f003288 100644 --- a/commands/utility/_UAC.js +++ b/commands/utility/_UAC.js @@ -4,14 +4,16 @@ * @property {Object} levels - Defines labels for default permission ranges * @author MinusGix ( https://github.com/MinusGix ) * @version v1.0.0 - * @license WTFPL ( http://www.wtfpl.net/txt/copying/ ) + * @module UAC */ import { getChannelSettings, -} from './_Channels'; +} from './_Channels.js'; -const crypto = require('crypto'); +const { + createHash, +} = await import('crypto'); /** * Object defining labels for default permission ranges @@ -106,12 +108,13 @@ export function getUserDetails(socket) { return { nick: socket.nick, trip: socket.trip || '', - uType: socket.uType, + uType: socket.uType, /* @legacy */ hash: socket.hash, level: socket.level, userid: socket.userid, isBot: socket.isBot, color: socket.color, + online: true, }; } @@ -132,11 +135,12 @@ export function verifyNickname(nick) { * or a blank string * @public * @param {string} pass User's password + * @param {buffer} salt Server salt data * @param {string} config Server config object * @param {string} channel Channel-level permissions check * @return {string} */ -export function getUserPerms(pass, config, channel) { +export function getUserPerms(pass, salt, config, channel) { if (!pass) { return { trip: '', @@ -144,8 +148,8 @@ export function getUserPerms(pass, config, channel) { }; } - const sha = crypto.createHash('sha256'); - sha.update(pass + config.tripSalt); + const sha = createHash('sha256'); + sha.update(pass + salt); const trip = sha.digest('base64').substr(0, 6); // check if user is global admin @@ -159,7 +163,7 @@ export function getUserPerms(pass, config, channel) { let level = levels.default; // check if user is global mod - config.mods.forEach((mod) => { // eslint-disable-line consistent-return + config.globalMods.forEach((mod) => { // eslint-disable-line consistent-return if (trip === mod.trip) { level = levels.moderator; } diff --git a/documentation/DOCUMENTATION.md b/documentation/DOCUMENTATION.md deleted file mode 100644 index c535cd7..0000000 --- a/documentation/DOCUMENTATION.md +++ /dev/null @@ -1,48 +0,0 @@ -You can programmatically access hack.chat using the following commands via a websocket. A list of wrappers written for accessing hack.chat can be found [here](https://github.com/hack-chat/3rd-party-software-list#libraries). - -The commands are to be sent through a websocket to the URL `wss://hack.chat/chat-ws` (everything sent and received are JSON). If you are sending messages locally or to another domain, replace 'hack.chat' with the respective domain. If you're running your own instance of hack.chat, you can retain backwards-compatibility in order to ensure that software created for the main server will work on yours too. - -All commands sent must be JSON objects with the command specified in the `"cmd"` key. For example: -```json -{ - "cmd": "join", - "channel": "programming", - "nick": "john#doe" -} -``` - -hack.chat has three permission levels. When you access a command, hack.chat automatically knows your permission level from your trip code. The lowest permission level is `user`. `mod` is above `user`, so it can access `user` commands in addition to `mod` commands. `admin` is similarly above `mod`. - -# `user` - -|Command|Parameters|Explanation| -|-------|----------|-----------| -|`changenick`|`nick`|Changes the current connection's nickname.| -|`chat`|`text`|This broadcasts `text` to the channel the user is connected to.| -|`disconnect`||An event handler or forced disconnect.| -|`invite`|`nick`|Generates a pseudo-unique channel name and passes it to both the calling user and `nick`.| -|`join`|`channel`, `nick`|Places the calling socket into the target channel with the target nick and broadcasts the event to the channel.| -|`morestats`||Sends back the current server's stats to the calling client.| -|`move`|`channel`|This will change the current channel to `channel`.| -|`stats`||Sends back legacy server stats to the calling client. Use `morestats` when possible.| -|`help`|`category` or `command`|Gives documentation programmatically. If `category` (the permission level, such as `mod`) is sent, a list of commands available to that permission level will be sent back (as a `string` and not an `array`). This list only includes what is unique to that category and not every command a user with that permission level could perform. If `command` (e.g., `chat`) is sent, a description of the command will be sent back.| - -# `mod` - -|Command|Parameters|Explanation| -|-------|----------|-----------| -|`ban`|`nick`|Disconnects the target nickname in the same channel as the calling socket and adds it to the rate limiter.| -|`kick`|`nick`|Silently forces target client(s) into another channel. `nick` may be `string` or `array` of `string`s.| -|`unban`|`ip` or `hash`|Removes the target ip from the rate limiter.| -|`dumb`|`nick`|Mutes a user's (spammer's) texts such that it is displayable to the user only.| -|`speak`|`ip` or `hash`|Unmutes the user's (spammer's) texts and makes it displayable to everyone again.| - -# `admin` - -|Command|Parameters|Explanation| -|-------|----------|-----------| -|`addmod`|`nick`|Adds the target trip to the config as a mod and upgrades the socket type.| -|`listusers`||Outputs all current channels and sockets in those channels.| -|`reload`||(Re)loads any new commands into memory and outputs errors, if any.| -|`saveconfig`||Saves the current config.| -|`shout`|`text`|Displays the passed text to each client connected.| diff --git a/documentation/admin_addmod.js.html b/documentation/admin_addmod.js.html new file mode 100644 index 0000000..eacf973 --- /dev/null +++ b/documentation/admin_addmod.js.html @@ -0,0 +1,159 @@ + + + + + JSDoc: Source: admin/addmod.js + + + + + + + + + + +
+ +

Source: admin/addmod.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Create a new mod trip
+  * @version 1.0.0
+  * @description Adds target trip to the config as a mod and upgrades the socket type
+  * @module addmod
+  */
+
+import {
+  isAdmin,
+  isModerator,
+  levels,
+  getUserDetails,
+} from '../utility/_UAC.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // increase rate limit chance and ignore if not admin
+  if (!isAdmin(socket.level)) {
+    return server.police.frisk(socket.address, 20);
+  }
+
+  // add new trip to config
+  core.appConfig.data.globalMods.push({ trip: payload.trip });
+
+  // find targets current connections
+  const newMod = server.findSockets({ trip: payload.trip });
+  if (newMod.length !== 0) {
+    // build update notice with new privileges
+    const updateNotice = {
+      ...getUserDetails(newMod[0]),
+      ...{
+        cmd: 'updateUser',
+        uType: 'mod', // @todo use legacyLevelToLabel from _LegacyFunctions.js
+        level: levels.moderator,
+      },
+    };
+
+    for (let i = 0, l = newMod.length; i < l; i += 1) {
+      // upgrade privileges
+      newMod[i].uType = 'mod'; // @todo use legacyLevelToLabel from _LegacyFunctions.js
+      newMod[i].level = levels.moderator;
+
+      // inform new mod
+      server.send({
+        cmd: 'info',
+        text: 'You are now a mod.',
+        channel: newMod[i].channel, // @todo Multichannel
+      }, newMod[i]);
+
+      // notify channel
+      server.broadcast({
+        ...updateNotice,
+        ...{
+          channel: newMod[i].channel,
+        },
+      }, { channel: newMod[i].channel });
+    }
+  }
+
+  // return success message
+  server.reply({
+    cmd: 'info',
+    text: `Added mod trip: ${payload.trip}, remember to run 'saveconfig' to make it permanent`,
+    channel: socket.channel, // @todo Multichannel
+  }, socket);
+
+  // notify all mods
+  server.broadcast({
+    cmd: 'info',
+    text: `Added mod: ${payload.trip}`,
+    channel: false, // @todo Multichannel, false for global info
+  }, { level: isModerator });
+
+  return true;
+}
+
+/**
+  * The following payload properties are required to invoke this module:
+  * "trip"
+  * @public
+  * @typedef {Array} addmod/requiredData
+  */
+export const requiredData = ['trip'];
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} addmod/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'addmod',
+  category: 'admin',
+  description: 'Adds target trip to the config as a mod and upgrades the socket type',
+  usage: `
+    API: { cmd: 'addmod', trip: '<target trip>' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/admin_listusers.js.html b/documentation/admin_listusers.js.html new file mode 100644 index 0000000..fa199b7 --- /dev/null +++ b/documentation/admin_listusers.js.html @@ -0,0 +1,128 @@ + + + + + JSDoc: Source: admin/listusers.js + + + + + + + + + + +
+ +

Source: admin/listusers.js

+ + + + + + +
+
+
/* eslint no-unused-vars: 0 */
+/* eslint no-restricted-syntax: 0 */
+/* eslint guard-for-in: 0 */
+
+/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Show users and channels
+  * @version 1.0.0
+  * @description Outputs all current channels and sockets in those channels
+  * @module listusers
+  */
+
+import {
+  isAdmin,
+} from '../utility/_UAC.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({ server, socket }) {
+  // increase rate limit chance and ignore if not admin
+  if (!isAdmin(socket.level)) {
+    return server.police.frisk(socket.address, 20);
+  }
+
+  // find all users currently in a channel
+  const currentUsers = server.findSockets({
+    channel: (channel) => true,
+  });
+
+  // compile channel and user list
+  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}`,
+    );
+  }
+
+  // build output
+  const lines = [];
+  for (const channel in channels) {
+    lines.push(`?${channel} ${channels[channel].join(', ')}`);
+  }
+
+  // send reply
+  server.reply({
+    cmd: 'info',
+    text: lines.join('\n'),
+    channel: socket.channel, // @todo Multichannel
+  }, socket);
+
+  return true;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} listusers/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'listusers',
+  category: 'admin',
+  description: 'Outputs all current channels and sockets in those channels',
+  usage: `
+    API: { cmd: 'listusers' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/admin_reload.js.html b/documentation/admin_reload.js.html new file mode 100644 index 0000000..f3831f5 --- /dev/null +++ b/documentation/admin_reload.js.html @@ -0,0 +1,122 @@ + + + + + JSDoc: Source: admin/reload.js + + + + + + + + + + +
+ +

Source: admin/reload.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Refresh modules
+  * @version 1.0.0
+  * @description Allows a remote user to clear and re-import the server command modules
+  * @module reload
+  */
+
+import {
+  isAdmin,
+  isModerator,
+} from '../utility/_UAC.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // increase rate limit chance and ignore if not admin
+  if (!isAdmin(socket.level)) {
+    return server.police.frisk(socket.address, 20);
+  }
+
+  // do command reload and store results
+  let loadResult = await core.commands.reloadCommands();
+
+  // clear and rebuild all module hooks
+  server.loadHooks();
+
+  // build reply based on reload results
+  if (loadResult === '') {
+    loadResult = `Reloaded ${core.commands.commands.length} commands, 0 errors`;
+  } else {
+    loadResult = `Reloaded ${core.commands.commands.length} commands, error(s):
+      ${loadResult}`;
+  }
+
+  if (typeof payload.reason !== 'undefined') {
+    loadResult += `\nReason: ${payload.reason}`;
+  }
+
+  // send results to moderators (which the user using this command is higher than)
+  server.broadcast({
+    cmd: 'info',
+    text: loadResult,
+    channel: false, // @todo Multichannel, false for global
+  }, { level: isModerator });
+
+  return true;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} reload/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'reload',
+  category: 'admin',
+  description: 'Allows a remote user to clear and re-import the server command modules',
+  usage: `
+    API: { cmd: 'reload', reason: '<optional reason append>' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/admin_removemod.js.html b/documentation/admin_removemod.js.html new file mode 100644 index 0000000..5d40cd2 --- /dev/null +++ b/documentation/admin_removemod.js.html @@ -0,0 +1,164 @@ + + + + + JSDoc: Source: admin/removemod.js + + + + + + + + + + +
+ +

Source: admin/removemod.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Removes a mod
+  * @version 1.0.0
+  * @description Removes target trip from the config as a mod and downgrades the socket type
+  * @module removemod
+  */
+
+import {
+  isAdmin,
+  isModerator,
+  levels,
+  getUserDetails,
+} from '../utility/_UAC.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // increase rate limit chance and ignore if not admin
+  if (!isAdmin(socket.level)) {
+    return server.police.frisk(socket.address, 20);
+  }
+
+  // remove trip from config
+  // eslint-disable-next-line no-param-reassign
+  core.appConfig.data.globalMods = core.appConfig.data.globalMods.filter(
+    (mod) => mod.trip !== payload.trip,
+  );
+
+  // find targets current connections
+  const targetMod = server.findSockets({ trip: payload.trip });
+  if (targetMod.length !== 0) {
+    // build update notice with new privileges
+    const updateNotice = {
+      ...getUserDetails(targetMod[0]),
+      ...{
+        cmd: 'updateUser',
+        uType: 'user', // @todo use legacyLevelToLabel from _LegacyFunctions.js
+        level: levels.default,
+      },
+    };
+
+    for (let i = 0, l = targetMod.length; i < l; i += 1) {
+      // downgrade privileges
+      targetMod[i].uType = 'user'; /* @legacy */
+      targetMod[i].level = levels.default;
+
+      // inform ex-mod
+      server.send({
+        cmd: 'info',
+        text: 'You are now a user.',
+        channel: targetMod[i].channel, // @todo Multichannel
+      }, targetMod[i]);
+
+      // notify channel
+      server.broadcast({
+        ...updateNotice,
+        ...{
+          channel: targetMod[i].channel,
+        },
+      }, { channel: targetMod[i].channel });
+    }
+  }
+
+  // return success message
+  server.reply({
+    cmd: 'info',
+    text: `Removed mod trip: ${
+      payload.trip
+    }, remember to run 'saveconfig' to make it permanent`,
+    channel: socket.channel, // @todo Multichannel
+  }, socket);
+
+  // notify all mods
+  server.broadcast({
+    cmd: 'info',
+    text: `Removed mod: ${payload.trip}`,
+    channel: false, // @todo Multichannel, false for global
+  }, { level: isModerator });
+
+  return true;
+}
+
+/**
+  * The following payload properties are required to invoke this module:
+  * "trip"
+  * @public
+  * @typedef {Array} removemod/requiredData
+  */
+export const requiredData = ['trip'];
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} removemod/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'removemod',
+  category: 'admin',
+  description: 'Removes target trip from the config as a mod and downgrades the socket type',
+  usage: `
+    API: { cmd: 'removemod', trip: '<target trip>' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/admin_saveconfig.js.html b/documentation/admin_saveconfig.js.html new file mode 100644 index 0000000..a3af560 --- /dev/null +++ b/documentation/admin_saveconfig.js.html @@ -0,0 +1,113 @@ + + + + + JSDoc: Source: admin/saveconfig.js + + + + + + + + + + +
+ +

Source: admin/saveconfig.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Saves the config
+  * @version 1.0.0
+  * @description Writes the current config to disk
+  * @module saveconfig
+  */
+
+import {
+  isAdmin,
+  isModerator,
+} from '../utility/_UAC.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({ core, server, socket }) {
+  // increase rate limit chance and ignore if not admin
+  if (!isAdmin(socket.level)) {
+    return server.police.frisk(socket.address, 20);
+  }
+
+  // attempt save, notify of failure
+  try {
+    await core.appConfig.write();
+  } catch (err) {
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: 'Failed to save config, check logs.',
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // return success message to moderators and admins
+  server.broadcast({
+    cmd: 'info',
+    text: 'Config saved!',
+    channel: false, // @todo Multichannel
+  }, { level: isModerator });
+
+  return true;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} saveconfig/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'saveconfig',
+  category: 'admin',
+  description: 'Writes the current config to disk',
+  usage: `
+    API: { cmd: 'saveconfig' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/admin_shout.js.html b/documentation/admin_shout.js.html new file mode 100644 index 0000000..40b6367 --- /dev/null +++ b/documentation/admin_shout.js.html @@ -0,0 +1,109 @@ + + + + + JSDoc: Source: admin/shout.js + + + + + + + + + + +
+ +

Source: admin/shout.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Emit text everywhere
+  * @version 1.0.0
+  * @description Displays passed text to every client connected
+  * @module shout
+  */
+
+import {
+  isAdmin,
+} from '../utility/_UAC.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({ server, socket, payload }) {
+  // increase rate limit chance and ignore if not admin
+  if (!isAdmin(socket.level)) {
+    return server.police.frisk(socket.address, 20);
+  }
+
+  // send text to all channels
+  server.broadcast({
+    cmd: 'info',
+    text: `Server Notice: ${payload.text}`,
+    channel: false, // @todo Multichannel, false for global
+  }, {});
+
+  return true;
+}
+
+/**
+  * The following payload properties are required to invoke this module:
+  * "text"
+  * @public
+  * @typedef {Array} shout/requiredData
+  */
+export const requiredData = ['text'];
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} shout/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'shout',
+  category: 'admin',
+  description: 'Displays passed text to every client connected',
+  usage: `
+    API: { cmd: 'shout', text: '<shout text>' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_changecolor.js.html b/documentation/core_changecolor.js.html new file mode 100644 index 0000000..5241ad8 --- /dev/null +++ b/documentation/core_changecolor.js.html @@ -0,0 +1,209 @@ + + + + + JSDoc: Source: core/changecolor.js + + + + + + + + + + +
+ +

Source: core/changecolor.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Update name color
+  * @version 1.0.0
+  * @description Allows calling client to change their nickname color
+  * @module changecolor
+  */
+
+import {
+  getUserDetails,
+} from '../utility/_UAC.js';
+
+/**
+  * Validate a string as a valid hex color string
+  * @param {string} color - Color string to validate
+  * @private
+  * @todo Move into utility module
+  * @return {boolean}
+  */
+const verifyColor = (color) => /(^[0-9A-F]{6}$)|(^[0-9A-F]{3}$)/i.test(color);
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  server, socket, payload,
+}) {
+  const { channel } = socket;
+
+  if (server.police.frisk(socket.address, 1)) {
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: 'You are changing colors too fast. Wait a moment before trying again.',
+      channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // verify user data is string
+  if (typeof payload.color !== 'string') {
+    return false;
+  }
+
+  // make sure requested nickname meets standards
+  const newColor = payload.color.trim().toUpperCase().replace(/#/g, '');
+  if (newColor !== 'RESET' && !verifyColor(newColor)) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'Invalid color! Color must be in hex value',
+      channel, // @todo Multichannel
+    }, socket);
+  }
+
+  if (newColor === 'RESET') {
+    socket.color = false; // eslint-disable-line no-param-reassign
+  } else {
+    socket.color = newColor; // eslint-disable-line no-param-reassign
+  }
+
+  // build update notice with new color
+  const updateNotice = {
+    ...getUserDetails(socket),
+    ...{
+      cmd: 'updateUser',
+      channel: socket.channel, // @todo Multichannel
+    },
+  };
+
+  // notify channel that the user has changed their name
+  // @todo this should be sent to every channel the user is in (multichannel)
+  server.broadcast(updateNotice, { channel: socket.channel });
+
+  return true;
+}
+
+/**
+  * Automatically executes once after server is ready to register this modules hooks
+  * @param {Object} server - Reference to server enviroment object
+  * @public
+  * @return {void}
+  */
+export function initHooks(server) {
+  server.registerHook('in', 'chat', this.colorCheck.bind(this), 29);
+}
+
+/**
+  * Executes every time an incoming chat command is invoked
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function colorCheck({
+  core, server, socket, payload,
+}) {
+  if (typeof payload.text !== 'string') {
+    return false;
+  }
+
+  if (payload.text.startsWith('/color ')) {
+    const input = payload.text.split(' ');
+
+    // If there is no color target parameter
+    if (input[1] === undefined) {
+      server.reply({
+        cmd: 'warn',
+        text: 'Refer to `/help changecolor` for instructions on how to use this command.',
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+
+      return false;
+    }
+
+    this.run({
+      core,
+      server,
+      socket,
+      payload: {
+        cmd: 'changecolor',
+        color: input[1],
+      },
+    });
+
+    return false;
+  }
+
+  return payload;
+}
+
+/**
+  * The following payload properties are required to invoke this module:
+  * "color"
+  * @public
+  * @typedef {Array} changecolor/requiredData
+  */
+export const requiredData = ['color'];
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} changecolor/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'changecolor',
+  category: 'core',
+  description: 'Allows calling client to change their nickname color',
+  usage: `
+    API: { cmd: 'changecolor', color: '<new color as hex>' }
+    Text: /color <new color as hex>
+    Removal: /color reset`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_changenick.js.html b/documentation/core_changenick.js.html new file mode 100644 index 0000000..f666107 --- /dev/null +++ b/documentation/core_changenick.js.html @@ -0,0 +1,264 @@ + + + + + JSDoc: Source: core/changenick.js + + + + + + + + + + +
+ +

Source: core/changenick.js

+ + + + + + +
+
+
/* eslint eqeqeq: 0 */
+
+/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Update nickname
+  * @version 1.0.0
+  * @description Allows calling client to change their current nickname
+  * @module changenick
+  */
+
+import {
+  verifyNickname,
+  getUserDetails,
+} from '../utility/_UAC.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  server, socket, payload,
+}) {
+  const { channel } = socket;
+
+  if (server.police.frisk(socket.address, 6)) {
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: 'You are changing nicknames too fast. Wait a moment before trying again.',
+      channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // verify user data is string
+  if (typeof payload.nick !== 'string') {
+    return true;
+  }
+
+  const previousNick = socket.nick;
+
+  // make sure requested nickname meets standards
+  const newNick = payload.nick.trim();
+  if (!verifyNickname(newNick)) {
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: 'Nickname must consist of up to 24 letters, numbers, and underscores',
+      channel, // @todo Multichannel
+    }, socket);
+  }
+
+  if (newNick == previousNick) {
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: 'You already have that name',
+      channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // find any sockets that have the same nickname
+  const userExists = server.findSockets({
+    channel,
+    nick: (targetNick) => targetNick.toLowerCase() === newNick.toLowerCase()
+      // Allow them to rename themselves to a different case
+      && targetNick != previousNick,
+  });
+
+  // return error if found
+  if (userExists.length > 0) {
+    // That nickname is already in that channel
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: 'Nickname taken',
+      channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // build update notice with new nickname
+  const updateNotice = {
+    ...getUserDetails(socket),
+    ...{
+      cmd: 'updateUser',
+      nick: newNick,
+      channel, // @todo Multichannel
+    },
+  };
+
+  // build join and leave notices for legacy clients
+  const leaveNotice = {
+    cmd: 'onlineRemove',
+    userid: socket.userid,
+    nick: socket.nick,
+    channel, // @todo Multichannel
+  };
+
+  const joinNotice = {
+    ...getUserDetails(socket),
+    ...{
+      cmd: 'onlineAdd',
+      nick: newNick,
+      channel, // @todo Multichannel
+    },
+  };
+
+  // gather channel peers
+  const peerList = server.findSockets({ channel });
+  for (let i = 0, l = peerList.length; i < l; i += 1) {
+    if (peerList[i].hcProtocol === 1) {
+      // send join/leave to legacy clients
+      server.send(leaveNotice, peerList[i]);
+      server.send(joinNotice, peerList[i]);
+    } else {
+      // send update info
+      // @todo this should be sent to every channel the client is in (multichannel)
+      server.send(updateNotice, peerList[i]);
+    }
+  }
+
+  // notify channel that the user has changed their name
+  server.broadcast({
+    cmd: 'info',
+    text: `${socket.nick} is now ${newNick}`,
+    channel, // @todo Multichannel
+  }, { channel });
+
+  // commit change to nickname
+  socket.nick = newNick; // eslint-disable-line no-param-reassign
+
+  return true;
+}
+
+/**
+  * Automatically executes once after server is ready to register this modules hooks
+  * @param {Object} server - Reference to server enviroment object
+  * @public
+  * @return {void}
+  */
+export function initHooks(server) {
+  server.registerHook('in', 'chat', this.nickCheck.bind(this), 29);
+}
+
+/**
+  * Executes every time an incoming chat command is invoked
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function nickCheck({
+  core, server, socket, payload,
+}) {
+  if (typeof payload.text !== 'string') {
+    return false;
+  }
+
+  if (payload.text.startsWith('/nick')) {
+    const input = payload.text.split(' ');
+
+    // If there is no nickname target parameter
+    if (!input[1]) {
+      server.reply({
+        cmd: 'warn', // @todo Add numeric error code as `id`
+        text: 'Refer to `/help nick` for instructions on how to use this command.',
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+
+      return false;
+    }
+
+    const newNick = input[1].replace(/@/g, '');
+
+    this.run({
+      core,
+      server,
+      socket,
+      payload: {
+        cmd: 'changenick',
+        nick: newNick,
+      },
+    });
+
+    return false;
+  }
+
+  return payload;
+}
+
+/**
+  * The following payload properties are required to invoke this module:
+  * "nick"
+  * @public
+  * @typedef {Array} changenick/requiredData
+  */
+export const requiredData = ['nick'];
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} changenick/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'changenick',
+  category: 'core',
+  description: 'Allows calling client to change their current nickname',
+  usage: `
+    API: { cmd: 'changenick', nick: '<new nickname>' }
+    Text: /nick <new nickname>`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_chat.js.html b/documentation/core_chat.js.html new file mode 100644 index 0000000..0243531 --- /dev/null +++ b/documentation/core_chat.js.html @@ -0,0 +1,246 @@ + + + + + JSDoc: Source: core/chat.js + + + + + + + + + + +
+ +

Source: core/chat.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Send chat messages
+  * @version 1.0.0
+  * @description Broadcasts passed `text` field to the calling users channel
+  * @module chat
+  */
+
+import {
+  isAdmin,
+  isModerator,
+} from '../utility/_UAC.js';
+
+/**
+  * Check and trim string provided by remote client
+  * @param {string} text - Subject string
+  * @private
+  * @todo Move into utility module
+  * @return {string|boolean}
+  */
+const parseText = (text) => {
+  // verifies user input is text
+  if (typeof text !== 'string') {
+    return false;
+  }
+
+  let sanitizedText = text;
+
+  // strip newlines from beginning and end
+  sanitizedText = sanitizedText.replace(/^\s*\n|^\s+$|\n\s*$/g, '');
+  // replace 3+ newlines with just 2 newlines
+  sanitizedText = sanitizedText.replace(/\n{3,}/g, '\n\n');
+
+  return sanitizedText;
+};
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // check user input
+  const text = parseText(payload.text);
+
+  if (!text) {
+    // lets not send objects or empty text, yea?
+    return server.police.frisk(socket.address, 13);
+  }
+
+  // check for spam
+  const score = text.length / 83 / 4;
+  if (server.police.frisk(socket.address, score)) {
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.',
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // build chat payload
+  const outgoingPayload = {
+    cmd: 'chat',
+    nick: socket.nick, /* @legacy */
+    uType: socket.uType, /* @legacy */
+    userid: socket.userid,
+    channel: socket.channel,
+    text,
+    level: socket.level,
+  };
+
+  if (isAdmin(socket.level)) {
+    outgoingPayload.admin = true;
+  } else if (isModerator(socket.level)) {
+    outgoingPayload.mod = true;
+  }
+
+  if (socket.trip) {
+    outgoingPayload.trip = socket.trip; /* @legacy */
+  }
+
+  if (socket.color) {
+    outgoingPayload.color = socket.color;
+  }
+
+  // broadcast to channel peers
+  server.broadcast(outgoingPayload, { channel: socket.channel });
+
+  // stats are fun
+  core.stats.increment('messages-sent');
+
+  return true;
+}
+
+/**
+  * Automatically executes once after server is ready to register this modules hooks
+  * @param {Object} server - Reference to server enviroment object
+  * @public
+  * @return {void}
+  */
+export function initHooks(server) {
+  server.registerHook('in', 'chat', this.commandCheckIn.bind(this), 20);
+  server.registerHook('in', 'chat', this.finalCmdCheck.bind(this), 254);
+}
+
+/**
+  * Executes every time an incoming chat command is invoked;
+  * checks for miscellaneous '/' based commands
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function commandCheckIn({ server, socket, payload }) {
+  if (typeof payload.text !== 'string') {
+    return false;
+  }
+
+  if (payload.text.startsWith('/myhash')) {
+    server.reply({
+      cmd: 'info',
+      text: `Your hash: ${socket.hash}`,
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+
+    return false;
+  }
+
+  return payload;
+}
+
+/**
+  * Executes every time an incoming chat command is invoked;
+  * assumes a failed chat command invocation and will reject with notice
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function finalCmdCheck({ server, socket, payload }) {
+  if (typeof payload.text !== 'string') {
+    return false;
+  }
+
+  if (!payload.text.startsWith('/')) {
+    return payload;
+  }
+
+  if (payload.text.startsWith('//')) {
+    payload.text = payload.text.substr(1); // eslint-disable-line no-param-reassign
+
+    return payload;
+  }
+
+  server.reply({
+    cmd: 'warn', // @todo Add numeric error code as `id`
+    text: `Unknown command: ${payload.text}`,
+    channel: socket.channel, // @todo Multichannel
+  }, socket);
+
+  return false;
+}
+
+/**
+  * The following payload properties are required to invoke this module:
+  * "text"
+  * @public
+  * @typedef {Array} chat/requiredData
+  */
+export const requiredData = ['text'];
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} chat/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'chat',
+  category: 'core',
+  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`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_emote.js.html b/documentation/core_emote.js.html new file mode 100644 index 0000000..e81a524 --- /dev/null +++ b/documentation/core_emote.js.html @@ -0,0 +1,213 @@ + + + + + JSDoc: Source: core/emote.js + + + + + + + + + + +
+ +

Source: core/emote.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Emote / action text
+  * @version 1.0.0
+  * @description Broadcasts an emote to the current channel
+  * @module emote
+  */
+
+/**
+  * Check and trim string provided by remote client
+  * @param {string} text - Subject string
+  * @private
+  * @todo Move into utility module
+  * @return {string|boolean}
+  */
+const parseText = (text) => {
+  // verifies user input is text
+  if (typeof text !== 'string') {
+    return false;
+  }
+
+  let sanitizedText = text;
+
+  // strip newlines from beginning and end
+  sanitizedText = sanitizedText.replace(/^\s*\n|^\s+$|\n\s*$/g, '');
+  // replace 3+ newlines with just 2 newlines
+  sanitizedText = sanitizedText.replace(/\n{3,}/g, '\n\n');
+
+  return sanitizedText;
+};
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({ server, socket, payload }) {
+  // check user input
+  let text = parseText(payload.text);
+
+  if (!text) {
+    // lets not send objects or empty text, yea?
+    return server.police.frisk(socket.address, 8);
+  }
+
+  // check for spam
+  const score = text.length / 83 / 4;
+  if (server.police.frisk(socket.address, score)) {
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.',
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  if (!text.startsWith("'")) {
+    text = ` ${text}`;
+  }
+
+  const newPayload = {
+    cmd: 'emote',
+    nick: socket.nick,
+    userid: socket.userid,
+    text: `@${socket.nick}${text}`,
+    channel: socket.channel, // @todo Multichannel
+  };
+
+  if (socket.trip) {
+    newPayload.trip = socket.trip;
+  }
+
+  // broadcast to channel peers
+  server.broadcast(newPayload, { channel: socket.channel });
+
+  return true;
+}
+
+/**
+  * Automatically executes once after server is ready to register this modules hooks
+  * @param {Object} server - Reference to server enviroment object
+  * @public
+  * @return {void}
+  */
+export function initHooks(server) {
+  server.registerHook('in', 'chat', this.emoteCheck.bind(this), 30);
+}
+
+/**
+  * Executes every time an incoming chat command is invoked;
+  * hooks chat commands checking for /me
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function emoteCheck({
+  core, server, socket, payload,
+}) {
+  if (typeof payload.text !== 'string') {
+    return false;
+  }
+
+  if (payload.text.startsWith('/me ')) {
+    const input = payload.text.split(' ');
+
+    // If there is no emote target parameter
+    if (input[1] === undefined) {
+      server.reply({
+        cmd: 'warn', // @todo Add numeric error code as `id`
+        text: 'Refer to `/help emote` for instructions on how to use this command.',
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+
+      return false;
+    }
+
+    input.splice(0, 1);
+    const actionText = input.join(' ');
+
+    this.run({
+      core,
+      server,
+      socket,
+      payload: {
+        cmd: 'emote',
+        text: actionText,
+      },
+    });
+
+    return false;
+  }
+
+  return payload;
+}
+
+/**
+  * The following payload properties are required to invoke this module:
+  * "text"
+  * @public
+  * @typedef {Array} emote/requiredData
+  */
+export const requiredData = ['text'];
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} emote/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'emote',
+  category: 'core',
+  description: 'Broadcasts an emote to the current channel',
+  usage: `
+    API: { cmd: 'emote', text: '<emote/action text>' }
+    Text: /me <emote/action text>`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_help.js.html b/documentation/core_help.js.html new file mode 100644 index 0000000..7a3eaae --- /dev/null +++ b/documentation/core_help.js.html @@ -0,0 +1,185 @@ + + + + + JSDoc: Source: core/help.js + + + + + + + + + + +
+ +

Source: core/help.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Get help
+  * @version 1.0.0
+  * @description Outputs information about the servers current protocol
+  * @module help
+  */
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // check for spam
+  if (server.police.frisk(socket.address, 2)) {
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.',
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // verify user input
+  if (typeof payload.command !== 'undefined' && typeof payload.command !== 'string') {
+    return true;
+  }
+
+  let reply = '';
+  if (typeof payload.command === 'undefined') {
+    reply += '# All commands:\n|Category:|Name:|\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())}:|`;
+      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`;
+    }
+
+    reply += '---\nFor specific help on certain commands, use either:\nText: `/help <command name>`\nAPI: `{cmd: \'help\', command: \'<command name>\'}`';
+  } else {
+    const command = core.commands.get(payload.command);
+
+    if (typeof command === 'undefined') {
+      reply += 'Unknown command';
+    } else {
+      reply += `# ${command.info.name} command:\n| | |\n|---:|---|\n`;
+      reply += `|**Name:**|${command.info.name}|\n`;
+      reply += `|**Aliases:**|${typeof command.info.aliases !== 'undefined' ? command.info.aliases.join(', ') : 'None'}|\n`;
+      reply += `|**Category:**|${command.info.category.replace('../src/commands/', '').replace(/^\w/, (c) => c.toUpperCase())}|\n`;
+      reply += `|**Required Parameters:**|${command.requiredData || 'None'}|\n`;
+      // eslint-disable-next-line no-useless-escape
+      reply += `|**Description:**|${command.info.description || '¯\_(ツ)_/¯'}|\n\n`;
+      reply += `**Usage:** ${command.info.usage || command.info.name}`;
+    }
+  }
+
+  // output reply
+  server.reply({
+    cmd: 'info',
+    text: reply,
+    channel: socket.channel, // @todo Multichannel
+  }, socket);
+
+  return true;
+}
+
+/**
+  * Automatically executes once after server is ready to register this modules hooks
+  * @param {Object} server - Reference to server enviroment object
+  * @public
+  * @return {void}
+  */
+export function initHooks(server) {
+  server.registerHook('in', 'chat', this.helpCheck.bind(this), 28);
+}
+
+/**
+  * Executes every time an incoming chat command is invoked;
+  * hooks chat commands checking for /help
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function helpCheck({
+  core, server, socket, payload,
+}) {
+  if (typeof payload.text !== 'string') {
+    return false;
+  }
+
+  if (payload.text.startsWith('/help')) {
+    const input = payload.text.substr(1).split(' ', 2);
+
+    this.run({
+      core,
+      server,
+      socket,
+      payload: {
+        cmd: input[0],
+        command: input[1],
+      },
+    });
+
+    return false;
+  }
+
+  return payload;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} help/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'help',
+  category: 'core',
+  description: 'Outputs information about the servers current protocol',
+  usage: `
+    API: { cmd: 'help', command: '<optional command name>' }
+    Text: /help <optional command name>`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_invite.js.html b/documentation/core_invite.js.html new file mode 100644 index 0000000..7920f80 --- /dev/null +++ b/documentation/core_invite.js.html @@ -0,0 +1,174 @@ + + + + + JSDoc: Source: core/invite.js + + + + + + + + + + +
+ +

Source: core/invite.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Send an invite
+  * @version 1.0.0
+  * @description Sends an invite to the target client with the provided channel, or a random channel
+  * @module invite
+  */
+
+import {
+  findUser,
+} from '../utility/_Channels.js';
+import {
+  Errors,
+} from '../utility/_Constants.js';
+import {
+  legacyInviteOut,
+  legacyInviteReply,
+} from '../utility/_LegacyFunctions.js';
+
+/**
+  * Returns the channel that should be invited to.
+  * @param {any} channel
+  * @private
+  * @return {string}
+  */
+export function getChannel(channel = undefined) {
+  if (typeof channel === 'string') {
+    return channel;
+  }
+  return Math.random().toString(36).substr(2, 8);
+}
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // check for spam
+  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.',
+      id: Errors.Invite.RATELIMIT,
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // verify user input
+  // if this is a legacy client add missing params to payload
+  if (socket.hcProtocol === 1) {
+    if (typeof socket.channel === 'undefined' || typeof payload.nick !== 'string') {
+      return true;
+    }
+
+    payload.channel = socket.channel; // eslint-disable-line no-param-reassign
+  } else if (typeof payload.userid !== 'number' || typeof payload.channel !== 'string') {
+    return true;
+  }
+
+  // @todo Verify this socket is part of payload.channel - multichannel patch
+  // find target user
+  const targetUser = findUser(server, payload);
+  if (!targetUser) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'Could not find user in that channel',
+      id: Errors.Global.UNKNOWN_USER,
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // generate common channel
+  const channel = getChannel(payload.to);
+
+  // build invite
+  const outgoingPayload = {
+    cmd: 'invite',
+    channel: socket.channel, // @todo Multichannel
+    from: socket.userid,
+    to: targetUser.userid,
+    inviteChannel: channel,
+  };
+
+  // send invite notice to target client
+  if (targetUser.hcProtocol === 1) {
+    server.reply(legacyInviteOut(outgoingPayload, socket.nick), targetUser);
+  } else {
+    server.reply(outgoingPayload, targetUser);
+  }
+
+  // send invite notice to this client
+  if (socket.hcProtocol === 1) {
+    server.reply(legacyInviteReply(outgoingPayload, targetUser.nick), socket);
+  } else {
+    server.reply(outgoingPayload, socket);
+  }
+
+  // stats are fun
+  core.stats.increment('invites-sent');
+
+  return true;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} invite/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'invite',
+  category: 'core',
+  description: 'Sends an invite to the target client with the provided channel, or a random channel.',
+  usage: `
+    API: { cmd: 'invite', nick: '<target nickname>', to: '<optional destination channel>' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_join.js.html b/documentation/core_join.js.html new file mode 100644 index 0000000..bba3e25 --- /dev/null +++ b/documentation/core_join.js.html @@ -0,0 +1,323 @@ + + + + + JSDoc: Source: core/join.js + + + + + + + + + + +
+ +

Source: core/join.js

+ + + + + + +
+
+
/* eslint no-param-reassign: 0 */
+/* eslint import/no-cycle: [0, { ignoreExternal: true }] */
+
+/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Join target channel
+  * @version 1.0.0
+  * @description Join the target channel using the supplied nick and password
+  * @module join
+  */
+
+import {
+  getSession,
+} from './session.js';
+import {
+  canJoinChannel,
+  socketInChannel,
+} from '../utility/_Channels.js';
+import {
+  Errors,
+} from '../utility/_Constants.js';
+import {
+  upgradeLegacyJoin,
+  legacyLevelToLabel,
+} from '../utility/_LegacyFunctions.js';
+import {
+  verifyNickname,
+  getUserPerms,
+  getUserDetails,
+} from '../utility/_UAC.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // check for spam
+  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.',
+      id: Errors.Join.RATELIMIT,
+      channel: false, // @todo Multichannel, false for global event
+    }, socket);
+  }
+
+  // `join` is the legacy entry point, check if it needs to be upgraded
+  if (typeof socket.hcProtocol === 'undefined') {
+    payload = upgradeLegacyJoin(server, socket, payload);
+  }
+
+  // store payload values
+  const { channel, nick, pass } = payload;
+
+  // check if a client is able to join target channel
+  const mayJoin = canJoinChannel(channel, socket);
+  if (mayJoin !== true) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'You may not join that channel.',
+      id: mayJoin,
+      channel: false, // @todo Multichannel, false for global event
+    }, socket);
+  }
+
+  // calling socket already in a channel
+  // @todo multichannel update, will remove
+  if (typeof socket.channel !== 'undefined') {
+    return server.reply({
+      cmd: 'warn', // @todo Remove this
+      text: 'Joining more than one channel is not currently supported',
+      id: Errors.Join.ALREADY_JOINED,
+      channel: false, // @todo Multichannel, false for global event
+    }, socket);
+  }
+  // end todo
+
+  // validates the user input for `nick`
+  if (verifyNickname(nick, socket) !== true) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'Nickname must consist of up to 24 letters, numbers, and underscores',
+      id: Errors.Join.INVALID_NICK,
+      channel: false, // @todo Multichannel, false for global event
+    }, socket);
+  }
+
+  // get trip and level
+  const { trip, level } = getUserPerms(pass, core.saltKey, core.appConfig.data, channel);
+
+  // store the user values
+  const userInfo = {
+    nick,
+    trip,
+    uType: legacyLevelToLabel(level),
+    hash: socket.hash,
+    level,
+    userid: socket.userid,
+    isBot: socket.isBot,
+    color: socket.color,
+    channel,
+  };
+
+  // check if the nickname already exists in the channel
+  const userExists = server.findSockets({
+    channel,
+    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',
+      id: Errors.Join.NAME_TAKEN,
+      channel: false, // @todo Multichannel, false for global event
+    }, socket);
+  }
+
+  // prepare to notify channel peers
+  const newPeerList = server.findSockets({ channel });
+  const nicks = []; /* @legacy */
+  const users = [];
+  const joinAnnouncement = { ...{ cmd: 'onlineAdd' }, ...userInfo };
+
+  // send join announcement and prep online set reply
+  for (let i = 0, l = newPeerList.length; i < l; i += 1) {
+    server.reply(joinAnnouncement, newPeerList[i]);
+
+    nicks.push(newPeerList[i].nick); /* @legacy */
+    users.push({
+      ...{
+        channel,
+        isme: false,
+      },
+      ...getUserDetails(newPeerList[i]),
+    });
+  }
+
+  // store user info
+  socket.nick = userInfo.nick;
+  socket.trip = userInfo.trip;
+  socket.level = userInfo.level;
+  socket.uType = userInfo.uType; /* @legacy */
+  socket.channel = channel; /* @legacy */
+  // @todo multi-channel patch
+  // socket.channels.push(channel);
+  socket.channels = [channel];
+
+  nicks.push(userInfo.nick); /* @legacy */
+  users.push({ ...{ isme: true, isBot: socket.isBot }, ...userInfo });
+
+  // reply with channel peer list
+  server.reply({
+    cmd: 'onlineSet',
+    nicks, /* @legacy */
+    users,
+    channel, // @todo Multichannel (?)
+  }, socket);
+
+  // update client with new session info
+  server.reply({
+    cmd: 'session',
+    restored: false,
+    token: getSession(socket, core),
+    channels: socket.channels,
+  }, socket);
+
+  // stats are fun
+  core.stats.increment('users-joined');
+
+  return true;
+}
+
+export function restoreJoin({
+  server, socket, channel,
+}) {
+  // check if a client is able to join target channel
+  const mayJoin = canJoinChannel(channel, socket);
+  if (mayJoin !== true) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'You may not join that channel.',
+      id: mayJoin,
+      channel: false, // @todo Multichannel, false for global event
+    }, socket);
+  }
+
+  // store the user values
+  const userInfo = {
+    nick: socket.nick,
+    trip: socket.trip,
+    uType: legacyLevelToLabel(socket.level),
+    hash: socket.hash,
+    level: socket.level,
+    userid: socket.userid,
+    isBot: socket.isBot,
+    color: socket.color,
+    channel,
+  };
+
+  // prepare to notify channel peers
+  const newPeerList = server.findSockets({ channel });
+  const nicks = []; /* @legacy */
+  const users = [];
+  const joinAnnouncement = { ...{ cmd: 'onlineAdd' }, ...userInfo };
+  // build update notice with new privileges
+  const updateAnnouncement = {
+    ...getUserDetails(socket),
+    ...{
+      cmd: 'updateUser',
+      online: true,
+    },
+  };
+
+  const isDuplicate = socketInChannel(server, channel, socket);
+
+  // send join announcement and prep online set reply
+  for (let i = 0, l = newPeerList.length; i < l; i += 1) {
+    if (isDuplicate) {
+      server.reply(updateAnnouncement, newPeerList[i]);
+    } else {
+      server.reply(joinAnnouncement, newPeerList[i]);
+    }
+
+    nicks.push(newPeerList[i].nick); /* @legacy */
+    users.push({
+      ...{
+        channel,
+        isme: false,
+      },
+      ...getUserDetails(newPeerList[i]),
+    });
+  }
+
+  nicks.push(userInfo.nick); /* @legacy */
+  users.push({ ...{ isme: true, isBot: socket.isBot }, ...userInfo });
+
+  // reply with channel peer list
+  server.reply({
+    cmd: 'onlineSet',
+    nicks, /* @legacy */
+    users,
+    channel, // @todo Multichannel (?)
+  }, socket);
+
+  socket.channel = channel; /* @legacy */
+  socket.channels.push(channel);
+
+  return true;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} join/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'join',
+  category: 'core',
+  description: 'Join the target channel using the supplied nick and password',
+  usage: `
+    API: { cmd: 'join', nick: '<your nickname>', pass: '<optional password>', channel: '<target channel>' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_morestats.js.html b/documentation/core_morestats.js.html new file mode 100644 index 0000000..07b3fad --- /dev/null +++ b/documentation/core_morestats.js.html @@ -0,0 +1,215 @@ + + + + + JSDoc: Source: core/morestats.js + + + + + + + + + + +
+ +

Source: core/morestats.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Get stats
+  * @version 1.0.0
+  * @description Sends back current server stats to the calling client
+  * @module morestats
+  */
+
+/**
+  * Format input time into string
+  * @param {Date} time - Subject date
+  * @private
+  * @return {string}
+  */
+const formatTime = (time) => {
+  let seconds = time[0] + time[1] / 1e9;
+
+  let minutes = Math.floor(seconds / 60);
+  seconds %= 60;
+
+  let hours = Math.floor(minutes / 60);
+  minutes %= 60;
+
+  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`;
+};
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({ core, server, socket }) {
+  // gather connection and channel count
+  const ips = {};
+  const channels = {};
+  // @todo use public channel flag
+  const publicChanCounts = {
+    lounge: 0,
+    meta: 0,
+    math: 0,
+    physics: 0,
+    chemistry: 0,
+    technology: 0,
+    programming: 0,
+    games: 0,
+    banana: 0,
+    chinese: 0,
+  };
+
+  // @todo code resuage between here and `session`; should share exported function
+  server.clients.forEach((client) => {
+    if (client.channel) {
+      channels[client.channel] = true;
+      ips[client.address] = true;
+      if (typeof publicChanCounts[client.channel] !== 'undefined') {
+        publicChanCounts[client.channel] += 1;
+      }
+    }
+  });
+
+  const uniqueClientCount = Object.keys(ips).length;
+  const uniqueChannels = Object.keys(channels).length;
+  const joins = core.stats.get('users-joined') || 0;
+  const invites = core.stats.get('invites-sent') || 0;
+  const messages = core.stats.get('messages-sent') || 0;
+  const banned = core.stats.get('users-banned') || 0;
+  const kicked = core.stats.get('users-kicked') || 0;
+  const stats = core.stats.get('stats-requested') || 0;
+  const uptime = formatTime(process.hrtime(core.stats.get('start-time')));
+
+  // dispatch info
+  server.reply({
+    cmd: 'info',
+    users: uniqueClientCount,
+    chans: uniqueChannels,
+    joins,
+    invites,
+    messages,
+    banned,
+    kicked,
+    stats,
+    uptime,
+    public: publicChanCounts,
+    text: `current-connections: ${uniqueClientCount}
+current-channels: ${uniqueChannels}
+users-joined: ${joins}
+invites-sent: ${invites}
+messages-sent: ${messages}
+users-banned: ${banned}
+users-kicked: ${kicked}
+stats-requested: ${stats}
+server-uptime: ${uptime}`,
+    channel: socket.channel, // @todo Multichannel
+  }, socket);
+
+  // stats are fun
+  core.stats.increment('stats-requested');
+
+  return true;
+}
+
+/**
+  * Automatically executes once after server is ready to register this modules hooks
+  * @param {Object} server - Reference to server enviroment object
+  * @public
+  * @return {void}
+  */
+export function initHooks(server) {
+  server.registerHook('in', 'chat', this.statsCheck.bind(this), 26);
+}
+
+/**
+  * Executes every time an incoming chat command is invoked;
+  * hooks chat commands checking for /stats
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function statsCheck({
+  core, server, socket, payload,
+}) {
+  if (typeof payload.text !== 'string') {
+    return false;
+  }
+
+  if (payload.text.startsWith('/stats')) {
+    this.run({
+      core,
+      server,
+      socket,
+      payload: {
+        cmd: 'morestats',
+      },
+    });
+
+    return false;
+  }
+
+  return payload;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} morestats/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'morestats',
+  category: 'core',
+  description: 'Sends back current server stats to the calling client',
+  usage: `
+    API: { cmd: 'morestats' }
+    Text: /stats`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_ping.js.html b/documentation/core_ping.js.html new file mode 100644 index 0000000..9285bc0 --- /dev/null +++ b/documentation/core_ping.js.html @@ -0,0 +1,83 @@ + + + + + JSDoc: Source: core/ping.js + + + + + + + + + + +
+ +

Source: core/ping.js

+ + + + + + +
+
+
/* eslint no-empty-function: 0 */
+
+/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Legacy support module
+  * @version 1.0.0
+  * @description This module is only in place to supress error notices legacy clients may get
+  * @module ping
+  */
+
+/**
+  * Executes when invoked by a remote client
+  * @public
+  * @return {void}
+  */
+export async function run() { }
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} ping/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'ping',
+  category: 'core',
+  description: 'This module is only in place to supress error notices legacy clients may get',
+  usage: 'none',
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_session.js.html b/documentation/core_session.js.html new file mode 100644 index 0000000..4d37721 --- /dev/null +++ b/documentation/core_session.js.html @@ -0,0 +1,244 @@ + + + + + JSDoc: Source: core/session.js + + + + + + + + + + +
+ +

Source: core/session.js

+ + + + + + +
+
+
/* eslint import/no-cycle: [0, { ignoreExternal: true }] */
+
+/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Create or restore session
+  * @version 1.0.0
+  * @description Restore previous state by session or create new session
+  * @module session
+  */
+
+import fs from 'fs';
+import jsonwebtoken from 'jsonwebtoken';
+
+import {
+  verifyNickname,
+} from '../utility/_UAC.js';
+import {
+  Errors,
+} from '../utility/_Constants.js';
+import {
+  restoreJoin,
+} from './join.js';
+
+const SessionLocation = './session.key';
+
+/**
+  *
+  * @param {*} socket
+  * @param {*} core
+  * @returns {object}
+  */
+export function getSession(socket, core) {
+  return jsonwebtoken.sign({
+    channel: socket.channel,
+    channels: socket.channels,
+    color: socket.color,
+    isBot: socket.isBot,
+    level: socket.level,
+    nick: socket.nick,
+    trip: socket.trip,
+    userid: socket.userid,
+    uType: socket.uType, /* @legacy */
+    muzzled: socket.muzzled || false,
+    banned: socket.banned || false,
+  }, core.sessionKey, {
+    expiresIn: '7 days',
+  });
+}
+
+/**
+  *
+  * @param {*} server
+  * @param {*} socket
+  * @returns {boolean}
+  */
+function notifyFailure(server, socket) {
+  server.reply({
+    cmd: 'error',
+    id: Errors.Session.BAD_SESSION,
+    text: 'Invalid session',
+  }, socket);
+
+  return false;
+}
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  if (typeof payload.token === 'undefined') {
+    return notifyFailure(server, socket);
+  }
+
+  let session = false;
+  try {
+    session = jsonwebtoken.verify(payload.token, core.sessionKey);
+  } catch (err) {
+    return notifyFailure(server, socket);
+  }
+
+  // validate session
+  if (typeof session.channel !== 'string') {
+    return notifyFailure(server, socket);
+  }
+
+  if (Array.isArray(session.channels) === false) {
+    return notifyFailure(server, socket);
+  }
+
+  if (typeof session.color !== 'string' && typeof session.color !== 'boolean') {
+    return notifyFailure(server, socket);
+  }
+
+  if (typeof session.isBot !== 'boolean') {
+    return notifyFailure(server, socket);
+  }
+
+  if (typeof session.level !== 'number') {
+    return notifyFailure(server, socket);
+  }
+
+  if (verifyNickname(session.nick) === false) {
+    return notifyFailure(server, socket);
+  }
+
+  if (typeof session.trip !== 'string') {
+    return notifyFailure(server, socket);
+  }
+
+  if (typeof session.userid !== 'number') {
+    return notifyFailure(server, socket);
+  }
+
+  if (typeof session.uType !== 'string') {
+    return notifyFailure(server, socket);
+  }
+
+  if (typeof session.muzzled !== 'boolean') {
+    return notifyFailure(server, socket);
+  }
+
+  if (typeof session.banned !== 'boolean') {
+    return notifyFailure(server, socket);
+  }
+
+  // populate socket info with validated session
+  socket.channels = [];
+  socket.color = session.color;
+  socket.isBot = session.isBot;
+  socket.level = session.level;
+  socket.nick = session.nick;
+  socket.trip = session.trip;
+  socket.userid = session.userid;
+  socket.uType = session.uType; /* @legacy */
+  socket.muzzled = session.muzzled;
+  socket.banned = session.banned;
+
+  socket.hash = server.getSocketHash(socket);
+  socket.hcProtocol = 2;
+
+  // dispatch info
+  server.reply({
+    cmd: 'session',
+    restored: true,
+    token: getSession(socket, core),
+    channels: socket.channels,
+  }, socket);
+
+  for (let i = 0, j = session.channels.length; i < j; i += 1) {
+    restoreJoin({
+      core,
+      server,
+      socket,
+      channel: session.channels[i],
+    }, true);
+  }
+
+  return true;
+}
+
+/**
+  * Automatically executes once after server is ready
+  * @param {Object} core - Reference to core enviroment object
+  * @public
+  * @return {void}
+  */
+export function init(core) {
+  // load the encryption key if required
+  if (typeof core.sessionKey === 'undefined') {
+    core.sessionKey = fs.readFileSync(SessionLocation);
+  }
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} session/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'session',
+  category: 'core',
+  description: 'Restore previous state by session or create new session',
+  usage: "API: { cmd: 'session', id: '<previous session>' }",
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_stats.js.html b/documentation/core_stats.js.html new file mode 100644 index 0000000..1b25125 --- /dev/null +++ b/documentation/core_stats.js.html @@ -0,0 +1,110 @@ + + + + + JSDoc: Source: core/stats.js + + + + + + + + + + +
+ +

Source: core/stats.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Simple stats
+  * @version 1.0.0
+  * @description Sends back legacy server stats to the calling client
+  * @module stats
+  */
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({ core, server, socket }) {
+  // gather connection and channel count
+  let ips = {};
+  let channels = {};
+  // for (const client of server.clients) {
+  server.clients.forEach((client) => {
+    if (client.channel) {
+      channels[client.channel] = true;
+      ips[client.address] = true;
+    }
+  });
+
+  const uniqueClientCount = Object.keys(ips).length;
+  const uniqueChannels = Object.keys(channels).length;
+
+  ips = null;
+  channels = null;
+
+  // dispatch info
+  server.reply({
+    cmd: 'info',
+    text: `${uniqueClientCount} unique IPs in ${uniqueChannels} channels`,
+    channel: socket.channel, // @todo Multichannel
+  }, socket);
+
+  // stats are fun
+  core.stats.increment('stats-requested');
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} stats/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'stats',
+  category: 'core',
+  description: 'Sends back legacy server stats to the calling client',
+  usage: `
+    API: { cmd: 'stats' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/core_whisper.js.html b/documentation/core_whisper.js.html new file mode 100644 index 0000000..f82308d --- /dev/null +++ b/documentation/core_whisper.js.html @@ -0,0 +1,282 @@ + + + + + JSDoc: Source: core/whisper.js + + + + + + + + + + +
+ +

Source: core/whisper.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Send whisper
+  * @version 1.0.0
+  * @description Display text on target users screen that only they can see
+  * @module whisper
+  * @todo This should be changed to it's own event type, instead of `info`
+        and accept a `userid` rather than `nick`
+  */
+
+import {
+  findUser,
+} from '../utility/_Channels.js';
+import {
+  Errors,
+} from '../utility/_Constants.js';
+import {
+  legacyWhisperOut,
+  legacyWhisperReply,
+} from '../utility/_LegacyFunctions.js';
+
+/**
+  * Check and trim string provided by remote client
+  * @param {string} text - Subject string
+  * @private
+  * @todo Move into utility module
+  * @return {string|boolean}
+  */
+const parseText = (text) => {
+  // verifies user input is text
+  if (typeof text !== 'string') {
+    return false;
+  }
+
+  let sanitizedText = text;
+
+  // strip newlines from beginning and end
+  sanitizedText = sanitizedText.replace(/^\s*\n|^\s+$|\n\s*$/g, '');
+  // replace 3+ newlines with just 2 newlines
+  sanitizedText = sanitizedText.replace(/\n{3,}/g, '\n\n');
+
+  return sanitizedText;
+};
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({ server, socket, payload }) {
+  // if this is a legacy client add missing params to payload
+  if (socket.hcProtocol === 1) {
+    payload.channel = socket.channel; // eslint-disable-line no-param-reassign
+  }
+
+  // verify user input
+  const text = parseText(payload.text);
+
+  if (!text) {
+    // lets not send objects or empty text, yea?
+    return server.police.frisk(socket.address, 13);
+  }
+
+  // check for spam
+  const score = text.length / 83 / 4;
+  if (server.police.frisk(socket.address, score)) {
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.',
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  const targetUser = findUser(server, payload);
+  if (!targetUser) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'Could not find user in that channel',
+      id: Errors.Global.UNKNOWN_USER,
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  const outgoingPayload = {
+    cmd: 'whisper',
+    channel: socket.channel, // @todo Multichannel
+    from: socket.userid,
+    to: targetUser.userid,
+    text,
+  };
+
+  // send invite notice to target client
+  if (targetUser.hcProtocol === 1) {
+    server.reply(legacyWhisperOut(outgoingPayload, socket), targetUser);
+  } else {
+    server.reply(outgoingPayload, targetUser);
+  }
+
+  // send invite notice to this client
+  if (socket.hcProtocol === 1) {
+    server.reply(legacyWhisperReply(outgoingPayload, targetUser.nick), socket);
+  } else {
+    server.reply(outgoingPayload, socket);
+  }
+
+  targetUser.whisperReply = socket.nick;
+
+  return true;
+}
+
+/**
+  * Automatically executes once after server is ready to register this modules hooks
+  * @param {Object} server - Reference to server enviroment object
+  * @public
+  * @return {void}
+  */
+export function initHooks(server) {
+  server.registerHook('in', 'chat', this.whisperCheck.bind(this), 20);
+}
+
+/**
+  * Executes every time an incoming chat command is invoked;
+  * hooks chat commands checking for /whisper
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function whisperCheck({
+  core, server, socket, payload,
+}) {
+  if (typeof payload.text !== 'string') {
+    return false;
+  }
+
+  if (payload.text.startsWith('/whisper ') || payload.text.startsWith('/w ')) {
+    const input = payload.text.split(' ');
+
+    // If there is no nickname target parameter
+    if (!input[1]) {
+      server.reply({
+        cmd: 'warn', // @todo Add numeric error code as `id`
+        text: 'Refer to `/help whisper` for instructions on how to use this command.',
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+
+      return false;
+    }
+
+    const target = input[1].replace(/@/g, '');
+    input.splice(0, 2);
+    const whisperText = input.join(' ');
+
+    this.run({
+      core,
+      server,
+      socket,
+      payload: {
+        cmd: 'whisper',
+        channel: socket.channel, // @todo Multichannel
+        nick: target,
+        text: whisperText,
+      },
+    });
+
+    return false;
+  }
+
+  if (payload.text.startsWith('/reply ') || payload.text.startsWith('/r ')) {
+    if (typeof socket.whisperReply === 'undefined') {
+      server.reply({
+        cmd: 'warn', // @todo Add numeric error code as `id`
+        text: 'Cannot reply to nobody',
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+
+      return false;
+    }
+
+    const input = payload.text.split(' ');
+    input.splice(0, 1);
+    const whisperText = input.join(' ');
+
+    this.run({
+      core,
+      server,
+      socket,
+      payload: {
+        cmd: 'whisper',
+        nick: socket.whisperReply,
+        channel: socket.channel, // @todo Multichannel
+        text: whisperText,
+      },
+    });
+
+    return false;
+  }
+
+  return payload;
+}
+
+/**
+  * The following payload properties are required to invoke this module:
+  * "nick", "text"
+  * @public
+  * @typedef {Array} whisper/requiredData
+  */
+export const requiredData = ['nick', 'text'];
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} whisper/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'whisper',
+  category: 'core',
+  description: 'Display text on target users screen that only they can see',
+  usage: `
+    API: { cmd: 'whisper', nick: '<target name>', text: '<text to whisper>' }
+    Text: /whisper <target name> <text to whisper>
+    Text: /w <target name> <text to whisper>
+    Alt Text: /reply <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>`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/fonts/OpenSans-Bold-webfont.eot b/documentation/fonts/OpenSans-Bold-webfont.eot new file mode 100644 index 0000000..5d20d91 Binary files /dev/null and b/documentation/fonts/OpenSans-Bold-webfont.eot differ diff --git a/documentation/fonts/OpenSans-Bold-webfont.svg b/documentation/fonts/OpenSans-Bold-webfont.svg new file mode 100644 index 0000000..3ed7be4 --- /dev/null +++ b/documentation/fonts/OpenSans-Bold-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/fonts/OpenSans-Bold-webfont.woff b/documentation/fonts/OpenSans-Bold-webfont.woff new file mode 100644 index 0000000..1205787 Binary files /dev/null and b/documentation/fonts/OpenSans-Bold-webfont.woff differ diff --git a/documentation/fonts/OpenSans-BoldItalic-webfont.eot b/documentation/fonts/OpenSans-BoldItalic-webfont.eot new file mode 100644 index 0000000..1f639a1 Binary files /dev/null and b/documentation/fonts/OpenSans-BoldItalic-webfont.eot differ diff --git a/documentation/fonts/OpenSans-BoldItalic-webfont.svg b/documentation/fonts/OpenSans-BoldItalic-webfont.svg new file mode 100644 index 0000000..6a2607b --- /dev/null +++ b/documentation/fonts/OpenSans-BoldItalic-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/fonts/OpenSans-BoldItalic-webfont.woff b/documentation/fonts/OpenSans-BoldItalic-webfont.woff new file mode 100644 index 0000000..ed760c0 Binary files /dev/null and b/documentation/fonts/OpenSans-BoldItalic-webfont.woff differ diff --git a/documentation/fonts/OpenSans-Italic-webfont.eot b/documentation/fonts/OpenSans-Italic-webfont.eot new file mode 100644 index 0000000..0c8a0ae Binary files /dev/null and b/documentation/fonts/OpenSans-Italic-webfont.eot differ diff --git a/documentation/fonts/OpenSans-Italic-webfont.svg b/documentation/fonts/OpenSans-Italic-webfont.svg new file mode 100644 index 0000000..e1075dc --- /dev/null +++ b/documentation/fonts/OpenSans-Italic-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/fonts/OpenSans-Italic-webfont.woff b/documentation/fonts/OpenSans-Italic-webfont.woff new file mode 100644 index 0000000..ff652e6 Binary files /dev/null and b/documentation/fonts/OpenSans-Italic-webfont.woff differ diff --git a/documentation/fonts/OpenSans-Light-webfont.eot b/documentation/fonts/OpenSans-Light-webfont.eot new file mode 100644 index 0000000..1486840 Binary files /dev/null and b/documentation/fonts/OpenSans-Light-webfont.eot differ diff --git a/documentation/fonts/OpenSans-Light-webfont.svg b/documentation/fonts/OpenSans-Light-webfont.svg new file mode 100644 index 0000000..11a472c --- /dev/null +++ b/documentation/fonts/OpenSans-Light-webfont.svg @@ -0,0 +1,1831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/fonts/OpenSans-Light-webfont.woff b/documentation/fonts/OpenSans-Light-webfont.woff new file mode 100644 index 0000000..e786074 Binary files /dev/null and b/documentation/fonts/OpenSans-Light-webfont.woff differ diff --git a/documentation/fonts/OpenSans-LightItalic-webfont.eot b/documentation/fonts/OpenSans-LightItalic-webfont.eot new file mode 100644 index 0000000..8f44592 Binary files /dev/null and b/documentation/fonts/OpenSans-LightItalic-webfont.eot differ diff --git a/documentation/fonts/OpenSans-LightItalic-webfont.svg b/documentation/fonts/OpenSans-LightItalic-webfont.svg new file mode 100644 index 0000000..431d7e3 --- /dev/null +++ b/documentation/fonts/OpenSans-LightItalic-webfont.svg @@ -0,0 +1,1835 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/fonts/OpenSans-LightItalic-webfont.woff b/documentation/fonts/OpenSans-LightItalic-webfont.woff new file mode 100644 index 0000000..43e8b9e Binary files /dev/null and b/documentation/fonts/OpenSans-LightItalic-webfont.woff differ diff --git a/documentation/fonts/OpenSans-Regular-webfont.eot b/documentation/fonts/OpenSans-Regular-webfont.eot new file mode 100644 index 0000000..6bbc3cf Binary files /dev/null and b/documentation/fonts/OpenSans-Regular-webfont.eot differ diff --git a/documentation/fonts/OpenSans-Regular-webfont.svg b/documentation/fonts/OpenSans-Regular-webfont.svg new file mode 100644 index 0000000..25a3952 --- /dev/null +++ b/documentation/fonts/OpenSans-Regular-webfont.svg @@ -0,0 +1,1831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/fonts/OpenSans-Regular-webfont.woff b/documentation/fonts/OpenSans-Regular-webfont.woff new file mode 100644 index 0000000..e231183 Binary files /dev/null and b/documentation/fonts/OpenSans-Regular-webfont.woff differ diff --git a/documentation/index.html b/documentation/index.html new file mode 100644 index 0000000..2c1c319 --- /dev/null +++ b/documentation/index.html @@ -0,0 +1,105 @@ + + + + + JSDoc: Home + + + + + + + + + + +
+ +

Home

+ + + + + + + + +

+ + + + + + + + + + + + + + + +
+

hack.chat

+

hack.chat is a minimal, distraction-free, accountless, logless, disappearing chat service which is easily deployable as your own service. The current client comes bundled with LaTeX rendering provided by KaTeX and code syntax highlighting provided by highlight.js.

+

A list of software developed for the hack.chat framework can be found at the 3rd party software list repository. This includes bots, clients, docker containers, etc.

+

This is a backwards compatible continuation of the work by Andrew Belt. The server code has been updated to ES6 along with several new features including new commands and hot-reload of the commands/protocol. There is also documentation.

+

Installation

+

Prerequisites

+ +

Developer Installation

+
    +
  1. Clone the repository: git clone https://github.com/hack-chat/main.git
  2. +
  3. Change the directory: cd main
  4. +
  5. Install the dependencies: npm install
  6. +
  7. Launch: npm start
  8. +
+

Live Deployment Installation

+

See DEPLOY.md

+

Contributing

+
    +
  • Use two space indents.
  • +
  • Name files in camelCase.
  • +
+

Credits

+ +

License

+

This project is licensed under the MIT License.

+
+ + + + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/internal_disconnect.js.html b/documentation/internal_disconnect.js.html new file mode 100644 index 0000000..35dd4b8 --- /dev/null +++ b/documentation/internal_disconnect.js.html @@ -0,0 +1,117 @@ + + + + + JSDoc: Source: internal/disconnect.js + + + + + + + + + + +
+ +

Source: internal/disconnect.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Disconnection handler
+  * @version 1.0.0
+  * @description The server invokes this module each time a websocket connection is disconnected
+  * @module disconnect
+  */
+
+import {
+  socketInChannel,
+} from '../utility/_Channels.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({ server, socket, payload }) {
+  if (payload.cmdKey !== server.cmdKey) {
+    // internal command attempt by client, increase rate limit chance and ignore
+    return server.police.frisk(socket.address, 20);
+  }
+
+  // send leave notice to client peers
+  // @todo Multichannel update
+  if (socket.channel) {
+    const isDuplicate = socketInChannel(server, socket.channel, socket);
+
+    if (isDuplicate === false) {
+      server.broadcast({
+        cmd: 'onlineRemove',
+        nick: socket.nick,
+      }, { channel: socket.channel });
+    }
+  }
+
+  // commit close just in case
+  socket.terminate();
+
+  return true;
+}
+
+/**
+  * The following payload properties are required to invoke this module:
+  * "cmdKey"
+  * @public
+  * @typedef {Array} disconnect/requiredData
+  */
+export const requiredData = ['cmdKey'];
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} disconnect/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'disconnect',
+  category: 'internal',
+  description: 'Internally used to relay disconnect events to clients',
+  usage: 'Internal Use Only',
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/internal_socketreply.js.html b/documentation/internal_socketreply.js.html new file mode 100644 index 0000000..f1f6455 --- /dev/null +++ b/documentation/internal_socketreply.js.html @@ -0,0 +1,102 @@ + + + + + JSDoc: Source: internal/socketreply.js + + + + + + + + + + +
+ +

Source: internal/socketreply.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Bridge warning events to a user
+  * @version 1.0.0
+  * @description If a warning occurs within the server, this module will relay the warning to the
+  *   client
+  * @module socketreply
+  */
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({ server, socket, payload }) {
+  if (payload.cmdKey !== server.cmdKey) {
+    // internal command attempt by client, increase rate limit chance and ignore
+    return server.police.frisk(socket.address, 20);
+  }
+
+  // send warning to target socket
+  return server.reply({
+    cmd: 'warn',
+    text: payload.text,
+  }, socket);
+}
+
+/**
+  * The following payload properties are required to invoke this module:
+  * "cmdKey", "text"
+  * @public
+  * @typedef {Array} socketreply/requiredData
+  */
+export const requiredData = ['cmdKey', 'text'];
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} socketreply/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'socketreply',
+  category: 'internal',
+  description: 'Internally used to relay warnings to clients',
+  usage: 'Internal Use Only',
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/mod_ban.js.html b/documentation/mod_ban.js.html new file mode 100644 index 0000000..9471b5e --- /dev/null +++ b/documentation/mod_ban.js.html @@ -0,0 +1,166 @@ + + + + + JSDoc: Source: mod/ban.js + + + + + + + + + + +
+ +

Source: mod/ban.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Ban a user
+  * @version 1.0.0
+  * @description Bans target user by name
+  * @module ban
+  */
+
+import {
+  isModerator,
+  getUserDetails,
+  levels,
+} from '../utility/_UAC.js';
+import {
+  Errors,
+} from '../utility/_Constants.js';
+import {
+  findUser,
+} from '../utility/_Channels.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // increase rate limit chance and ignore if not admin or mod
+  if (!isModerator(socket.level)) {
+    return server.police.frisk(socket.address, 10);
+  }
+
+  // check user input
+  if (socket.hcProtocol === 1) {
+    if (typeof payload.nick !== 'string') {
+      return false;
+    }
+
+    payload.channel = socket.channel; // eslint-disable-line no-param-reassign
+  } else if (typeof payload.userid !== 'number') {
+    return false;
+  }
+
+  // find target user
+  const targetUser = findUser(server, payload);
+  if (!targetUser) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'Could not find user in that channel',
+      id: Errors.Global.UNKNOWN_USER,
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+  const targetNick = targetUser.nick;
+
+  // i guess banning mods or admins isn't the best idea?
+  if (targetUser.level >= socket.level) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'Cannot ban other users of the same level, how rude',
+      id: Errors.Global.PERMISSION,
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // commit arrest record
+  server.police.arrest(targetUser.address, targetUser.hash);
+
+  console.log(`${socket.nick} [${socket.trip}] banned ${targetNick} in ${socket.channel}`);
+
+  // notify normal users
+  server.broadcast({
+    cmd: 'info',
+    text: `Banned ${targetNick}`,
+    user: getUserDetails(targetUser),
+    channel: socket.channel, // @todo Multichannel
+  }, { channel: socket.channel, level: (level) => level < levels.moderator });
+
+  // notify mods
+  server.broadcast({
+    cmd: 'info',
+    text: `${socket.nick}#${socket.trip} banned ${targetNick} in ${payload.channel}, userhash: ${targetUser.hash}`,
+    channel: socket.channel, // @todo Multichannel
+    inChannel: payload.channel,
+    user: getUserDetails(targetUser),
+    banner: getUserDetails(socket),
+  }, { level: isModerator });
+
+  // force connection closed
+  targetUser.terminate();
+
+  // stats are fun
+  core.stats.increment('users-banned');
+
+  return true;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} ban/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'ban',
+  category: 'moderators',
+  description: 'Bans target user by name',
+  usage: `
+    API: { cmd: 'ban', nick: '<target nickname>' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/mod_dumb.js.html b/documentation/mod_dumb.js.html new file mode 100644 index 0000000..f197c42 --- /dev/null +++ b/documentation/mod_dumb.js.html @@ -0,0 +1,424 @@ + + + + + JSDoc: Source: mod/dumb.js + + + + + + + + + + +
+ +

Source: mod/dumb.js

+ + + + + + +
+
+
/* eslint no-param-reassign: 0 */
+/* eslint no-multi-assign: 0 */
+
+/**
+  * @author OpSimple ( https://github.com/OpSimple )
+  * @summary Muzzle a user
+  * @version 1.0.0
+  * @description Globally shadow mute a connection. Optional allies array will see muted messages.
+  * @module dumb
+  */
+
+import {
+  isModerator,
+} from '../utility/_UAC.js';
+import {
+  findUser,
+} from '../utility/_Channels.js';
+import {
+  Errors,
+} from '../utility/_Constants.js';
+import {
+  legacyInviteReply,
+  legacyWhisperReply,
+} from '../utility/_LegacyFunctions.js';
+
+/**
+  * Returns the channel that should be invited to.
+  * @param {any} channel
+  * @private
+  * @return {string}
+  */
+export function getChannel(channel = undefined) {
+  if (typeof channel === 'string') {
+    return channel;
+  }
+  return Math.random().toString(36).substr(2, 8);
+}
+
+/**
+  * Check and trim string provided by remote client
+  * @param {string} text - Subject string
+  * @private
+  * @todo Move into utility module
+  * @return {string|boolean}
+  */
+const parseText = (text) => {
+  // verifies user input is text
+  if (typeof text !== 'string') {
+    return false;
+  }
+
+  let sanitizedText = text;
+
+  // strip newlines from beginning and end
+  sanitizedText = sanitizedText.replace(/^\s*\n|^\s+$|\n\s*$/g, '');
+  // replace 3+ newlines with just 2 newlines
+  sanitizedText = sanitizedText.replace(/\n{3,}/g, '\n\n');
+
+  return sanitizedText;
+};
+
+/**
+  * Automatically executes once after server is ready
+  * @param {Object} core - Reference to core enviroment object
+  * @public
+  * @return {void}
+  */
+export function init(core) {
+  if (typeof core.muzzledHashes === 'undefined') {
+    core.muzzledHashes = {};
+  }
+}
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // increase rate limit chance and ignore if not admin or mod
+  if (!isModerator(socket.level)) {
+    return server.police.frisk(socket.address, 10);
+  }
+
+  // check user input
+  if (socket.hcProtocol === 1) {
+    if (typeof payload.nick !== 'string') {
+      return true;
+    }
+
+    payload.channel = socket.channel;
+  } else if (typeof payload.userid !== 'number') {
+    return true;
+  }
+
+  // find target user
+  const targetUser = findUser(server, payload);
+
+  if (!targetUser) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'Could not find user in that channel',
+      id: Errors.Global.UNKNOWN_USER,
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // likely dont need this, muting mods and admins is fine
+  if (targetUser.level >= socket.level) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'This trick wont work on users of the same level',
+      id: Errors.Global.PERMISSION,
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // store hash in mute list
+  const record = core.muzzledHashes[targetUser.hash] = {
+    dumb: true,
+  };
+
+  // store allies if needed
+  if (payload.allies && Array.isArray(payload.allies)) {
+    record.allies = payload.allies;
+  }
+
+  // notify mods
+  server.broadcast({
+    cmd: 'info',
+    text: `${socket.nick}#${socket.trip} muzzled ${targetUser.nick} in ${payload.channel}, userhash: ${targetUser.hash}`,
+    channel: false, // @todo Multichannel, false for global
+  }, { level: isModerator });
+
+  return true;
+}
+
+/**
+  * Automatically executes once after server is ready to register this modules hooks
+  * @param {Object} server - Reference to server enviroment object
+  * @public
+  * @return {void}
+  */
+export function initHooks(server) {
+  server.registerHook('in', 'chat', this.chatCheck.bind(this), 10);
+  server.registerHook('in', 'invite', this.inviteCheck.bind(this), 10);
+  server.registerHook('in', 'whisper', this.whisperCheck.bind(this), 10);
+}
+
+/**
+  * Executes every time an incoming chat command is invoked;
+  * hook incoming chat commands, shadow-prevent chat if they are muzzled
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function chatCheck({
+  core, server, socket, payload,
+}) {
+  if (typeof payload.text !== 'string') {
+    return false;
+  }
+
+  if (core.muzzledHashes[socket.hash]) {
+    // build fake chat payload
+    const outgoingPayload = {
+      cmd: 'chat',
+      nick: socket.nick, /* @legacy */
+      uType: socket.uType, /* @legacy */
+      userid: socket.userid,
+      channel: socket.channel,
+      text: payload.text,
+      level: socket.level,
+    };
+
+    if (socket.trip) {
+      outgoingPayload.trip = socket.trip;
+    }
+
+    if (socket.color) {
+      outgoingPayload.color = socket.color;
+    }
+
+    // broadcast to any duplicate connections in channel
+    server.broadcast(outgoingPayload, { channel: socket.channel, hash: socket.hash });
+
+    // broadcast to allies, if any
+    if (core.muzzledHashes[socket.hash].allies) {
+      server.broadcast(
+        outgoingPayload,
+        {
+          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.address, 9);
+
+    return false;
+  }
+
+  return payload;
+}
+
+/**
+  * Executes every time an incoming chat command is invoked;
+  * shadow-prevent all invites from muzzled users
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function inviteCheck({
+  core, server, socket, payload,
+}) {
+  if (core.muzzledHashes[socket.hash]) {
+    // check for spam
+    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.',
+        id: Errors.Invite.RATELIMIT,
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+    }
+
+    // verify user input
+    // if this is a legacy client add missing params to payload
+    if (socket.hcProtocol === 1) {
+      if (typeof socket.channel === 'undefined' || typeof payload.nick !== 'string') {
+        return true;
+      }
+
+      payload.channel = socket.channel; // eslint-disable-line no-param-reassign
+    } else if (typeof payload.userid !== 'number' || typeof payload.channel !== 'string') {
+      return true;
+    }
+
+    // @todo Verify this socket is part of payload.channel - multichannel patch
+    // find target user
+    const targetUser = findUser(server, payload);
+    if (!targetUser) {
+      return server.reply({
+        cmd: 'warn',
+        text: 'Could not find user in that channel',
+        id: Errors.Global.UNKNOWN_USER,
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+    }
+
+    // generate common channel
+    const channel = getChannel(payload.to);
+
+    // build invite
+    const outgoingPayload = {
+      cmd: 'invite',
+      channel: socket.channel, // @todo Multichannel
+      from: socket.userid,
+      to: targetUser.userid,
+      inviteChannel: channel,
+    };
+
+    // send invite notice to this client
+    if (socket.hcProtocol === 1) {
+      server.reply(legacyInviteReply(outgoingPayload, targetUser.nick), socket);
+    } else {
+      server.reply(outgoingPayload, socket);
+    }
+
+    return false;
+  }
+
+  return payload;
+}
+
+/**
+  * Executes every time an incoming chat command is invoked;
+  * shadow-prevent all whispers from muzzled users
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function whisperCheck({
+  core, server, socket, payload,
+}) {
+  if (core.muzzledHashes[socket.hash]) {
+    // if this is a legacy client add missing params to payload
+    if (socket.hcProtocol === 1) {
+      payload.channel = socket.channel; // eslint-disable-line no-param-reassign
+    }
+
+    // verify user input
+    const text = parseText(payload.text);
+
+    if (!text) {
+      // lets not send objects or empty text, yea?
+      return server.police.frisk(socket.address, 13);
+    }
+
+    // check for spam
+    const score = text.length / 83 / 4;
+    if (server.police.frisk(socket.address, score)) {
+      return server.reply({
+        cmd: 'warn', // @todo Add numeric error code as `id`
+        text: 'You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.',
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+    }
+
+    const targetUser = findUser(server, payload);
+    if (!targetUser) {
+      return server.reply({
+        cmd: 'warn',
+        text: 'Could not find user in that channel',
+        id: Errors.Global.UNKNOWN_USER,
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+    }
+
+    const outgoingPayload = {
+      cmd: 'whisper',
+      channel: socket.channel, // @todo Multichannel
+      from: socket.userid,
+      to: targetUser.userid,
+      text,
+    };
+
+    // send invite notice to this client
+    if (socket.hcProtocol === 1) {
+      server.reply(legacyWhisperReply(outgoingPayload, targetUser.nick), socket);
+    } else {
+      server.reply(outgoingPayload, socket);
+    }
+
+    targetUser.whisperReply = socket.nick;
+
+    return false;
+  }
+
+  return payload;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} dumb/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'dumb',
+  category: 'moderators',
+  description: 'Globally shadow mute a connection. Optional allies array will see muted messages.',
+  aliases: ['muzzle', 'mute'],
+  usage: `
+    API: { cmd: 'dumb', nick: '<target nick>', allies: ['<optional nick array>', ...] }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/mod_forcecolor.js.html b/documentation/mod_forcecolor.js.html new file mode 100644 index 0000000..232b4e5 --- /dev/null +++ b/documentation/mod_forcecolor.js.html @@ -0,0 +1,250 @@ + + + + + JSDoc: Source: mod/forcecolor.js + + + + + + + + + + +
+ +

Source: mod/forcecolor.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Color a user
+  * @version 1.0.0
+  * @description Forces a user nick to become a certain color
+  * @module forcecolor
+  */
+
+import {
+  isModerator,
+  getUserDetails,
+} from '../utility/_UAC.js';
+import {
+  Errors,
+} from '../utility/_Constants.js';
+import {
+  findUser,
+} from '../utility/_Channels.js';
+
+/**
+  * Validate a string as a valid hex color string
+  * @param {string} color - Color string to validate
+  * @private
+  * @todo Move into utility module
+  * @return {boolean}
+  */
+const verifyColor = (color) => /(^[0-9A-F]{6}$)|(^[0-9A-F]{3}$)/i.test(color);
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  server, socket, payload,
+}) {
+  // increase rate limit chance and ignore if not admin or mod
+  if (!isModerator(socket.level)) {
+    return server.police.frisk(socket.address, 10);
+  }
+
+  const { channel } = socket;
+  if (typeof payload.channel === 'undefined') {
+    payload.channel = channel;
+  }
+
+  // check user input
+  if (typeof payload.nick !== 'string') {
+    return true;
+  }
+
+  if (typeof payload.color !== 'string') {
+    return true;
+  }
+
+  // make sure requested nickname meets standards
+  const newColor = payload.color.trim().toUpperCase().replace(/#/g, '');
+  if (newColor !== 'RESET' && !verifyColor(newColor)) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'Invalid color! Color must be in hex value',
+      channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // find target user
+  const targetUser = findUser(server, payload);
+  if (!targetUser) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'Could not find user in that channel',
+      id: Errors.Global.UNKNOWN_USER,
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // TODO: Change this uType to use level / uac
+  // i guess coloring mods or admins isn't the best idea?
+  if (targetUser.uType !== 'user') {
+    return true;
+  }
+
+  if (newColor === 'RESET') {
+    targetUser.color = false;
+  } else {
+    targetUser.color = newColor;
+  }
+
+  // build update notice with new color
+  const updateNotice = {
+    ...getUserDetails(targetUser),
+    ...{
+      cmd: 'updateUser',
+      channel: socket.channel, // @todo Multichannel
+    },
+  };
+
+  // notify channel that the user has changed their name
+  // @todo this should be sent to every channel the user is in (multichannel)
+  server.broadcast(updateNotice, { channel: socket.channel });
+
+  return true;
+}
+
+/**
+  * Automatically executes once after server is ready to register this modules hooks
+  * @param {Object} server - Reference to server enviroment object
+  * @public
+  * @return {void}
+  */
+export function initHooks(server) {
+  server.registerHook('in', 'chat', this.colorCheck.bind(this), 20);
+}
+
+/**
+  * Executes every time an incoming chat command is invoked;
+  * hooks chat commands checking for /forcecolor
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {{Object|boolean|string}} Object = same/altered payload,
+  * false = suppress action,
+  * string = error
+  */
+export function colorCheck({
+  core, server, socket, payload,
+}) {
+  if (typeof payload.text !== 'string') {
+    return false;
+  }
+
+  if (payload.text.startsWith('/forcecolor ')) {
+    const input = payload.text.split(' ');
+
+    // If there is no nickname target parameter
+    if (input[1] === undefined) {
+      server.reply({
+        cmd: 'warn',
+        text: 'Refer to `/help forcecolor` for instructions on how to use this command.',
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+
+      return false;
+    }
+
+    if (input[2] === undefined) {
+      server.reply({
+        cmd: 'warn',
+        text: 'Refer to `/help forcecolor` for instructions on how to use this command.',
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+
+      return false;
+    }
+
+    const target = input[1].replace(/@/g, '');
+
+    this.run({
+      core,
+      server,
+      socket,
+      payload: {
+        cmd: 'forcecolor',
+        nick: target,
+        color: input[2],
+      },
+    });
+
+    return false;
+  }
+
+  return payload;
+}
+
+/**
+  * The following payload properties are required to invoke this module:
+  * "nick", "color"
+  * @public
+  * @typedef {Array} forcecolor/requiredData
+  */
+export const requiredData = ['nick', 'color'];
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} forcecolor/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'forcecolor',
+  category: 'moderators',
+  description: 'Forces a user nick to become a certain color',
+  usage: `
+    API: { cmd: 'forcecolor', nick: '<target nick>', color: '<color as hex>' }
+Text: /forcecolor <target nick> <color as hex>`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/mod_kick.js.html b/documentation/mod_kick.js.html new file mode 100644 index 0000000..650b684 --- /dev/null +++ b/documentation/mod_kick.js.html @@ -0,0 +1,203 @@ + + + + + JSDoc: Source: mod/kick.js + + + + + + + + + + +
+ +

Source: mod/kick.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Give da boot
+  * @version 1.0.0
+  * @description Silently forces target client(s) into another channel
+  * @module kick
+  */
+
+import {
+  isModerator,
+  levels,
+  getUserDetails,
+} from '../utility/_UAC.js';
+import {
+  Errors,
+} from '../utility/_Constants.js';
+import {
+  findUsers,
+} from '../utility/_Channels.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // increase rate limit chance and ignore if not admin or mod
+  if (!isModerator(socket.level)) {
+    return server.police.frisk(socket.address, 10);
+  }
+
+  // check user input
+  if (socket.hcProtocol === 1) {
+    if (typeof payload.nick !== 'string') {
+      if (typeof payload.nick !== 'object' && !Array.isArray(payload.nick)) {
+        return true;
+      }
+    }
+
+    payload.channel = socket.channel; // eslint-disable-line no-param-reassign
+  } else if (typeof payload.userid !== 'number') {
+    // @todo create multi-ban ui
+    if (typeof payload.userid !== 'object' && !Array.isArray(payload.userid)) {
+      return true;
+    }
+  }
+
+  // find target user(s)
+  const badClients = findUsers(server, payload);
+  if (badClients.length === 0) {
+    return server.reply({
+      cmd: 'warn',
+      text: 'Could not find user(s) in that channel',
+      id: Errors.Global.UNKNOWN_USER,
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // check if found targets are kickable, add them to the list if they are
+  const kicked = [];
+  for (let i = 0, j = badClients.length; i < j; i += 1) {
+    if (badClients[i].level >= socket.level) {
+      server.reply({
+        cmd: 'warn',
+        text: 'Cannot kick other users with the same level, how rude',
+        id: Errors.Global.PERMISSION,
+        channel: socket.channel, // @todo Multichannel
+      }, socket);
+    } else {
+      kicked.push(badClients[i]);
+    }
+  }
+
+  if (kicked.length === 0) {
+    return true;
+  }
+
+  let destChannel;
+  if (typeof payload.to === 'string' && !!payload.to.trim()) {
+    destChannel = payload.to;
+  } else {
+    destChannel = Math.random().toString(36).substr(2, 8);
+  }
+
+  // Announce the kicked clients arrival in destChannel and that they were kicked
+  // Before they arrive, so they don't see they got moved
+  for (let i = 0; i < kicked.length; i += 1) {
+    server.broadcast({
+      ...getUserDetails(kicked[i]),
+      ...{
+        cmd: 'onlineAdd',
+        channel: destChannel, // @todo Multichannel
+      },
+    }, { channel: destChannel });
+  }
+
+  // Move all kicked clients to the new channel
+  for (let i = 0; i < kicked.length; i += 1) {
+    // @todo multi-channel update
+    kicked[i].channel = destChannel;
+
+    server.broadcast({
+      cmd: 'info',
+      text: `${kicked[i].nick} was banished to ?${destChannel}`,
+      channel: socket.channel, // @todo Multichannel
+    }, { channel: socket.channel, level: isModerator });
+
+    console.log(`${socket.nick} [${socket.trip}] kicked ${kicked[i].nick} in ${socket.channel} to ${destChannel} `);
+  }
+
+  // broadcast client leave event
+  for (let i = 0, j = kicked.length; i < j; i += 1) {
+    server.broadcast({
+      cmd: 'onlineRemove',
+      userid: kicked[i].userid,
+      nick: kicked[i].nick,
+      channel: socket.channel, // @todo Multichannel
+    }, { channel: socket.channel });
+  }
+
+  // publicly broadcast kick event
+  server.broadcast({
+    cmd: 'info',
+    text: `Kicked ${kicked.map((k) => k.nick).join(', ')}`,
+    channel: socket.channel, // @todo Multichannel
+  }, { channel: socket.channel, level: (level) => level < levels.moderator });
+
+  // stats are fun
+  core.stats.increment('users-kicked', kicked.length);
+
+  return true;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} kick/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'kick',
+  category: 'moderators',
+  description: 'Silently forces target client(s) into another channel. `nick` may be string or array of strings',
+  usage: `
+    API: { cmd: 'kick', nick: '<target nick>', to: '<optional target channel>' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/mod_speak.js.html b/documentation/mod_speak.js.html new file mode 100644 index 0000000..c9566c7 --- /dev/null +++ b/documentation/mod_speak.js.html @@ -0,0 +1,157 @@ + + + + + JSDoc: Source: mod/speak.js + + + + + + + + + + +
+ +

Source: mod/speak.js

+ + + + + + +
+
+
/* eslint no-param-reassign: 0 */
+
+/**
+  * @author OpSimple ( https://github.com/OpSimple )
+  * @summary Unmuzzle a user
+  * @version 1.0.0
+  * @description Pardon a dumb user to be able to speak again
+  * @module speak
+  */
+
+import {
+  isModerator,
+} from '../utility/_UAC.js';
+
+/**
+  * Automatically executes once after server is ready
+  * @param {Object} core - Reference to core enviroment object
+  * @public
+  * @return {void}
+  */
+export function init(core) {
+  if (typeof core.muzzledHashes === 'undefined') {
+    core.muzzledHashes = {};
+  }
+}
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // increase rate limit chance and ignore if not admin or mod
+  if (!isModerator(socket.level)) {
+    return server.police.frisk(socket.address, 10);
+  }
+
+  // check user input
+  if (typeof payload.ip !== 'string' && typeof payload.hash !== 'string') {
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: "hash:'targethash' or ip:'1.2.3.4' is required",
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  if (typeof payload.ip === 'string') {
+    if (payload.ip === '*') {
+      core.muzzledHashes = {};
+
+      return server.broadcast({
+        cmd: 'info',
+        text: `${socket.nick} unmuzzled all users`,
+        channel: false, // @todo Multichannel, false for global
+      }, { level: isModerator });
+    }
+  } else if (payload.hash === '*') {
+    core.muzzledHashes = {};
+
+    return server.broadcast({
+      cmd: 'info',
+      text: `${socket.nick} unmuzzled all users`,
+      channel: false, // @todo Multichannel, false for global
+    }, { level: isModerator });
+  }
+
+  // find target & remove mute status
+  let target;
+  if (typeof payload.ip === 'string') {
+    target = server.getSocketHash(payload.ip);
+  } else {
+    target = payload.hash;
+  }
+
+  delete core.muzzledHashes[target];
+
+  // notify mods
+  server.broadcast({
+    cmd: 'info',
+    text: `${socket.nick}#${socket.trip} unmuzzled : ${target}`,
+    channel: false, // @todo Multichannel, false for global
+  }, { level: isModerator });
+
+  return true;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} speak/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'speak',
+  category: 'moderators',
+  description: 'Pardon a dumb user to be able to speak again',
+  aliases: ['unmuzzle', 'unmute'],
+  usage: `
+    API: { cmd: 'speak', ip/hash: '<target ip or hash' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/mod_unban.js.html b/documentation/mod_unban.js.html new file mode 100644 index 0000000..1ed956a --- /dev/null +++ b/documentation/mod_unban.js.html @@ -0,0 +1,142 @@ + + + + + JSDoc: Source: mod/unban.js + + + + + + + + + + +
+ +

Source: mod/unban.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Unban a user
+  * @version 1.0.0
+  * @description Un-bans target user by ip or hash
+  * @module unban
+  */
+
+import {
+  isModerator,
+} from '../utility/_UAC.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({
+  core, server, socket, payload,
+}) {
+  // increase rate limit chance and ignore if not admin or mod
+  if (!isModerator(socket.level)) {
+    return server.police.frisk(socket.address, 10);
+  }
+
+  // check user input
+  if (typeof payload.ip !== 'string' && typeof payload.hash !== 'string') {
+    return server.reply({
+      cmd: 'warn', // @todo Add numeric error code as `id`
+      text: "hash:'targethash' or ip:'1.2.3.4' is required",
+      channel: socket.channel, // @todo Multichannel
+    }, socket);
+  }
+
+  // find target
+  let mode;
+  let target;
+  if (typeof payload.ip === 'string') {
+    mode = 'ip';
+    target = payload.ip;
+  } else {
+    mode = 'hash';
+    target = payload.hash;
+  }
+
+  // remove arrest record
+  server.police.pardon(target);
+
+  // mask ip if used
+  if (mode === 'ip') {
+    target = server.getSocketHash(target);
+  }
+  console.log(`${socket.nick} [${socket.trip}] unbanned ${target} in ${socket.channel}`);
+
+  // reply with success
+  server.reply({
+    cmd: 'info',
+    text: `Unbanned ${target}`,
+    channel: socket.channel, // @todo Multichannel
+  }, socket);
+
+  // notify mods
+  server.broadcast({
+    cmd: 'info',
+    text: `${socket.nick}#${socket.trip} unbanned: ${target}`,
+    channel: false, // @todo Multichannel, false for global
+  }, { level: isModerator });
+
+  // stats are fun
+  core.stats.decrement('users-banned');
+
+  return true;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} unban/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'unban',
+  category: 'moderators',
+  description: 'Un-bans target user by ip or hash',
+  usage: `
+    API: { cmd: 'unban', ip/hash: '<target ip or hash>' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/mod_unbanall.js.html b/documentation/mod_unbanall.js.html new file mode 100644 index 0000000..8e4c416 --- /dev/null +++ b/documentation/mod_unbanall.js.html @@ -0,0 +1,115 @@ + + + + + JSDoc: Source: mod/unbanall.js + + + + + + + + + + +
+ +

Source: mod/unbanall.js

+ + + + + + +
+
+
/**
+  * @author Marzavec ( https://github.com/marzavec )
+  * @summary Released them from the void
+  * @version 1.0.0
+  * @description Clears all banned ip addresses
+  * @module unbanall
+  */
+
+import {
+  isModerator,
+} from '../utility/_UAC.js';
+
+/**
+  * Executes when invoked by a remote client
+  * @param {Object} env - Enviroment object with references to core, server, socket & payload
+  * @public
+  * @return {void}
+  */
+export async function run({ core, server, socket }) {
+  // increase rate limit chance and ignore if not admin or mod
+  if (!isModerator(socket.level)) {
+    return server.police.frisk(socket.address, 10);
+  }
+
+  // remove arrest records
+  server.police.clear();
+
+  core.stats.set('users-banned', 0);
+
+  console.log(`${socket.nick} [${socket.trip}] unbanned all`);
+
+  // reply with success
+  server.reply({
+    cmd: 'info',
+    text: 'Unbanned all ip addresses',
+    channel: socket.channel, // @todo Multichannel
+  }, socket);
+
+  // notify mods
+  server.broadcast({
+    cmd: 'info',
+    text: `${socket.nick}#${socket.trip} unbanned all ip addresses`,
+    channel: false, // @todo Multichannel, false for global
+  }, { level: isModerator });
+
+  return true;
+}
+
+/**
+  * Module meta information
+  * @public
+  * @typedef {Object} unbanall/info
+  * @property {string} name - Module command name
+  * @property {string} category - Module category name
+  * @property {string} description - Information about module
+  * @property {string} usage - Information about module usage
+  */
+export const info = {
+  name: 'unbanall',
+  category: 'moderators',
+  description: 'Clears all banned ip addresses',
+  usage: `
+    API: { cmd: 'unbanall' }`,
+};
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + diff --git a/documentation/module-addmod.html b/documentation/module-addmod.html new file mode 100644 index 0000000..1e4b182 --- /dev/null +++ b/documentation/module-addmod.html @@ -0,0 +1,604 @@ + + + + + JSDoc: Module: addmod + + + + + + + + + + +
+ +

Module: addmod

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Adds target trip to the config as a mod and upgrades the socket type
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

addmod/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

addmod/requiredData

+ + + + +
+ The following payload properties are required to invoke this module: +"trip" +
+ + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-ban.html b/documentation/module-ban.html new file mode 100644 index 0000000..bf7061d --- /dev/null +++ b/documentation/module-ban.html @@ -0,0 +1,531 @@ + + + + + JSDoc: Module: ban + + + + + + + + + + +
+ +

Module: ban

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Bans target user by name
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

ban/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-changecolor.html b/documentation/module-changecolor.html new file mode 100644 index 0000000..337cb77 --- /dev/null +++ b/documentation/module-changecolor.html @@ -0,0 +1,902 @@ + + + + + JSDoc: Module: changecolor + + + + + + + + + + +
+ +

Module: changecolor

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Allows calling client to change their nickname color
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) colorCheck(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + +

(static) initHooks(server) → {void}

+ + + + + + +
+ Automatically executes once after server is ready to register this modules hooks +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
server + + +Object + + + + Reference to server enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

changecolor/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

changecolor/requiredData

+ + + + +
+ The following payload properties are required to invoke this module: +"color" +
+ + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-changenick.html b/documentation/module-changenick.html new file mode 100644 index 0000000..10b4082 --- /dev/null +++ b/documentation/module-changenick.html @@ -0,0 +1,902 @@ + + + + + JSDoc: Module: changenick + + + + + + + + + + +
+ +

Module: changenick

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Allows calling client to change their current nickname
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) initHooks(server) → {void}

+ + + + + + +
+ Automatically executes once after server is ready to register this modules hooks +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
server + + +Object + + + + Reference to server enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) nickCheck(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

changenick/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

changenick/requiredData

+ + + + +
+ The following payload properties are required to invoke this module: +"nick" +
+ + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-chat.html b/documentation/module-chat.html new file mode 100644 index 0000000..2df83e7 --- /dev/null +++ b/documentation/module-chat.html @@ -0,0 +1,1047 @@ + + + + + JSDoc: Module: chat + + + + + + + + + + +
+ +

Module: chat

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Broadcasts passed `text` field to the calling users channel
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) commandCheckIn(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked; +checks for miscellaneous '/' based commands +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + +

(static) finalCmdCheck(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked; +assumes a failed chat command invocation and will reject with notice +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + +

(static) initHooks(server) → {void}

+ + + + + + +
+ Automatically executes once after server is ready to register this modules hooks +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
server + + +Object + + + + Reference to server enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

chat/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

chat/requiredData

+ + + + +
+ The following payload properties are required to invoke this module: +"text" +
+ + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-disconnect.html b/documentation/module-disconnect.html new file mode 100644 index 0000000..46e4209 --- /dev/null +++ b/documentation/module-disconnect.html @@ -0,0 +1,604 @@ + + + + + JSDoc: Module: disconnect + + + + + + + + + + +
+ +

Module: disconnect

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
The server invokes this module each time a websocket connection is disconnected
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

disconnect/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

disconnect/requiredData

+ + + + +
+ The following payload properties are required to invoke this module: +"cmdKey" +
+ + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-dumb.html b/documentation/module-dumb.html new file mode 100644 index 0000000..4316c2f --- /dev/null +++ b/documentation/module-dumb.html @@ -0,0 +1,1273 @@ + + + + + JSDoc: Module: dumb + + + + + + + + + + +
+ +

Module: dumb

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Globally shadow mute a connection. Optional allies array will see muted messages.
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • OpSimple ( https://github.com/OpSimple )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) chatCheck(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked; +hook incoming chat commands, shadow-prevent chat if they are muzzled +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + +

(static) init(core) → {void}

+ + + + + + +
+ Automatically executes once after server is ready +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
core + + +Object + + + + Reference to core enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) initHooks(server) → {void}

+ + + + + + +
+ Automatically executes once after server is ready to register this modules hooks +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
server + + +Object + + + + Reference to server enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) inviteCheck(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked; +shadow-prevent all invites from muzzled users +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) whisperCheck(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked; +shadow-prevent all whispers from muzzled users +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + +

Type Definitions

+ + + +

dumb/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-emote.html b/documentation/module-emote.html new file mode 100644 index 0000000..c1c2541 --- /dev/null +++ b/documentation/module-emote.html @@ -0,0 +1,903 @@ + + + + + JSDoc: Module: emote + + + + + + + + + + +
+ +

Module: emote

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Broadcasts an emote to the current channel
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) emoteCheck(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked; +hooks chat commands checking for /me +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + +

(static) initHooks(server) → {void}

+ + + + + + +
+ Automatically executes once after server is ready to register this modules hooks +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
server + + +Object + + + + Reference to server enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

emote/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

emote/requiredData

+ + + + +
+ The following payload properties are required to invoke this module: +"text" +
+ + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-forcecolor.html b/documentation/module-forcecolor.html new file mode 100644 index 0000000..ca2ecb6 --- /dev/null +++ b/documentation/module-forcecolor.html @@ -0,0 +1,903 @@ + + + + + JSDoc: Module: forcecolor + + + + + + + + + + +
+ +

Module: forcecolor

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Forces a user nick to become a certain color
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) colorCheck(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked; +hooks chat commands checking for /forcecolor +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + +

(static) initHooks(server) → {void}

+ + + + + + +
+ Automatically executes once after server is ready to register this modules hooks +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
server + + +Object + + + + Reference to server enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

forcecolor/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

forcecolor/requiredData

+ + + + +
+ The following payload properties are required to invoke this module: +"nick", "color" +
+ + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-help.html b/documentation/module-help.html new file mode 100644 index 0000000..e905547 --- /dev/null +++ b/documentation/module-help.html @@ -0,0 +1,830 @@ + + + + + JSDoc: Module: help + + + + + + + + + + +
+ +

Module: help

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Outputs information about the servers current protocol
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) helpCheck(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked; +hooks chat commands checking for /help +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + + + +

(static) initHooks(server) → {void}

+ + + + + + +
+ Automatically executes once after server is ready to register this modules hooks +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
server + + +Object + + + + Reference to server enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

help/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-invite.html b/documentation/module-invite.html new file mode 100644 index 0000000..8e4d552 --- /dev/null +++ b/documentation/module-invite.html @@ -0,0 +1,531 @@ + + + + + JSDoc: Module: invite + + + + + + + + + + +
+ +

Module: invite

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Sends an invite to the target client with the provided channel, or a random channel
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

invite/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-join.html b/documentation/module-join.html new file mode 100644 index 0000000..4fca6e6 --- /dev/null +++ b/documentation/module-join.html @@ -0,0 +1,531 @@ + + + + + JSDoc: Module: join + + + + + + + + + + +
+ +

Module: join

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Join the target channel using the supplied nick and password
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

join/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-kick.html b/documentation/module-kick.html new file mode 100644 index 0000000..f522c78 --- /dev/null +++ b/documentation/module-kick.html @@ -0,0 +1,531 @@ + + + + + JSDoc: Module: kick + + + + + + + + + + +
+ +

Module: kick

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Silently forces target client(s) into another channel
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

kick/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-listusers.html b/documentation/module-listusers.html new file mode 100644 index 0000000..7ecfac1 --- /dev/null +++ b/documentation/module-listusers.html @@ -0,0 +1,531 @@ + + + + + JSDoc: Module: listusers + + + + + + + + + + +
+ +

Module: listusers

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Outputs all current channels and sockets in those channels
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

listusers/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-morestats.html b/documentation/module-morestats.html new file mode 100644 index 0000000..f6b1b34 --- /dev/null +++ b/documentation/module-morestats.html @@ -0,0 +1,830 @@ + + + + + JSDoc: Module: morestats + + + + + + + + + + +
+ +

Module: morestats

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Sends back current server stats to the calling client
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) initHooks(server) → {void}

+ + + + + + +
+ Automatically executes once after server is ready to register this modules hooks +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
server + + +Object + + + + Reference to server enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) statsCheck(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked; +hooks chat commands checking for /stats +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + +

Type Definitions

+ + + +

morestats/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-ping.html b/documentation/module-ping.html new file mode 100644 index 0000000..087e342 --- /dev/null +++ b/documentation/module-ping.html @@ -0,0 +1,482 @@ + + + + + JSDoc: Module: ping + + + + + + + + + + +
+ +

Module: ping

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
This module is only in place to supress error notices legacy clients may get
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run() → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

ping/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-reload.html b/documentation/module-reload.html new file mode 100644 index 0000000..9b69736 --- /dev/null +++ b/documentation/module-reload.html @@ -0,0 +1,531 @@ + + + + + JSDoc: Module: reload + + + + + + + + + + +
+ +

Module: reload

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Allows a remote user to clear and re-import the server command modules
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

reload/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-removemod.html b/documentation/module-removemod.html new file mode 100644 index 0000000..89443c9 --- /dev/null +++ b/documentation/module-removemod.html @@ -0,0 +1,604 @@ + + + + + JSDoc: Module: removemod + + + + + + + + + + +
+ +

Module: removemod

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Removes target trip from the config as a mod and downgrades the socket type
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

removemod/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

removemod/requiredData

+ + + + +
+ The following payload properties are required to invoke this module: +"trip" +
+ + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-saveconfig.html b/documentation/module-saveconfig.html new file mode 100644 index 0000000..9e7635c --- /dev/null +++ b/documentation/module-saveconfig.html @@ -0,0 +1,531 @@ + + + + + JSDoc: Module: saveconfig + + + + + + + + + + +
+ +

Module: saveconfig

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Writes the current config to disk
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

saveconfig/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-session.html b/documentation/module-session.html new file mode 100644 index 0000000..b6056eb --- /dev/null +++ b/documentation/module-session.html @@ -0,0 +1,1034 @@ + + + + + JSDoc: Module: session + + + + + + + + + + +
+ +

Module: session

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Restore previous state by session or create new session
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) getSession(socket, core) → {object}

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
socket + + +* + + + +
core + + +* + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +object + + +
+
+ + + + + + + + + + + + + +

(static) init(core) → {void}

+ + + + + + +
+ Automatically executes once after server is ready +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
core + + +Object + + + + Reference to core enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(inner) notifyFailure(server, socket) → {boolean}

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
server + + +* + + + +
socket + + +* + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

session/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-shout.html b/documentation/module-shout.html new file mode 100644 index 0000000..b1d7fea --- /dev/null +++ b/documentation/module-shout.html @@ -0,0 +1,604 @@ + + + + + JSDoc: Module: shout + + + + + + + + + + +
+ +

Module: shout

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Displays passed text to every client connected
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

shout/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

shout/requiredData

+ + + + +
+ The following payload properties are required to invoke this module: +"text" +
+ + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-socketreply.html b/documentation/module-socketreply.html new file mode 100644 index 0000000..295fb88 --- /dev/null +++ b/documentation/module-socketreply.html @@ -0,0 +1,605 @@ + + + + + JSDoc: Module: socketreply + + + + + + + + + + +
+ +

Module: socketreply

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
If a warning occurs within the server, this module will relay the warning to the + client
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

socketreply/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

socketreply/requiredData

+ + + + +
+ The following payload properties are required to invoke this module: +"cmdKey", "text" +
+ + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-speak.html b/documentation/module-speak.html new file mode 100644 index 0000000..8c26b26 --- /dev/null +++ b/documentation/module-speak.html @@ -0,0 +1,686 @@ + + + + + JSDoc: Module: speak + + + + + + + + + + +
+ +

Module: speak

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Pardon a dumb user to be able to speak again
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • OpSimple ( https://github.com/OpSimple )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) init(core) → {void}

+ + + + + + +
+ Automatically executes once after server is ready +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
core + + +Object + + + + Reference to core enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

speak/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-stats.html b/documentation/module-stats.html new file mode 100644 index 0000000..fbe8aef --- /dev/null +++ b/documentation/module-stats.html @@ -0,0 +1,531 @@ + + + + + JSDoc: Module: stats + + + + + + + + + + +
+ +

Module: stats

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Sends back legacy server stats to the calling client
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

stats/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-unban.html b/documentation/module-unban.html new file mode 100644 index 0000000..91cf840 --- /dev/null +++ b/documentation/module-unban.html @@ -0,0 +1,531 @@ + + + + + JSDoc: Module: unban + + + + + + + + + + +
+ +

Module: unban

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Un-bans target user by ip or hash
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

unban/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-unbanall.html b/documentation/module-unbanall.html new file mode 100644 index 0000000..917a661 --- /dev/null +++ b/documentation/module-unbanall.html @@ -0,0 +1,531 @@ + + + + + JSDoc: Module: unbanall + + + + + + + + + + +
+ +

Module: unbanall

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Clears all banned ip addresses
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

unbanall/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/module-whisper.html b/documentation/module-whisper.html new file mode 100644 index 0000000..5d5aea7 --- /dev/null +++ b/documentation/module-whisper.html @@ -0,0 +1,911 @@ + + + + + JSDoc: Module: whisper + + + + + + + + + + +
+ +

Module: whisper

+ + + + + + +
+ +
+ + + + + +
+ +
+
+ + +
Display text on target users screen that only they can see
+ + + + + + + + + + + + + + + + + + + +
+ + +
Version:
+
  • 1.0.0
+ + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Marzavec ( https://github.com/marzavec )
  • +
+
+ + + + + + + + + +
Source:
+
+ + + + + + + +
To Do:
+
+
    +
  • This should be changed to it's own event type, instead of `info` + and accept a `userid` rather than `nick`
  • +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) initHooks(server) → {void}

+ + + + + + +
+ Automatically executes once after server is ready to register this modules hooks +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
server + + +Object + + + + Reference to server enviroment object
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) run(env) → {void}

+ + + + + + +
+ Executes when invoked by a remote client +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + + + + +

(static) whisperCheck(env)

+ + + + + + +
+ Executes every time an incoming chat command is invoked; +hooks chat commands checking for /whisper +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + + Enviroment object with references to core, server, socket & payload
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + + + + + + + + + + + +

Type Definitions

+ + + +

whisper/info

+ + + + +
+ Module meta information +
+ + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + Module command name
category + + +string + + + + Module category name
description + + +string + + + + Information about module
usage + + +string + + + + Information about module usage
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

whisper/requiredData

+ + + + +
+ The following payload properties are required to invoke this module: +"nick", "text" +
+ + + +
Type:
+
    +
  • + +Array + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.6 on Wed Jun 22 2022 10:04:25 GMT-0500 (Central Daylight Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/scripts/linenumber.js b/documentation/scripts/linenumber.js new file mode 100644 index 0000000..4354785 --- /dev/null +++ b/documentation/scripts/linenumber.js @@ -0,0 +1,25 @@ +/*global document */ +(() => { + const source = document.getElementsByClassName('prettyprint source linenums'); + let i = 0; + let lineNumber = 0; + let lineId; + let lines; + let totalLines; + let anchorHash; + + if (source && source[0]) { + anchorHash = document.location.hash.substring(1); + lines = source[0].getElementsByTagName('li'); + totalLines = lines.length; + + for (; i < totalLines; i++) { + lineNumber++; + lineId = `line${lineNumber}`; + lines[i].id = lineId; + if (lineId === anchorHash) { + lines[i].className += ' selected'; + } + } + } +})(); diff --git a/documentation/scripts/prettify/Apache-License-2.0.txt b/documentation/scripts/prettify/Apache-License-2.0.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/documentation/scripts/prettify/Apache-License-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/documentation/scripts/prettify/lang-css.js b/documentation/scripts/prettify/lang-css.js new file mode 100644 index 0000000..041e1f5 --- /dev/null +++ b/documentation/scripts/prettify/lang-css.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", +/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/documentation/scripts/prettify/prettify.js b/documentation/scripts/prettify/prettify.js new file mode 100644 index 0000000..eef5ad7 --- /dev/null +++ b/documentation/scripts/prettify/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p th:last-child { border-right: 1px solid #ddd; } + +.ancestors, .attribs { color: #999; } +.ancestors a, .attribs a +{ + color: #999 !important; + text-decoration: none; +} + +.clear +{ + clear: both; +} + +.important +{ + font-weight: bold; + color: #950B02; +} + +.yes-def { + text-indent: -1000px; +} + +.type-signature { + color: #aaa; +} + +.name, .signature { + font-family: Consolas, Monaco, 'Andale Mono', monospace; +} + +.details { margin-top: 14px; border-left: 2px solid #DDD; } +.details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; } +.details dd { margin-left: 70px; } +.details ul { margin: 0; } +.details ul { list-style-type: none; } +.details li { margin-left: 30px; padding-top: 6px; } +.details pre.prettyprint { margin: 0 } +.details .object-value { padding-top: 0; } + +.description { + margin-bottom: 1em; + margin-top: 1em; +} + +.code-caption +{ + font-style: italic; + font-size: 107%; + margin: 0; +} + +.source +{ + border: 1px solid #ddd; + width: 80%; + overflow: auto; +} + +.prettyprint.source { + width: inherit; +} + +.source code +{ + font-size: 100%; + line-height: 18px; + display: block; + padding: 4px 12px; + margin: 0; + background-color: #fff; + color: #4D4E53; +} + +.prettyprint code span.line +{ + display: inline-block; +} + +.prettyprint.linenums +{ + padding-left: 70px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.prettyprint.linenums ol +{ + padding-left: 0; +} + +.prettyprint.linenums li +{ + border-left: 3px #ddd solid; +} + +.prettyprint.linenums li.selected, +.prettyprint.linenums li.selected * +{ + background-color: lightyellow; +} + +.prettyprint.linenums li * +{ + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.params .name, .props .name, .name code { + color: #4D4E53; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 100%; +} + +.params td.description > p:first-child, +.props td.description > p:first-child +{ + margin-top: 0; + padding-top: 0; +} + +.params td.description > p:last-child, +.props td.description > p:last-child +{ + margin-bottom: 0; + padding-bottom: 0; +} + +.disabled { + color: #454545; +} diff --git a/documentation/styles/prettify-jsdoc.css b/documentation/styles/prettify-jsdoc.css new file mode 100644 index 0000000..5a2526e --- /dev/null +++ b/documentation/styles/prettify-jsdoc.css @@ -0,0 +1,111 @@ +/* JSDoc prettify.js theme */ + +/* plain text */ +.pln { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* string content */ +.str { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a keyword */ +.kwd { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a comment */ +.com { + font-weight: normal; + font-style: italic; +} + +/* a type name */ +.typ { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* a literal value */ +.lit { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* punctuation */ +.pun { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* lisp open bracket */ +.opn { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* lisp close bracket */ +.clo { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a markup tag name */ +.tag { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a markup attribute name */ +.atn { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a markup attribute value */ +.atv { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a declaration */ +.dec { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a variable name */ +.var { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* a function name */ +.fun { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; +} diff --git a/documentation/styles/prettify-tomorrow.css b/documentation/styles/prettify-tomorrow.css new file mode 100644 index 0000000..b6f92a7 --- /dev/null +++ b/documentation/styles/prettify-tomorrow.css @@ -0,0 +1,132 @@ +/* Tomorrow Theme */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* Pretty printing styles. Used with prettify.js. */ +/* SPAN elements with the classes below are added by prettyprint. */ +/* plain text */ +.pln { + color: #4d4d4c; } + +@media screen { + /* string content */ + .str { + color: #718c00; } + + /* a keyword */ + .kwd { + color: #8959a8; } + + /* a comment */ + .com { + color: #8e908c; } + + /* a type name */ + .typ { + color: #4271ae; } + + /* a literal value */ + .lit { + color: #f5871f; } + + /* punctuation */ + .pun { + color: #4d4d4c; } + + /* lisp open bracket */ + .opn { + color: #4d4d4c; } + + /* lisp close bracket */ + .clo { + color: #4d4d4c; } + + /* a markup tag name */ + .tag { + color: #c82829; } + + /* a markup attribute name */ + .atn { + color: #f5871f; } + + /* a markup attribute value */ + .atv { + color: #3e999f; } + + /* a declaration */ + .dec { + color: #f5871f; } + + /* a variable name */ + .var { + color: #c82829; } + + /* a function name */ + .fun { + color: #4271ae; } } +/* Use higher contrast and text-weight for printable form. */ +@media print, projection { + .str { + color: #060; } + + .kwd { + color: #006; + font-weight: bold; } + + .com { + color: #600; + font-style: italic; } + + .typ { + color: #404; + font-weight: bold; } + + .lit { + color: #044; } + + .pun, .opn, .clo { + color: #440; } + + .tag { + color: #006; + font-weight: bold; } + + .atn { + color: #404; } + + .atv { + color: #060; } } +/* Style */ +/* +pre.prettyprint { + background: white; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 12px; + line-height: 1.5; + border: 1px solid #ccc; + padding: 10px; } +*/ + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; } + +/* IE indents via margin-left */ +li.L0, +li.L1, +li.L2, +li.L3, +li.L4, +li.L5, +li.L6, +li.L7, +li.L8, +li.L9 { + /* */ } + +/* Alternate shading for lines */ +li.L1, +li.L3, +li.L5, +li.L7, +li.L9 { + /* */ } diff --git a/documentation/templateCommand.js b/documentation/templateCommand.js deleted file mode 100644 index 4971528..0000000 --- a/documentation/templateCommand.js +++ /dev/null @@ -1,94 +0,0 @@ -/* - Description: This is a template module that should not be user in a production - environment -*/ - -// you can require() modules here - -// this function will only be only in the scope of the module -// module support functions -const createReply = (echoInput) => { - if (echoInput.length > 100) - echoInput = 'HOW ABOUT NO?'; - - return `You want me to echo: ${echoInput}?` -}; - -/* - `exports.init()` is optional, and will only be run when the module is loaded into memory - it will always be passed a reference to the global core class - note: this will fire again if a reload is issued, keep that in mind -*/ -exports.init = (core) => { - if (typeof core.showcase === 'undefined') { - core.showcase = 'init is a handy place to put global data by assigning it to `core`'; - } -} - -/* - `exports.run()` is required and will always be passed (core, server, socket, data) - - be sure it's async too - this is the main function that will run when called -*/ -// module main -exports.run = async (core, server, socket, data) => { - - server.reply({ - cmd: 'info', - text: `SHOWCASE MODULE: ${core.showcase} - ${createReply(data.echo)}` - }, socket); - -}; - -/* - `exports.initHooks` is optional, this will be called when the server is ready - for modules to register their hooking functions - - Hook function may alter the data before it is sent to a module, or before it - is sent to a client. If the function returns `false` then the data will be - dropped without further processing -*/ -// module hook functions -exports.initHooks = (server) => { - /* - First param is hook type. A hook may be registered as either `in` or `out`: - `in`: a hook function registered as `in` will be called before the client - request is passed to the module they are attempting to call. Note: socket - in this context is the client that sent the data - `out`: a hook function registered as `out` will be called before the data is - sent to any clients. Note: `socket` in this context is the socket that - will be sent the data. - - Second param is the `cmd` type to target, any valid module may be targeted - - Third param is the hook function itself, see `exports.hookExample` for an example - */ - server.registerHook('in', 'chat', this.hookExample); -}; - -/* - This hook function example alters the payload before it gets to the `chat` module, - changing the user's input from 'hookexample' to 'WORKING!' -*/ -exports.hookExample = (core, server, socket, payload) => { - // check if we need to alter the payload - if (payload.text === 'hookexample') { - payload.text = 'WORKING!'; - } - - // always return the payload, or false if processing should drop it - return payload; -} - -// optional, if `data.echo` is missing `exports.run()` will never be called & the user will be alerted -// remember; this will only verify that the data is not undefined, not the type of data -exports.requiredData = ['echo']; - -// optional parameters are marked, all others are required -exports.info = { - name: 'showcase', // actual command name - aliases: ['templateModule'], // optional, an array of other names this module can be executed by - usage: 'showcase {echo}', // used for help output, can be omitted if no parameters are required - description: 'Simple command module template & info' // used for help output -}; diff --git a/index.js b/index.js deleted file mode 100644 index 865ee71..0000000 --- a/index.js +++ /dev/null @@ -1 +0,0 @@ -console.log('Use "npm start" instead.') diff --git a/jsdoc.json b/jsdoc.json new file mode 100644 index 0000000..2876057 --- /dev/null +++ b/jsdoc.json @@ -0,0 +1,23 @@ +{ + "plugins": [], + "recurseDepth": 10, + "source": { + "include": ["commands"], + "includePattern": ".+\\.js(doc|x)?$", + "excludePattern": "(^|\\/|\\\\)_" + }, + "sourceType": "module", + "tags": { + "allowUnknownTags": true, + "dictionaries": ["jsdoc","closure"] + }, + "templates": { + "cleverLinks": false, + "monospaceLinks": false + }, + "opts": { + "destination": "documentation", + "recurse": true, + "readme": "README.md" + } +} \ No newline at end of file diff --git a/main.mjs b/main.mjs new file mode 100644 index 0000000..285f160 --- /dev/null +++ b/main.mjs @@ -0,0 +1,45 @@ +import fs from 'fs'; +import { join, dirname } from 'path'; +import { Low, JSONFile } from 'lowdb'; +import { fileURLToPath } from 'url'; +import { CoreApp } from 'hackchat-server'; + +// required file paths +const SessionLocation = './session.key'; +const SaltLocation = './salt.key'; +const AppConfigLocation = './config.json'; + +// verify required files exist +if (fs.existsSync(SessionLocation) === false) { + throw Error('Missing session key, you may need to run: npm run config'); +} + +if (fs.existsSync(SaltLocation) === false) { + throw Error('Missing salt key, you may need to run: npm run config'); +} + +if (fs.existsSync(AppConfigLocation) === false) { + throw Error('Missing config, you may need to run: npm run config'); +} + +// build main hack chat server +const server = new CoreApp({ + configPath: './.hcserver.json', + logErrDetailed: true, + lang: 'en', +}); + +// load sessoin key data +server.sessionKey = fs.readFileSync(SessionLocation); + +// load salt key data +server.saltKey = fs.readFileSync(SaltLocation); + +// load the configuration data +const adapter = new JSONFile(AppConfigLocation); +server.appConfig = new Low(adapter); +await server.appConfig.read(); + +server.init(); + +console.log('Websocket server ready'); diff --git a/package-lock.json b/package-lock.json index 43ea2c8..5d3a2c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,31 +1,6225 @@ { "name": "hack.chat-v2", - "version": "2.1.93", - "lockfileVersion": 1, + "version": "2.2.0", + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "hack.chat-v2", + "version": "2.2.0", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "enquirer": "^2.3.6", + "hackchat-server": "^2.2.27", + "http-server": "^14.1.0", + "jsonwebtoken": "^8.5.1", + "lowdb": "^3.0.0", + "pm2": "^5.2.0" + }, + "devDependencies": { + "c8": "^7.11.0", + "chai": "^4.3.6", + "codecov": "^3.8.3", + "eslint": "^8.9.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-plugin-import": "^2.25.4", + "mocha": "^9.2.1", + "nyc": "^15.1.0" + }, + "engines": { + "node": ">= 10.15.1", + "npm": ">= 6.7.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", + "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz", + "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.17.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", + "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helpers": "^7.17.2", + "@babel/parser": "^7.17.3", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", + "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", + "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.16.4", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.17.5", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", + "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", + "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz", + "integrity": "sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", + "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", + "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.0", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", + "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz", + "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", + "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.3", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@eslint/eslintrc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.1.0.tgz", + "integrity": "sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.1", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", + "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@opencensus/core": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.9.tgz", + "integrity": "sha512-31Q4VWtbzXpVUd2m9JS6HEaPjlKvNMOiF7lWKNmXF84yUcgfAFL5re7/hjDmdyQbOp32oGc+RFV78jXIldVz6Q==", + "dependencies": { + "continuation-local-storage": "^3.2.1", + "log-driver": "^1.2.7", + "semver": "^5.5.0", + "shimmer": "^1.2.0", + "uuid": "^3.2.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@opencensus/core/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@opencensus/propagation-b3": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@opencensus/propagation-b3/-/propagation-b3-0.0.8.tgz", + "integrity": "sha512-PffXX2AL8Sh0VHQ52jJC4u3T0H6wDK6N/4bg7xh4ngMYOIi13aR1kzVvX1sVDBgfGwDOkMbl4c54Xm3tlPx/+A==", + "dependencies": { + "@opencensus/core": "^0.0.8", + "uuid": "^3.2.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@opencensus/propagation-b3/node_modules/@opencensus/core": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.8.tgz", + "integrity": "sha512-yUFT59SFhGMYQgX0PhoTR0LBff2BEhPrD9io1jWfF/VDbakRfs6Pq60rjv0Z7iaTav5gQlttJCX2+VPxFWCuoQ==", + "dependencies": { + "continuation-local-storage": "^3.2.1", + "log-driver": "^1.2.7", + "semver": "^5.5.0", + "shimmer": "^1.2.0", + "uuid": "^3.2.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@opencensus/propagation-b3/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@pm2/agent": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.1.tgz", + "integrity": "sha512-QKHMm6yexcvdDfcNE7PL9D6uEjoQPGRi+8dh+rc4Hwtbpsbh5IAvZbz3BVGjcd4HaX6pt2xGpOohG7/Y2L4QLw==", + "dependencies": { + "async": "~3.2.0", + "chalk": "~3.0.0", + "dayjs": "~1.8.24", + "debug": "~4.3.1", + "eventemitter2": "~5.0.1", + "fast-json-patch": "^3.0.0-1", + "fclone": "~1.0.11", + "nssocket": "0.6.0", + "pm2-axon": "~4.0.1", + "pm2-axon-rpc": "~0.7.0", + "proxy-agent": "~5.0.0", + "semver": "~7.2.0", + "ws": "~7.4.0" + } + }, + "node_modules/@pm2/agent/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@pm2/agent/node_modules/semver": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.2.3.tgz", + "integrity": "sha512-utbW9Z7ZxVvwiIWkdOMLOR9G/NFXh2aRucghkVrEMJWuC++r3lCkBC3LwqBinyHzGMAJxY5tn6VakZGHObq5ig==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pm2/agent/node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@pm2/io": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@pm2/io/-/io-5.0.0.tgz", + "integrity": "sha512-3rToDVJaRoob5Lq8+7Q2TZFruoEkdORxwzFpZaqF4bmH6Bkd7kAbdPrI/z8X6k1Meq5rTtScM7MmDgppH6aLlw==", + "dependencies": { + "@opencensus/core": "0.0.9", + "@opencensus/propagation-b3": "0.0.8", + "async": "~2.6.1", + "debug": "~4.3.1", + "eventemitter2": "^6.3.1", + "require-in-the-middle": "^5.0.0", + "semver": "6.3.0", + "shimmer": "^1.2.0", + "signal-exit": "^3.0.3", + "tslib": "1.9.3" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@pm2/io/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/@pm2/io/node_modules/eventemitter2": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.5.tgz", + "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" + }, + "node_modules/@pm2/io/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@pm2/js-api": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.6.7.tgz", + "integrity": "sha512-jiJUhbdsK+5C4zhPZNnyA3wRI01dEc6a2GhcQ9qI38DyIk+S+C8iC3fGjcjUbt/viLYKPjlAaE+hcT2/JMQPXw==", + "dependencies": { + "async": "^2.6.3", + "axios": "^0.21.0", + "debug": "~4.3.1", + "eventemitter2": "^6.3.1", + "ws": "^7.0.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@pm2/js-api/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/@pm2/js-api/node_modules/eventemitter2": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.5.tgz", + "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" + }, + "node_modules/@pm2/js-api/node_modules/ws": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@pm2/pm2-version-check": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@pm2/pm2-version-check/-/pm2-version-check-1.0.4.tgz", + "integrity": "sha512-SXsM27SGH3yTWKc2fKR4SYNxsmnvuBQ9dd6QHtEWmiZ/VqaOYPAIlS8+vMcn27YLtAEBGvNRSh3TPNvtjZgfqA==", + "dependencies": { + "debug": "^4.3.1" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/amp": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz", + "integrity": "sha1-at+NWKdPNh6CwfqNOJwHnhOfxH0=" + }, + "node_modules/amp-message": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/amp-message/-/amp-message-0.1.2.tgz", + "integrity": "sha1-p48cmJlQh602GSpBKY5NtJ49/EU=", + "dependencies": { + "amp": "0.3.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "dependencies": { + "default-require-extensions": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", + "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=", + "dev": true, + "engines": { + "node": ">=0.6.10" + } + }, + "node_modules/array-includes": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", + "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", + "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ast-types/node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "node_modules/async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" + }, + "node_modules/async-listener": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz", + "integrity": "sha512-gpuo6xOyF4D5DE5WvyqZdPA3NGhiT6Qf07l7DCB0wwDEsLvDIbCr6j9S5aj5Ch96dLace5tXVzWBZkxU/c5ohw==", + "dependencies": { + "semver": "^5.3.0", + "shimmer": "^1.1.0" + }, + "engines": { + "node": "<=0.11.8 || >0.11.10" + } + }, + "node_modules/async-listener/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/blessed": { + "version": "0.1.81", + "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", + "integrity": "sha1-+WLWh+wsNpVwrnGvhDJW5tDKESk=", + "bin": { + "blessed": "bin/tput.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/bodec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", + "integrity": "sha1-vIUVVUMPI8n3ZQp172TGqUw0GMw=" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", + "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001312", + "electron-to-chromium": "^1.4.71", + "escalade": "^3.1.1", + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c8": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.11.0.tgz", + "integrity": "sha512-XqPyj1uvlHMr+Y1IeRndC2X5P7iJzJlEJwBpCdBbq2JocXOgJfr+JVfJkyNMGROke5LfKrhSFXGFXnwnRJAUJw==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.2", + "find-up": "^5.0.0", + "foreground-child": "^2.0.0", + "istanbul-lib-coverage": "^3.0.1", + "istanbul-lib-report": "^3.0.0", + "istanbul-reports": "^3.0.2", + "rimraf": "^3.0.0", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^8.0.0", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.7" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/c8/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/c8/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/c8/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/c8/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/c8/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/c8/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/c8/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "dependencies": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001312", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", + "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/chai": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=" + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-tableau": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cli-tableau/-/cli-tableau-2.0.1.tgz", + "integrity": "sha512-he+WTicka9cl0Fg/y+YyxcN6/bfQ/1O3QmgxRXDhABKqLzvoOSM4fMzp39uMyLBulAFuywD2N7UaoQE7WaADxQ==", + "dependencies": { + "chalk": "3.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/cli-tableau/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/codecov": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.8.3.tgz", + "integrity": "sha512-Y8Hw+V3HgR7V71xWH2vQ9lyS358CbGCldWlJFR0JirqoGtOoas3R3/OclRTvgUYFK29mmJICDPauVKmpqbwhOA==", + "deprecated": "https://about.codecov.io/blog/codecov-uploader-deprecation-plan/", + "dev": true, + "dependencies": { + "argv": "0.0.2", + "ignore-walk": "3.0.4", + "js-yaml": "3.14.1", + "teeny-request": "7.1.1", + "urlgrey": "1.0.0" + }, + "bin": { + "codecov": "bin/codecov" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/codecov/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, + "node_modules/continuation-local-storage": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz", + "integrity": "sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA==", + "dependencies": { + "async-listener": "^0.6.0", + "emitter-listener": "^1.1.1" + } + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/croner": { + "version": "4.1.97", + "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", + "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/culvert": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", + "integrity": "sha1-lQL18BVKLVoioCPnn3HMk2+m728=" + }, + "node_modules/data-uri-to-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/dayjs": { + "version": "1.8.36", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.36.tgz", + "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==" + }, + "node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, + "dependencies": { + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/default-require-extensions/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/degenerator": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.2.tgz", + "integrity": "sha512-c0mef3SNQo56t6urUU6tdQAs+ThoD0o9B9MJ8HEt7NQcGEILCRFqQb7ZbP9JAv+QF1Ky5plydhMR/IrqWDm+TQ==", + "dependencies": { + "ast-types": "^0.13.2", + "escodegen": "^1.8.1", + "esprima": "^4.0.0", + "vm2": "^3.9.8" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/didyoumean2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/didyoumean2/-/didyoumean2-4.2.0.tgz", + "integrity": "sha512-o8KZ9RERbXaPgvXklxuLwD4RotaV5trShsNXaA/y1h5e4u6qmtv5I6enJsst9l8R1b/eqFQFwfPAiTf+FgHAQQ==", + "dependencies": { + "@babel/runtime": "^7.10.2", + "leven": "^3.1.0", + "lodash.deburr": "^4.1.0" + }, + "engines": { + "node": ">=10.13" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.75", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.75.tgz", + "integrity": "sha512-LxgUNeu3BVU7sXaKjUDD9xivocQLxFtq6wgERrutdY/yIOps3ODOZExK1jg8DTEg4U8TUCb5MLGeWFOYuxjF3Q==", + "dev": true + }, + "node_modules/emitter-listener": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", + "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", + "dependencies": { + "shimmer": "^1.2.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/es-abstract": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.9.0.tgz", + "integrity": "sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.1.0", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", + "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.25.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", + "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.2", + "has": "^1.0.3", + "is-core-module": "^2.8.0", + "is-glob": "^4.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.5", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.12.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/espree": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", + "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", + "dev": true, + "dependencies": { + "acorn": "^8.7.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter2": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", + "integrity": "sha1-YZegldX7a1folC9v1+qtY6CclFI=" + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-patch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.0.tgz", + "integrity": "sha512-IhpytlsVTRndz0hU5t0/MGzS/etxLlfrpG5V5M9mVbuj9TrJLWaMfsox9REM5rkuGX0T+5qjpe8XA1o0gZ42nA==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "dev": true, + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/fast-url-parser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "node_modules/fclone": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", + "integrity": "sha1-EOhdo4v+p/xZk0HClu4ddyZu5kA=" + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-uri-to-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", + "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dependencies": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", + "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", + "dependencies": { + "@tootallnate/once": "1", + "data-uri-to-buffer": "3", + "debug": "4", + "file-uri-to-path": "2", + "fs-extra": "^8.1.0", + "ftp": "^0.3.10" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/get-uri/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/get-uri/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/get-uri/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/git-node-fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz", + "integrity": "sha1-SbIV4kLr5Dqkx1Ybu6SZUhdSCA8=" + }, + "node_modules/git-sha1": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/git-sha1/-/git-sha1-0.1.2.tgz", + "integrity": "sha1-WZrBkrcYdYJeE6RF86bgURjC90U=" + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "13.12.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", + "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/hackchat-server": { + "version": "2.2.27", + "resolved": "https://registry.npmjs.org/hackchat-server/-/hackchat-server-2.2.27.tgz", + "integrity": "sha512-ojTngxzBO9OYj12510XsoUEddMYbE3qf7AsRkyBfNStyiNKIMWG8/kyZkLsr/f/CIYKJZCQ3/Es6Cu6t/FBHvA==", + "dependencies": { + "didyoumean2": "^4.2.0", + "enquirer": "^2.3.6", + "esm": "^3.2.25", + "fs-extra": "^10.0.0", + "ws": "^8.2.1", + "yargs": "^17.1.1" + }, + "bin": { + "hc-config": "scripts/configure.js", + "hc-generate-cmd": "scripts/generate.js", + "hc-import": "scripts/import.js" + }, + "engines": { + "node": ">= 14.10.0", + "npm": ">= 7.0.0" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasha/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-server": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.0.tgz", + "integrity": "sha512-5lYsIcZtf6pdR8tCtzAHTWrAveo4liUlJdWc7YafwK/maPgYHs+VNP6KpCClmUnSorJrARVMXqtT055zBv11Yg==", + "dependencies": { + "basic-auth": "^2.0.1", + "chalk": "^4.1.2", + "corser": "^2.0.1", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", + "minimist": "^1.2.5", + "opener": "^1.5.1", + "portfinder": "^1.0.28", + "secure-compare": "3.0.1", + "union": "~0.5.0", + "url-join": "^4.0.1" + }, + "bin": { + "http-server": "bin/http-server" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "dependencies": { + "append-transform": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-git": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/js-git/-/js-git-0.7.8.tgz", + "integrity": "sha1-UvplWrYYd9bxB578ZTS1VPMeVEQ=", + "dependencies": { + "bodec": "^0.1.0", + "culvert": "^0.1.2", + "git-sha1": "^0.1.2", + "pako": "^0.2.5" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "optional": true + }, + "node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lazy": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", + "integrity": "sha1-2qBoIGKCVCwIgojpdcKXwa53tpA=", + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.deburr": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.deburr/-/lodash.deburr-4.1.0.tgz", + "integrity": "sha1-3bG7s+8HRYwBd7oH3hRCLLAz/5s=" + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "node_modules/log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "engines": { + "node": ">=0.8.6" + } + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/loupe": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", + "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/lowdb": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-3.0.0.tgz", + "integrity": "sha512-9KZRulmIcU8fZuWiaM0d5e2/nPnrFyXkeXVpqT+MJS+vgbgOf1EbtvgQmba8HwUFgDl1oeZR6XqEJnkJmQdKmg==", + "dependencies": { + "steno": "^2.1.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.1.tgz", + "integrity": "sha512-T7uscqjJVS46Pq1XDXyo9Uvey9gd3huT/DD9cYBb4K2Xc/vbKRPUWK067bxDQRK0yIz6Jxk73IrnimvASzBNAQ==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.2.0", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", + "integrity": "sha1-EUyUlnPiqKNenTV4hSeqN7Z52is=" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "node_modules/nanoid": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", + "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/needle": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", + "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "dependencies": { + "process-on-spawn": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nssocket": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.6.0.tgz", + "integrity": "sha1-Wflvb/MhVm8zxw99vu7N/cBxVPo=", + "dependencies": { + "eventemitter2": "~0.4.14", + "lazy": "~1.0.11" + }, + "engines": { + "node": ">= 0.10.x" + } + }, + "node_modules/nssocket/node_modules/eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=" + }, + "node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "dependencies": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pac-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", + "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4", + "get-uri": "3", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "5", + "pac-resolver": "^5.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "5" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/pac-resolver": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.0.tgz", + "integrity": "sha512-H+/A6KitiHNNW+bxBKREk2MCGSxljfqRX76NjummWEYIat7ldVXRU3dhRIE3iXZ0nvGBk6smv3nntxKkzRL8NA==", + "dependencies": { + "degenerator": "^3.0.1", + "ip": "^1.1.5", + "netmask": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidusage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-3.0.0.tgz", + "integrity": "sha512-8VJLToXhj+RYZGNVw8oxc7dS54iCQXUJ+MDFHezQ/fwF5B8W4OWodAMboc1wb08S/4LiHwAmkT4ohf/d3YPPsw==", + "dependencies": { + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pidusage/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pm2": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.2.0.tgz", + "integrity": "sha512-PO5hMVhQ85cTszFM++6v07Me9hPJMkFbHjkFigtMMk+La8ty2wCi2dlBTeZYJDhPUSjK8Ccltpq2buNRcyMOTw==", + "dependencies": { + "@pm2/agent": "~2.0.0", + "@pm2/io": "~5.0.0", + "@pm2/js-api": "~0.6.7", + "@pm2/pm2-version-check": "latest", + "async": "~3.2.0", + "blessed": "0.1.81", + "chalk": "3.0.0", + "chokidar": "^3.5.1", + "cli-tableau": "^2.0.0", + "commander": "2.15.1", + "croner": "~4.1.92", + "dayjs": "~1.8.25", + "debug": "^4.3.1", + "enquirer": "2.3.6", + "eventemitter2": "5.0.1", + "fclone": "1.0.11", + "mkdirp": "1.0.4", + "needle": "2.4.0", + "pidusage": "~3.0", + "pm2-axon": "~4.0.1", + "pm2-axon-rpc": "~0.7.1", + "pm2-deploy": "~1.0.2", + "pm2-multimeter": "^0.1.2", + "promptly": "^2", + "semver": "^7.2", + "source-map-support": "0.5.19", + "sprintf-js": "1.1.2", + "vizion": "~2.2.1", + "yamljs": "0.3.0" + }, + "bin": { + "pm2": "bin/pm2", + "pm2-dev": "bin/pm2-dev", + "pm2-docker": "bin/pm2-docker", + "pm2-runtime": "bin/pm2-runtime" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "pm2-sysmonit": "^1.2.8" + } + }, + "node_modules/pm2-axon": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pm2-axon/-/pm2-axon-4.0.1.tgz", + "integrity": "sha512-kES/PeSLS8orT8dR5jMlNl+Yu4Ty3nbvZRmaAtROuVm9nYYGiaoXqqKQqQYzWQzMYWUKHMQTvBlirjE5GIIxqg==", + "dependencies": { + "amp": "~0.3.1", + "amp-message": "~0.1.1", + "debug": "^4.3.1", + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=5" + } + }, + "node_modules/pm2-axon-rpc": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/pm2-axon-rpc/-/pm2-axon-rpc-0.7.1.tgz", + "integrity": "sha512-FbLvW60w+vEyvMjP/xom2UPhUN/2bVpdtLfKJeYM3gwzYhoTEEChCOICfFzxkxuoEleOlnpjie+n1nue91bDQw==", + "dependencies": { + "debug": "^4.3.1" + }, + "engines": { + "node": ">=5" + } + }, + "node_modules/pm2-deploy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pm2-deploy/-/pm2-deploy-1.0.2.tgz", + "integrity": "sha512-YJx6RXKrVrWaphEYf++EdOOx9EH18vM8RSZN/P1Y+NokTKqYAca/ejXwVLyiEpNju4HPZEk3Y2uZouwMqUlcgg==", + "dependencies": { + "run-series": "^1.1.8", + "tv4": "^1.3.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pm2-multimeter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/pm2-multimeter/-/pm2-multimeter-0.1.2.tgz", + "integrity": "sha1-Gh5VFT1BoFU0zqI8/oYKuqDrSs4=", + "dependencies": { + "charm": "~0.1.1" + } + }, + "node_modules/pm2-sysmonit": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/pm2-sysmonit/-/pm2-sysmonit-1.2.8.tgz", + "integrity": "sha512-ACOhlONEXdCTVwKieBIQLSi2tQZ8eKinhcr9JpZSUAL8Qy0ajIgRtsLxG/lwPOW3JEKqPyw/UaHmTWhUzpP4kA==", + "optional": true, + "dependencies": { + "async": "^3.2.0", + "debug": "^4.3.1", + "pidusage": "^2.0.21", + "systeminformation": "^5.7", + "tx2": "~1.0.4" + } + }, + "node_modules/pm2-sysmonit/node_modules/pidusage": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz", + "integrity": "sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==", + "optional": true, + "dependencies": { + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pm2-sysmonit/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true + }, + "node_modules/pm2/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pm2/node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + }, + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/portfinder/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "dependencies": { + "fromentries": "^1.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/promptly": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz", + "integrity": "sha1-KhP6BjaIoqWYOxYf/wEIoH0m/HQ=", + "dependencies": { + "read": "^1.0.4" + } + }, + "node_modules/proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", + "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", + "dependencies": { + "agent-base": "^6.0.0", + "debug": "4", + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "lru-cache": "^5.1.1", + "pac-proxy-agent": "^5.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^5.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/raw-body": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.0.tgz", + "integrity": "sha512-XpyZ6O7PVu3ItMQl0LslfsRoKxMOxi3SzDkrOtxMES5AqLFpYjQCryxI4LGygUN2jL+RgFsPkMPPlG7cg/47+A==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-in-the-middle": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.1.0.tgz", + "integrity": "sha512-M2rLKVupQfJ5lf9OvqFGIT+9iVLnTmjgbOmpil12hiSQNn5zJTKGPoIisETNjfK+09vP3rpm1zJajmErpr2sEQ==", + "dependencies": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.12.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-series": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.9.tgz", + "integrity": "sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=" + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "dependencies": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "dependencies": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/steno": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/steno/-/steno-2.1.0.tgz", + "integrity": "sha512-mauOsiaqTNGFkWqIfwcm3y/fq+qKKaIWf1vf3ocOuTdco9XoHCO2AGF1gFYXuZFSWuP38Q8LBHBGJv2KnJSXyA==", + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "dev": true, + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "dev": true + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/systeminformation": { + "version": "5.11.4", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.11.4.tgz", + "integrity": "sha512-rh7bjpjP5whUaTknim5CiGdAiKZcgWhmbmxjzBRXDWqUc/k67bz2OP+03DdcX6/SN/CDSAi/NeUwM5o2gjHJoA==", + "optional": true, + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" + } + }, + "node_modules/teeny-request": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.1.1.tgz", + "integrity": "sha512-iwY6rkW5DDGq8hE2YgNQlKbptYpY5Nn2xecjQiNjOXWbKzPGUfmeUBCSQbbr306d7Z7U2N0TPl+/SwYRfua1Dg==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/teeny-request/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "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==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "node_modules/tsconfig-paths": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "node_modules/tv4": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", + "integrity": "sha1-0CDIRvrdUMhVq7JeuuzGj8EPeWM=", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/tx2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tx2/-/tx2-1.0.5.tgz", + "integrity": "sha512-sJ24w0y03Md/bxzK4FU8J8JveYYUbSs2FViLJ2D/8bytSiyPRbuE3DyL/9UKYXTZlV3yXq0L8GLlhobTnekCVg==", + "optional": true, + "dependencies": { + "json-stringify-safe": "^5.0.1" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dependencies": { + "qs": "^6.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, + "node_modules/urlgrey": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-1.0.0.tgz", + "integrity": "sha512-hJfIzMPJmI9IlLkby8QrsCykQ+SXDeO2W5Q9QTW3QpqZVTx4a/K7p8/5q+/isD8vsbVaFgql/gvAoQCRQ2Cb5w==", + "dev": true, + "dependencies": { + "fast-url-parser": "^1.1.3" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/vizion": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vizion/-/vizion-2.2.1.tgz", + "integrity": "sha512-sfAcO2yeSU0CSPFI/DmZp3FsFE9T+8913nv1xWBOyzODv13fwkn6Vl7HqxGpkr9F608M+8SuFId3s+BlZqfXww==", + "dependencies": { + "async": "^2.6.3", + "git-node-fs": "^1.0.0", + "ini": "^1.3.5", + "js-git": "^0.7.8" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/vizion/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/vm2": { + "version": "3.9.8", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.8.tgz", + "integrity": "sha512-/1PYg/BwdKzMPo8maOZ0heT7DLI0DAFTm7YQaz/Lim9oIaFZsJs3EdtalvXuBfZwczNwsYhju75NW4d6E+4q+w==", + "dependencies": { + "acorn": "^8.7.0", + "acorn-walk": "^8.2.0" + }, + "bin": { + "vm2": "bin/vm2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "engines": { + "node": "*" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "dependencies": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + }, + "bin": { + "json2yaml": "bin/json2yaml", + "yaml2json": "bin/yaml2json" + } + }, + "node_modules/yargs": { + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", + "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "@ampproject/remapping": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", + "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", "dev": true, "requires": { - "@babel/highlight": "^7.10.4" + "@jridgewell/trace-mapping": "^0.3.0" + } + }, + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/compat-data": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz", + "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==", + "dev": true + }, + "@babel/core": { + "version": "7.17.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", + "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helpers": "^7.17.2", + "@babel/parser": "^7.17.3", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0" + }, + "dependencies": { + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", + "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", + "dev": true, + "requires": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-compilation-targets": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", + "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.16.4", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.17.5", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", + "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", + "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-transforms": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz", + "integrity": "sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-simple-access": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", + "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" } }, "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true + }, + "@babel/helpers": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", + "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.0", + "@babel/types": "^7.17.0" + } + }, + "@babel/highlight": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -65,6 +6259,12 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -82,35 +6282,223 @@ } } }, + "@babel/parser": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", + "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", + "dev": true + }, + "@babel/runtime": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz", + "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/traverse": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", + "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.3", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, "@eslint/eslintrc": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz", - "integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.1.0.tgz", + "integrity": "sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg==", "dev": true, "requires": { "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", + "debug": "^4.3.2", + "espree": "^9.3.1", + "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "lodash": "^4.17.19", + "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "ms": "^2.1.1" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true } } }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jridgewell/resolve-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", + "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@opencensus/core": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.9.tgz", @@ -159,75 +6547,56 @@ } }, "@pm2/agent": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-1.0.4.tgz", - "integrity": "sha512-cZLwaoLa45FRuetKCcoI3kHnnQ7VMLpZnmVom04MoK0cpY/RxcSarkCHSCu9V+pdARwxx96QrWdrtAJdw97dng==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.1.tgz", + "integrity": "sha512-QKHMm6yexcvdDfcNE7PL9D6uEjoQPGRi+8dh+rc4Hwtbpsbh5IAvZbz3BVGjcd4HaX6pt2xGpOohG7/Y2L4QLw==", "requires": { "async": "~3.2.0", "chalk": "~3.0.0", "dayjs": "~1.8.24", - "debug": "~4.1.1", + "debug": "~4.3.1", "eventemitter2": "~5.0.1", + "fast-json-patch": "^3.0.0-1", "fclone": "~1.0.11", "nssocket": "0.6.0", - "pm2-axon": "^3.2.0", - "pm2-axon-rpc": "^0.5.0", - "proxy-agent": "~3.1.1", + "pm2-axon": "~4.0.1", + "pm2-axon-rpc": "~0.7.0", + "proxy-agent": "~5.0.0", "semver": "~7.2.0", - "ws": "~7.2.0" + "ws": "~7.4.0" }, "dependencies": { - "async": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", - "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "requires": { - "ms": "^2.1.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, "semver": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.2.3.tgz", "integrity": "sha512-utbW9Z7ZxVvwiIWkdOMLOR9G/NFXh2aRucghkVrEMJWuC++r3lCkBC3LwqBinyHzGMAJxY5tn6VakZGHObq5ig==" - } - } - }, - "@pm2/agent-node": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@pm2/agent-node/-/agent-node-1.1.10.tgz", - "integrity": "sha512-xRcrk7OEwhS3d/227/kKGvxgmbIi6Yyp27FzGlFNermEKhgddmFaRnmd7GRLIsBM/KB28NrwflBZulzk/mma6g==", - "requires": { - "debug": "^3.1.0", - "eventemitter2": "^5.0.1", - "proxy-agent": "^3.0.3", - "ws": "^6.0.0" - }, - "dependencies": { + }, "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "requires": { - "async-limiter": "~1.0.0" - } + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "requires": {} } } }, "@pm2/io": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@pm2/io/-/io-4.3.5.tgz", - "integrity": "sha512-CY/a6Nw72vrlp/FPx38l4jfEHp4gNEbo8i+WlSJ2cnWO6VE6CKmnC1zb4yQLvdP8f3EuzzoOBZVq6aGN20M82Q==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@pm2/io/-/io-5.0.0.tgz", + "integrity": "sha512-3rToDVJaRoob5Lq8+7Q2TZFruoEkdORxwzFpZaqF4bmH6Bkd7kAbdPrI/z8X6k1Meq5rTtScM7MmDgppH6aLlw==", "requires": { "@opencensus/core": "0.0.9", "@opencensus/propagation-b3": "0.0.8", - "@pm2/agent-node": "^1.1.10", "async": "~2.6.1", - "debug": "4.1.1", + "debug": "~4.3.1", "eventemitter2": "^6.3.1", "require-in-the-middle": "^5.0.0", "semver": "6.3.0", @@ -236,54 +6605,77 @@ "tslib": "1.9.3" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "requires": { - "ms": "^2.1.1" + "lodash": "^4.17.14" } }, "eventemitter2": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.3.tgz", - "integrity": "sha512-t0A2msp6BzOf+QAcI6z9XMktLj52OjGQg+8SJH6v5+3uxNpWYRR3wQmfA+6xtMU9kOC59qk9licus5dYcrYkMQ==" + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.5.tgz", + "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" } } }, "@pm2/js-api": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.6.0.tgz", - "integrity": "sha512-ZgM/0yI8s3FRyxP01wI5UzDrVTecS/SmD98z25C9fsHo2Wz3JB1DtS4uIBlPopq2/R5HIQynTUJPDNn4qo1d/Q==", + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.6.7.tgz", + "integrity": "sha512-jiJUhbdsK+5C4zhPZNnyA3wRI01dEc6a2GhcQ9qI38DyIk+S+C8iC3fGjcjUbt/viLYKPjlAaE+hcT2/JMQPXw==", "requires": { "async": "^2.6.3", - "axios": "^0.19.0", - "debug": "~3.2.6", + "axios": "^0.21.0", + "debug": "~4.3.1", "eventemitter2": "^6.3.1", "ws": "^7.0.0" }, "dependencies": { + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } + }, "eventemitter2": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.3.tgz", - "integrity": "sha512-t0A2msp6BzOf+QAcI6z9XMktLj52OjGQg+8SJH6v5+3uxNpWYRR3wQmfA+6xtMU9kOC59qk9licus5dYcrYkMQ==" + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.5.tgz", + "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" + }, + "ws": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "requires": {} } } }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + "@pm2/pm2-version-check": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@pm2/pm2-version-check/-/pm2-version-check-1.0.4.tgz", + "integrity": "sha512-SXsM27SGH3yTWKc2fKR4SYNxsmnvuBQ9dd6QHtEWmiZ/VqaOYPAIlS8+vMcn27YLtAEBGvNRSh3TPNvtjZgfqA==", + "requires": { + "debug": "^4.3.1" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true }, "@types/json5": { "version": "0.0.29", @@ -291,30 +6683,51 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, - "acorn": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", - "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==" + }, "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" }, "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "requires": { - "es6-promisify": "^5.0.0" + "debug": "4" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" } }, "ajv": { - "version": "6.12.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", - "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -337,138 +6750,110 @@ } }, "ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, + "append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "requires": { + "default-require-extensions": "^3.0.0" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "requires": { "sprintf-js": "~1.0.2" - }, - "dependencies": { - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - } } }, + "argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", + "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=", + "dev": true + }, "array-includes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", - "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", + "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", "dev": true, "requires": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "is-string": "^1.0.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" } }, "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", + "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", "dev": true, "requires": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "es-abstract": "^1.19.0" + } + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "requires": { + "tslib": "^2.0.1" }, "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, - "ast-types": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.1.tgz", - "integrity": "sha512-pfSiukbt23P1qMhNnsozLzhMLBs7EEeXqPyvPmnuZM+RMfwfqwDbSVKYflgGuVI7/VehR4oMks0igzdNAg4VeQ==", - "requires": { - "tslib": "^2.0.1" - } - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, "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-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" }, "async-listener": { "version": "0.6.10", @@ -487,56 +6872,41 @@ } }, "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "requires": { - "follow-redirects": "1.5.10" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "requires": { - "debug": "=3.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "follow-redirects": "^1.14.0" } }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "basic-auth": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", - "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + } }, "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, "blessed": { "version": "0.1.81", "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", "integrity": "sha1-+WLWh+wsNpVwrnGvhDJW5tDKESk=" }, + "bodec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", + "integrity": "sha1-vIUVVUMPI8n3ZQp172TGqUw0GMw=" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -554,15 +6924,146 @@ "fill-range": "^7.0.1" } }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "browserslist": { + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", + "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001312", + "electron-to-chromium": "^1.4.71", + "escalade": "^3.1.1", + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" + } + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "c8": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.11.0.tgz", + "integrity": "sha512-XqPyj1uvlHMr+Y1IeRndC2X5P7iJzJlEJwBpCdBbq2JocXOgJfr+JVfJkyNMGROke5LfKrhSFXGFXnwnRJAUJw==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.2", + "find-up": "^5.0.0", + "foreground-child": "^2.0.0", + "istanbul-lib-coverage": "^3.0.1", + "istanbul-lib-report": "^3.0.0", + "istanbul-reports": "^3.0.2", + "rimraf": "^3.0.0", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^8.0.0", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.7" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } + }, + "caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "requires": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } }, "callsites": { "version": "3.1.0", @@ -570,10 +7071,37 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001312", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", + "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==", + "dev": true + }, + "chai": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + } + }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -584,33 +7112,86 @@ "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=" }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" + "readdirp": "~3.6.0" } }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, "cli-tableau": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/cli-tableau/-/cli-tableau-2.0.1.tgz", "integrity": "sha512-he+WTicka9cl0Fg/y+YyxcN6/bfQ/1O3QmgxRXDhABKqLzvoOSM4fMzp39uMyLBulAFuywD2N7UaoQE7WaADxQ==", "requires": { "chalk": "3.0.0" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "codecov": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.8.3.tgz", + "integrity": "sha512-Y8Hw+V3HgR7V71xWH2vQ9lyS358CbGCldWlJFR0JirqoGtOoas3R3/OclRTvgUYFK29mmJICDPauVKmpqbwhOA==", + "dev": true, + "requires": { + "argv": "0.0.2", + "ignore-walk": "3.0.4", + "js-yaml": "3.14.1", + "teeny-request": "7.1.1", + "urlgrey": "1.0.0" + }, + "dependencies": { + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } + } }, "color-convert": { "version": "2.0.1", @@ -625,31 +7206,26 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, "commander": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "confusing-browser-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", - "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==", - "dev": true - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", "dev": true }, "continuation-local-storage": { @@ -661,23 +7237,29 @@ "emitter-listener": "^1.1.1" } }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, "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=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "corser": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=" }, - "cron": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/cron/-/cron-1.8.2.tgz", - "integrity": "sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg==", - "requires": { - "moment-timezone": "^0.5.x" - } + "croner": { + "version": "4.1.97", + "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", + "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==" }, "cross-spawn": { "version": "7.0.3", @@ -690,28 +7272,65 @@ "which": "^2.0.1" } }, + "culvert": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", + "integrity": "sha1-lQL18BVKLVoioCPnn3HMk2+m728=" + }, "data-uri-to-buffer": { - "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==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==" }, "dayjs": { - "version": "1.8.34", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.34.tgz", - "integrity": "sha512-Olb+E6EoMvdPmAMq2QoucuyZycKHjTlBXmRx8Ada+wGtq4SIXuDCdtoaX4KkK0yjf1fJLnwXQURr8gQKWKaybw==" + "version": "1.8.36", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.36.tgz", + "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==" }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" } }, "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=" + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, + "requires": { + "strip-bom": "^4.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + } + } }, "define-properties": { "version": "1.1.3", @@ -723,19 +7342,36 @@ } }, "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.2.tgz", + "integrity": "sha512-c0mef3SNQo56t6urUU6tdQAs+ThoD0o9B9MJ8HEt7NQcGEILCRFqQb7ZbP9JAv+QF1Ky5plydhMR/IrqWDm+TQ==", "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" + "ast-types": "^0.13.2", + "escodegen": "^1.8.1", + "esprima": "^4.0.0", + "vm2": "^3.9.8" } }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "didyoumean2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/didyoumean2/-/didyoumean2-4.2.0.tgz", + "integrity": "sha512-o8KZ9RERbXaPgvXklxuLwD4RotaV5trShsNXaA/y1h5e4u6qmtv5I6enJsst9l8R1b/eqFQFwfPAiTf+FgHAQQ==", + "requires": { + "@babel/runtime": "^7.10.2", + "leven": "^3.1.0", + "lodash.deburr": "^4.1.0" + } + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true }, "doctrine": { "version": "3.0.0", @@ -746,17 +7382,20 @@ "esutils": "^2.0.2" } }, - "ecstatic": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", - "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "requires": { - "he": "^1.1.1", - "mime": "^1.6.0", - "minimist": "^1.1.0", - "url-join": "^2.0.5" + "safe-buffer": "^5.0.1" } }, + "electron-to-chromium": { + "version": "1.4.75", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.75.tgz", + "integrity": "sha512-LxgUNeu3BVU7sXaKjUDD9xivocQLxFtq6wgERrutdY/yIOps3ODOZExK1jg8DTEg4U8TUCb5MLGeWFOYuxjF3Q==", + "dev": true + }, "emitter-listener": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", @@ -766,46 +7405,44 @@ } }, "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "enquirer": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.5.tgz", - "integrity": "sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", "requires": { - "ansi-colors": "^3.2.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" + "ansi-colors": "^4.1.1" } }, "es-abstract": { - "version": "1.18.0-next.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", - "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" } }, "es-to-primitive": { @@ -819,29 +7456,21 @@ "is-symbol": "^1.0.2" } }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "requires": { - "es6-promise": "^4.0.3" - } - }, - "escape-regexp": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/escape-regexp/-/escape-regexp-0.0.1.tgz", - "integrity": "sha1-9EvaEtRbvfnLf4Yu5+SCez3TIlQ=" + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "escodegen": { "version": "1.14.3", @@ -855,202 +7484,178 @@ "source-map": "~0.6.1" }, "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "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.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } } } }, "eslint": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.9.0.tgz", - "integrity": "sha512-V6QyhX21+uXp4T+3nrNfI3hQNBDa/P8ga7LoQOenwrlEFXrEnUEE+ok1dMtaS3b6rmLXhT1TkTIsG75HMLbknA==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.9.0.tgz", + "integrity": "sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.1.3", + "@eslint/eslintrc": "^1.1.0", + "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", - "debug": "^4.0.1", + "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.0", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^1.3.0", - "espree": "^7.3.0", - "esquery": "^1.2.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", + "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.19", + "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "table": "^5.2.3", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, "dependencies": { - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" + "is-glob": "^4.0.3" } } } }, "eslint-config-airbnb-base": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz", - "integrity": "sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", "dev": true, "requires": { - "confusing-browser-globals": "^1.0.9", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2" + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", "dev": true, "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" + "debug": "^3.2.7", + "resolve": "^1.20.0" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", + "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", "dev": true, "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" + "debug": "^3.2.7", + "find-up": "^2.1.0" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, "eslint-plugin-import": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz", - "integrity": "sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg==", + "version": "2.25.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", + "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", "dev": true, "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.3", - "eslint-module-utils": "^2.6.0", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.2", "has": "^1.0.3", + "is-core-module": "^2.8.0", + "is-glob": "^4.0.3", "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" + "object.values": "^1.1.5", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.12.0" }, "dependencies": { "debug": { @@ -1063,21 +7668,14 @@ } }, "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" + "esutils": "^2.0.2" } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1087,28 +7685,44 @@ } }, "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, "requires": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } } }, "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.1.0" + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } } }, "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true }, "esm": { @@ -1117,34 +7731,34 @@ "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==" }, "espree": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", - "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", + "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", "dev": true, "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.3.0" + "acorn": "^8.7.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.3.0" } }, "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { "estraverse": "^5.1.0" }, "dependencies": { "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } @@ -1159,9 +7773,9 @@ }, "dependencies": { "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } @@ -1186,17 +7800,17 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-json-patch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.0.tgz", + "integrity": "sha512-IhpytlsVTRndz0hU5t0/MGzS/etxLlfrpG5V5M9mVbuj9TrJLWaMfsox9REM5rkuGX0T+5qjpe8XA1o0gZ42nA==" + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -1208,24 +7822,41 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, + "fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "dev": true, + "requires": { + "punycode": "^1.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, "fclone": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", "integrity": "sha1-EOhdo4v+p/xZk0HClu4ddyZu5kA=" }, "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "requires": { - "flat-cache": "^2.0.1" + "flat-cache": "^3.0.4" } }, "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", + "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==" }, "fill-range": { "version": "7.0.1", @@ -1235,6 +7866,17 @@ "to-regex-range": "^5.0.1" } }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -1244,27 +7886,58 @@ "locate-path": "^2.0.0" } }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" } }, "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, "follow-redirects": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", - "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==" + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + }, + "foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + } + }, + "fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true + }, + "fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } }, "fs.realpath": { "version": "1.0.0", @@ -1272,9 +7945,9 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "optional": true }, "ftp": { @@ -1284,26 +7957,12 @@ "requires": { "readable-stream": "1.1.x", "xregexp": "2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - } } }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -1311,38 +7970,101 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "get-uri": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.4.tgz", - "integrity": "sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==", + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "~3.0.2", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "get-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", + "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", + "requires": { + "@tootallnate/once": "1", + "data-uri-to-buffer": "3", + "debug": "4", + "file-uri-to-path": "2", + "fs-extra": "^8.1.0", + "ftp": "^0.3.10" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "requires": { - "ms": "2.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" } } }, + "git-node-fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz", + "integrity": "sha1-SbIV4kLr5Dqkx1Ybu6SZUhdSCA8=" + }, + "git-sha1": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/git-sha1/-/git-sha1-0.1.2.tgz", + "integrity": "sha1-WZrBkrcYdYJeE6RF86bgURjC90U=" + }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1353,69 +8075,126 @@ } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "requires": { "is-glob": "^4.0.1" } }, "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "version": "13.12.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", + "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "type-fest": "^0.20.2" } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "hackchat-server": { + "version": "2.2.27", + "resolved": "https://registry.npmjs.org/hackchat-server/-/hackchat-server-2.2.27.tgz", + "integrity": "sha512-ojTngxzBO9OYj12510XsoUEddMYbE3qf7AsRkyBfNStyiNKIMWG8/kyZkLsr/f/CIYKJZCQ3/Es6Cu6t/FBHvA==", + "requires": { + "didyoumean2": "^4.2.0", + "enquirer": "^2.3.6", + "esm": "^3.2.25", + "fs-extra": "^10.0.0", + "ws": "^8.2.1", + "yargs": "^17.1.1" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "requires": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "requires": { + "whatwg-encoding": "^2.0.0" + } + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" } }, "http-proxy": { @@ -1429,53 +8208,42 @@ } }, "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" } }, "http-server": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz", - "integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.0.tgz", + "integrity": "sha512-5lYsIcZtf6pdR8tCtzAHTWrAveo4liUlJdWc7YafwK/maPgYHs+VNP6KpCClmUnSorJrARVMXqtT055zBv11Yg==", "requires": { - "basic-auth": "^1.0.3", - "colors": "^1.4.0", + "basic-auth": "^2.0.1", + "chalk": "^4.1.2", "corser": "^2.0.1", - "ecstatic": "^3.3.2", - "http-proxy": "^1.18.0", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", "minimist": "^1.2.5", "opener": "^1.5.1", - "portfinder": "^1.0.25", + "portfinder": "^1.0.28", "secure-compare": "3.0.1", - "union": "~0.5.0" + "union": "~0.5.0", + "url-join": "^4.0.1" } }, "https-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", - "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" + "agent-base": "6", + "debug": "4" } }, "iconv-lite": { @@ -1487,15 +8255,24 @@ } }, "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true }, + "ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -1508,6 +8285,12 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1522,16 +8305,35 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } }, "is-binary-path": { "version": "2.1.0", @@ -1541,17 +8343,38 @@ "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, "is-callable": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz", - "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, + "is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "requires": { + "has": "^1.0.3" + } + }, "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-extglob": { "version": "2.1.1", @@ -1559,23 +8382,22 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "requires": { "is-extglob": "^2.1.1" } }, "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true }, "is-number": { @@ -1583,30 +8405,88 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "has-tostringtag": "^1.0.0" } }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, + "is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "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==", + "dev": true + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -1618,6 +8498,99 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "requires": { + "append-transform": "^2.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "js-git": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/js-git/-/js-git-0.7.8.tgz", + "integrity": "sha1-UvplWrYYd9bxB578ZTS1VPMeVEQ=", + "requires": { + "bodec": "^0.1.0", + "culvert": "^0.1.2", + "git-sha1": "^0.1.2", + "pako": "^0.2.5" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1625,23 +8598,28 @@ "dev": true }, "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" }, "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true } } }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1654,6 +8632,12 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "optional": true + }, "json5": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", @@ -1663,30 +8647,76 @@ "minimist": "^1.2.0" } }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "lazy": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", "integrity": "sha1-2qBoIGKCVCwIgojpdcKXwa53tpA=" }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, "locate-path": { @@ -1700,15 +8730,94 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.deburr": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.deburr/-/lodash.deburr-4.1.0.tgz", + "integrity": "sha1-3bG7s+8HRYwBd7oH3hRCLLAz/5s=" + }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" }, "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==" }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "loupe": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", + "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "dev": true, + "requires": { + "get-func-name": "^2.0.0" + } + }, + "lowdb": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-3.0.0.tgz", + "integrity": "sha512-9KZRulmIcU8fZuWiaM0d5e2/nPnrFyXkeXVpqT+MJS+vgbgOf1EbtvgQmba8HwUFgDl1oeZR6XqEJnkJmQdKmg==", + "requires": { + "steno": "^2.1.0" + } + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -1717,30 +8826,166 @@ "yallist": "^3.0.2" } }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "mocha": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.1.tgz", + "integrity": "sha512-T7uscqjJVS46Pq1XDXyo9Uvey9gd3huT/DD9cYBb4K2Xc/vbKRPUWK067bxDQRK0yIz6Jxk73IrnimvASzBNAQ==", + "dev": true, "requires": { - "minimist": "^1.2.5" + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.2.0", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + } } }, "module-details-from-path": { @@ -1748,19 +8993,6 @@ "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", "integrity": "sha1-EUyUlnPiqKNenTV4hSeqN7Z52is=" }, - "moment": { - "version": "2.27.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", - "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" - }, - "moment-timezone": { - "version": "0.5.31", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", - "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", - "requires": { - "moment": ">= 2.9.0" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -1771,6 +9003,12 @@ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, + "nanoid": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", + "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "dev": true + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -1785,33 +9023,47 @@ "debug": "^3.2.6", "iconv-lite": "^0.4.4", "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } } }, "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==" }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "whatwg-url": "^5.0.0" } }, + "node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "requires": { + "process-on-spawn": "^1.0.0" + } + }, + "node-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "dev": true + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -1833,11 +9085,159 @@ } } }, + "nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "requires": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "dependencies": { + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" }, "object-keys": { "version": "1.1.1", @@ -1846,80 +9246,37 @@ "dev": true }, "object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dev": true, "requires": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", "has-symbols": "^1.0.1", "object-keys": "^1.1.1" } }, "object.entries": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", - "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", "dev": true, "requires": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "has": "^1.0.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "es-abstract": "^1.19.1" } }, "object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", "dev": true, "requires": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "es-abstract": "^1.19.1" } }, "once": { @@ -1931,21 +9288,22 @@ } }, "opener": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", - "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==" + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" }, "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" } }, "p-limit": { @@ -1966,6 +9324,15 @@ "p-limit": "^1.1.0" } }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", @@ -1973,42 +9340,48 @@ "dev": true }, "pac-proxy-agent": { - "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==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", + "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", "requires": { - "agent-base": "^4.2.0", - "debug": "^4.1.1", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^3.0.0", - "pac-resolver": "^3.0.0", + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4", + "get-uri": "3", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "5", + "pac-resolver": "^5.0.0", "raw-body": "^2.2.0", - "socks-proxy-agent": "^4.0.1" - }, - "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" - } - } + "socks-proxy-agent": "5" } }, "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.0.tgz", + "integrity": "sha512-H+/A6KitiHNNW+bxBKREk2MCGSxljfqRX76NjummWEYIat7ldVXRU3dhRIE3iXZ0nvGBk6smv3nntxKkzRL8NA==", "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", + "degenerator": "^3.0.1", "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" + "netmask": "^2.0.1" } }, + "package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2018,15 +9391,6 @@ "callsites": "^3.0.0" } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -2045,130 +9409,172 @@ "dev": true }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" - }, - "pidusage": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.18.tgz", - "integrity": "sha512-Y/VfKfh3poHjMEINxU+gJTeVOBjiThQeFAmzR7z56HSNiMx+etl+yBhk42nRPciPYt/VZl8DQLVXNC6P5vH11A==", - "requires": { - "safe-buffer": "^5.1.2" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pidusage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-3.0.0.tgz", + "integrity": "sha512-8VJLToXhj+RYZGNVw8oxc7dS54iCQXUJ+MDFHezQ/fwF5B8W4OWodAMboc1wb08S/4LiHwAmkT4ohf/d3YPPsw==", + "requires": { + "safe-buffer": "^5.2.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "requires": { - "find-up": "^2.1.0" + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } } }, "pm2": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/pm2/-/pm2-4.4.1.tgz", - "integrity": "sha512-ece2zqVvSg29tIGdznKqk07IwVaO4mX7zLBMVxbJQMfvxpQUotLLERDW0v/RYMHtzj1bX8MLsDUsmPiIbEszKg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.2.0.tgz", + "integrity": "sha512-PO5hMVhQ85cTszFM++6v07Me9hPJMkFbHjkFigtMMk+La8ty2wCi2dlBTeZYJDhPUSjK8Ccltpq2buNRcyMOTw==", "requires": { - "@pm2/agent": "~1.0.2", - "@pm2/io": "~4.3.5", - "@pm2/js-api": "~0.6.0", - "@pm2/pm2-version-check": "^1.0.3", + "@pm2/agent": "~2.0.0", + "@pm2/io": "~5.0.0", + "@pm2/js-api": "~0.6.7", + "@pm2/pm2-version-check": "latest", "async": "~3.2.0", "blessed": "0.1.81", "chalk": "3.0.0", - "chokidar": "^3.3.0", + "chokidar": "^3.5.1", "cli-tableau": "^2.0.0", "commander": "2.15.1", - "cron": "1.8.2", + "croner": "~4.1.92", "dayjs": "~1.8.25", - "debug": "4.1.1", - "enquirer": "2.3.5", + "debug": "^4.3.1", + "enquirer": "2.3.6", "eventemitter2": "5.0.1", "fclone": "1.0.11", "mkdirp": "1.0.4", "needle": "2.4.0", - "pidusage": "2.0.18", - "pm2-axon": "3.3.0", - "pm2-axon-rpc": "0.5.1", + "pidusage": "~3.0", + "pm2-axon": "~4.0.1", + "pm2-axon-rpc": "~0.7.1", "pm2-deploy": "~1.0.2", "pm2-multimeter": "^0.1.2", + "pm2-sysmonit": "^1.2.8", "promptly": "^2", - "ps-list": "6.3.0", "semver": "^7.2", - "source-map-support": "0.5.16", + "source-map-support": "0.5.19", "sprintf-js": "1.1.2", - "systeminformation": "^4.23.3", - "vizion": "0.2.13", + "vizion": "~2.2.1", "yamljs": "0.3.0" }, "dependencies": { - "@pm2/pm2-version-check": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@pm2/pm2-version-check/-/pm2-version-check-1.0.3.tgz", - "integrity": "sha512-SBuYsh+o35knItbRW97vl5/5nEc5c5DYP7PxjyPLOfmm9bMaDsVeATXjXMBy6+KLlyrYWHZxGbfXe003NnHClg==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "requires": { - "debug": "^4.1.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "async": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", - "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" - }, - "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" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" } } }, "pm2-axon": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/pm2-axon/-/pm2-axon-3.3.0.tgz", - "integrity": "sha512-dAFlFYRuFbFjX7oAk41zT+dx86EuaFX/TgOp5QpUKRKwxb946IM6ydnoH5sSTkdI2pHSVZ+3Am8n/l0ocr7jdQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pm2-axon/-/pm2-axon-4.0.1.tgz", + "integrity": "sha512-kES/PeSLS8orT8dR5jMlNl+Yu4Ty3nbvZRmaAtROuVm9nYYGiaoXqqKQqQYzWQzMYWUKHMQTvBlirjE5GIIxqg==", "requires": { "amp": "~0.3.1", "amp-message": "~0.1.1", - "debug": "^3.0", - "escape-regexp": "0.0.1" + "debug": "^4.3.1", + "escape-string-regexp": "^4.0.0" } }, "pm2-axon-rpc": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/pm2-axon-rpc/-/pm2-axon-rpc-0.5.1.tgz", - "integrity": "sha512-hT8gN3/j05895QLXpwg+Ws8PjO4AVID6Uf9StWpud9HB2homjc1KKCcI0vg9BNOt56FmrqKDT1NQgheIz35+sA==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/pm2-axon-rpc/-/pm2-axon-rpc-0.7.1.tgz", + "integrity": "sha512-FbLvW60w+vEyvMjP/xom2UPhUN/2bVpdtLfKJeYM3gwzYhoTEEChCOICfFzxkxuoEleOlnpjie+n1nue91bDQw==", "requires": { - "debug": "^3.0" + "debug": "^4.3.1" } }, "pm2-deploy": { @@ -2188,6 +9594,36 @@ "charm": "~0.1.1" } }, + "pm2-sysmonit": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/pm2-sysmonit/-/pm2-sysmonit-1.2.8.tgz", + "integrity": "sha512-ACOhlONEXdCTVwKieBIQLSi2tQZ8eKinhcr9JpZSUAL8Qy0ajIgRtsLxG/lwPOW3JEKqPyw/UaHmTWhUzpP4kA==", + "optional": true, + "requires": { + "async": "^3.2.0", + "debug": "^4.3.1", + "pidusage": "^2.0.21", + "systeminformation": "^5.7", + "tx2": "~1.0.4" + }, + "dependencies": { + "pidusage": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz", + "integrity": "sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==", + "optional": true, + "requires": { + "safe-buffer": "^5.2.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "optional": true + } + } + }, "portfinder": { "version": "1.0.28", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", @@ -2196,24 +9632,49 @@ "async": "^2.6.2", "debug": "^3.1.1", "mkdirp": "^0.5.5" + }, + "dependencies": { + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + } } }, "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "requires": { + "fromentries": "^1.2.0" + } + }, "promptly": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz", @@ -2223,28 +9684,18 @@ } }, "proxy-agent": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.1.tgz", - "integrity": "sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", + "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", "requires": { - "agent-base": "^4.2.0", + "agent-base": "^6.0.0", "debug": "4", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^3.0.0", + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", "lru-cache": "^5.1.1", - "pac-proxy-agent": "^3.0.1", + "pac-proxy-agent": "^5.0.0", "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^4.0.1" - }, - "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" - } - } + "socks-proxy-agent": "^5.0.0" } }, "proxy-from-env": { @@ -2252,11 +9703,6 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, - "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==" - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -2264,17 +9710,29 @@ "dev": true }, "qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } }, "raw-body": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", - "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.0.tgz", + "integrity": "sha512-XpyZ6O7PVu3ItMQl0LslfsRoKxMOxi3SzDkrOtxMES5AqLFpYjQCryxI4LGygUN2jL+RgFsPkMPPlG7cg/47+A==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.3", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } @@ -2287,101 +9745,79 @@ "mute-stream": "~0.0.4" } }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "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": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "requires": { "picomatch": "^2.2.1" } }, + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, + "release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "requires": { + "es6-error": "^4.0.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, "require-in-the-middle": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.0.3.tgz", - "integrity": "sha512-p/ICV8uMlqC4tjOYabLMxAWCIKa0YUQgZZ6KDM0xgXJNgdGQ1WmL2A07TwmrZw+wi6ITUFKzH5v3n+ENEyXVkA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.1.0.tgz", + "integrity": "sha512-M2rLKVupQfJ5lf9OvqFGIT+9iVLnTmjgbOmpil12hiSQNn5zJTKGPoIisETNjfK+09vP3rpm1zJajmErpr2sEQ==", "requires": { "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" - } - } } }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "requires": { - "path-parse": "^1.0.6" + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-from": { @@ -2391,18 +9827,18 @@ "dev": true }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { "glob": "^7.1.3" } }, "run-series": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.8.tgz", - "integrity": "sha512-+GztYEPRpIsQoCSraWHDBs9WVy4eVME16zhOtDB4H9J4xN0XRhknnmLOl+4gRgZtu8dpp9N/utSPjKH/xmDzXg==" + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.9.tgz", + "integrity": "sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==" }, "safe-buffer": { "version": "5.1.2", @@ -2425,14 +9861,47 @@ "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=" }, "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "shebang-command": { "version": "2.0.0", @@ -2454,79 +9923,43 @@ "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - } + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" } }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "smart-buffer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", - "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" }, "socks": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", - "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", "requires": { - "ip": "1.1.5", - "smart-buffer": "^4.1.0" + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" } }, "socks-proxy-agent": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", - "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" - }, - "dependencies": { - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "requires": { - "es6-promisify": "^5.0.0" - } - } + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" } }, "source-map": { @@ -2535,144 +9968,50 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" } }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", - "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", - "dev": true - }, "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "steno": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/steno/-/steno-2.1.0.tgz", + "integrity": "sha512-mauOsiaqTNGFkWqIfwcm3y/fq+qKKaIWf1vf3ocOuTdco9XoHCO2AGF1gFYXuZFSWuP38Q8LBHBGJv2KnJSXyA==" + }, + "stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "stubs": "^3.0.0" } }, "string_decoder": { @@ -2680,13 +10019,42 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" } }, "strip-bom": { @@ -2701,6 +10069,12 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2709,22 +10083,47 @@ "has-flag": "^4.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, "systeminformation": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-4.27.3.tgz", - "integrity": "sha512-0Nc8AYEK818h7FI+bbe/kj7xXsMD5zOHvO9alUqQH/G4MHXu5tHQfWqC/bzWOk4JtoQPhnyLgxMYncDA2eeSBw==", + "version": "5.11.4", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.11.4.tgz", + "integrity": "sha512-rh7bjpjP5whUaTknim5CiGdAiKZcgWhmbmxjzBRXDWqUc/k67bz2OP+03DdcX6/SN/CDSAi/NeUwM5o2gjHJoA==", "optional": true }, - "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "teeny-request": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.1.1.tgz", + "integrity": "sha512-iwY6rkW5DDGq8hE2YgNQlKbptYpY5Nn2xecjQiNjOXWbKzPGUfmeUBCSQbbr306d7Z7U2N0TPl+/SwYRfua1Dg==", "dev": true, "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^8.0.0" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + } + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" } }, "text-table": { @@ -2733,10 +10132,11 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true }, "to-regex-range": { "version": "5.0.1", @@ -2747,14 +10147,20 @@ } }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true }, "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", "dev": true, "requires": { "@types/json5": "^0.0.29", @@ -2764,29 +10170,66 @@ } }, "tslib": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", - "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, "tv4": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", "integrity": "sha1-0CDIRvrdUMhVq7JeuuzGj8EPeWM=" }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "tx2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tx2/-/tx2-1.0.5.tgz", + "integrity": "sha512-sJ24w0y03Md/bxzK4FU8J8JveYYUbSs2FViLJ2D/8bytSiyPRbuE3DyL/9UKYXTZlV3yXq0L8GLlhobTnekCVg==", + "optional": true, "requires": { - "prelude-ls": "~1.1.2" + "json-stringify-safe": "^5.0.1" } }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, "union": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", @@ -2795,29 +10238,38 @@ "qs": "^6.4.0" } }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { "punycode": "^2.1.0" } }, "url-join": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", - "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "urlgrey": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-1.0.0.tgz", + "integrity": "sha512-hJfIzMPJmI9IlLkby8QrsCykQ+SXDeO2W5Q9QTW3QpqZVTx4a/K7p8/5q+/isD8vsbVaFgql/gvAoQCRQ2Cb5w==", + "dev": true, + "requires": { + "fast-url-parser": "^1.1.3" + } }, "uuid": { "version": "3.4.0", @@ -2825,36 +10277,94 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "v8-compile-cache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", - "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", "dev": true, "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } } }, "vizion": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/vizion/-/vizion-0.2.13.tgz", - "integrity": "sha1-ExTN7is0EW+fWxJIU2+V2/zW718=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vizion/-/vizion-2.2.1.tgz", + "integrity": "sha512-sfAcO2yeSU0CSPFI/DmZp3FsFE9T+8913nv1xWBOyzODv13fwkn6Vl7HqxGpkr9F608M+8SuFId3s+BlZqfXww==", "requires": { - "async": "1.5" + "async": "^2.6.3", + "git-node-fs": "^1.0.0", + "ini": "^1.3.5", + "js-git": "^0.7.8" }, "dependencies": { "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } } } }, + "vm2": { + "version": "3.9.8", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.8.tgz", + "integrity": "sha512-/1PYg/BwdKzMPo8maOZ0heT7DLI0DAFTm7YQaz/Lim9oIaFZsJs3EdtalvXuBfZwczNwsYhju75NW4d6E+4q+w==", + "requires": { + "acorn": "^8.7.0", + "acorn-walk": "^8.2.0" + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "requires": { + "iconv-lite": "0.6.3" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2864,35 +10374,79 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, "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==" }, + "workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, "requires": { - "mkdirp": "^0.5.1" + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } }, "ws": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz", - "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA==" + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "requires": {} }, "xregexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -2906,6 +10460,57 @@ "argparse": "^1.0.7", "glob": "^7.0.5" } + }, + "yargs": { + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", + "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + } + }, + "yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==" + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + } + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index 6be4671..3861229 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,9 @@ { "name": "hack.chat-v2", - "version": "2.1.93", + "version": "2.2.0", + "type": "module", "description": "a minimal distraction free chat application", - "main": "index.js", + "main": "main.mjs", "repository": { "type": "git", "url": "git+https://github.com/hack-chat/main.git" @@ -12,26 +13,38 @@ "npm": ">= 6.7.0" }, "scripts": { - "start": "pm2 startOrReload pm2.config.js", - "stop": "pm2 stop pm2.config.js && pm2 delete pm2.config.js", + "start": "pm2 startOrReload pm2.config.cjs", + "stop": "pm2 stop pm2.config.cjs && pm2 delete pm2.config.cjs", "logs": "pm2 logs", "clear": "pm2 flush", "status": "pm2 list", - "refresh": "pm2 flush && pm2 stop pm2.config.js && pm2 delete pm2.config.js", - "postinstall": "cd ./server && npm install && npm run config", - "lint": "eslint --ignore-path .gitignore -- ./server ", - "lint:fix": "eslint --ignore-path .gitignore --fix -- ./server " + "refresh": "pm2 flush && pm2 stop pm2.config.cjs && pm2 delete pm2.config.cjs", + "postinstall": "npm run config", + "config": "node ./scripts/config.js", + "lint": "eslint -- . ", + "lint:fix": "eslint --fix -- . ", + "test_run": "cls && npm run refresh && npm start && npm run logs && npm run stop", + "test": "npm run lint && c8 mocha --exit ./test/*.test.js", + "makedocs": "jsdoc -c jsdoc.json" }, "author": "Marzavec", - "license": "WTFPL", + "license": "MIT", "dependencies": { - "esm": "^3.2.25", - "http-server": "^0.12.3", - "pm2": "^4.4.1" + "enquirer": "^2.3.6", + "hackchat-server": "^2.2.27", + "http-server": "^14.1.0", + "jsonwebtoken": "^8.5.1", + "lowdb": "^3.0.0", + "pm2": "^5.2.0" }, "devDependencies": { - "eslint": "^7.9.0", - "eslint-config-airbnb-base": "^14.2.0", - "eslint-plugin-import": "^2.22.0" + "c8": "^7.11.0", + "chai": "^4.3.6", + "codecov": "^3.8.3", + "eslint": "^8.9.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-plugin-import": "^2.25.4", + "mocha": "^9.2.1", + "nyc": "^15.1.0" } } diff --git a/pm2.config.js b/pm2.config.cjs similarity index 79% rename from pm2.config.js rename to pm2.config.cjs index 491f8e1..364373a 100644 --- a/pm2.config.js +++ b/pm2.config.cjs @@ -1,13 +1,11 @@ module.exports = { apps : [{ - name : 'hackchat-websocket', - node_args : '-r esm', - script : './server/main.js', - instances: 1, + name: 'hackchat-websocket', + script: './main.mjs', autorestart: true, max_memory_restart: '2G', exec_mode: 'fork', - watch : false, + watch: false, env: { NODE_ENV: 'development' }, diff --git a/scripts/config.js b/scripts/config.js new file mode 100644 index 0000000..89d3d80 --- /dev/null +++ b/scripts/config.js @@ -0,0 +1,191 @@ +/* eslint-disable no-await-in-loop */ +/* eslint import/no-unresolved: 0 */ + +import fs from 'fs'; +import { Low, JSONFile } from 'lowdb'; +import crypto from 'crypto'; +import enquirerPkg from 'enquirer'; + +const { + Select, + Confirm, + Password, + Input, +} = enquirerPkg; + +// required file paths +const SessionLocation = './session.key'; +const SaltLocation = './salt.key'; +const AppConfigLocation = './config.json'; + +// default configuration options +const defaultConfig = { + adminTrip: '', + globalMods: [], + publicChannels: [], + permissions: [], +}; + +// standard / default channel list +const defaultChannels = [ + 'lounge', + 'meta', + 'math', + 'physics', + 'chemistry', + 'technology', + 'programming', + 'games', + 'banana', +]; + +// load the configuration data +const adapter = new JSONFile(AppConfigLocation); +const config = new Low(adapter); + +// check for missing cert, generate if needed +const checkCert = async () => { + if (fs.existsSync(SessionLocation) === false) { + const prompt = new Confirm({ + name: 'certDialogue', + message: 'Missing session key, create new?', + }); + + if (await prompt.run() !== false) { + const data = crypto.randomBytes(4096); + + fs.writeFile(SessionLocation, data, (err) => { + if (err) throw err; + }); + } + } else { + console.log('Found existing session key.'); + } +}; + +// check for missing or uninitialized config +const checkConfig = async () => { + await config.read(); + + if (config.data === null) { + config.data = defaultConfig; + await config.write(); + } +}; + +// check for missing or uninitialized salt +const checkTripSalt = async () => { + if (fs.existsSync(SaltLocation) === false) { + const prompt = new Confirm({ + name: 'overwrite', + message: 'Missing trip salt, create new?', + }); + + if (await prompt.run() !== false) { + const data = crypto.randomBytes(4096); + + fs.writeFileSync(SaltLocation, data); + } + } else { + console.log('Found existing trip salt.'); + } +}; + +// verify config has an admin account +const checkPermissions = async () => { + if (typeof config.data.adminTrip === 'undefined' || config.data.adminTrip === '') { + const salt = fs.readFileSync(SaltLocation); + + const prompt = new Password({ + name: 'adminPassword', + message: 'What is your admin password?', + }); + + const password = await prompt.run(); + + const sha = crypto.createHash('sha256'); + sha.update(password + salt); + config.data.adminTrip = sha.digest('base64').substr(0, 6); + + await config.write(); + } else { + console.log(`Found admin trip: ${config.data.adminTrip}`); + } +}; + +// prompt user for a channel name +const getChannel = async () => { + const chanPrompt = new Input({ + message: 'New channel name:', + }); + + const chan = await chanPrompt.run(); + + return chan; +}; + +// prompt user to save standard channels or input their own +const setupChannels = async () => { + const standardMode = 'Use standard channels'; + const manualMode = 'Manual input'; + const modePrompt = new Select({ + name: 'mode', + message: 'How would you like to setup the public channels?', + choices: [ + standardMode, + manualMode, + ], + }); + + const mode = await modePrompt.run(); + + if (mode === standardMode) { + config.data.publicChannels = defaultChannels; + + await config.write(); + } else { + const channels = []; + let newChannel = ''; + + for (;;) { + console.log('(Leave blank to finish) Channels:', channels.join(', ')); + newChannel = await getChannel(); + + if (newChannel === '') { + break; + } else { + channels.push(newChannel); + } + } + + config.data.publicChannels = channels; + + await config.write(); + } +}; + +// check if pulic channels have been initialized +const checkPublicChannels = async () => { + if (typeof config.data.publicChannels === 'undefined' || config.data.publicChannels.length === 0) { + const prompt = new Confirm({ + name: 'addChannels', + message: 'Missing public channels, setup now?', + }); + + if (await prompt.run() !== false) { + await setupChannels(); + } + } else { + console.log('Found existing public channels.'); + } +}; + +// start checking +await checkCert(); +await checkConfig(); +await checkTripSalt(); +await checkPermissions(); +await checkPublicChannels(); + +// done! +console.log('Config completed!'); diff --git a/server/main.js b/server/main.js deleted file mode 100644 index 55b116b..0000000 --- a/server/main.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * HackChat main server entry point - * @author Marzavec ( https://github.com/marzavec ) - * @version v2.0.0 - * @license WTFPL ( http://www.wtfpl.net/txt/copying/ ) - */ - -// import and initialize the core application -import CoreApp from './src/serverLib/CoreApp'; - -const coreApp = new CoreApp(); -coreApp.init(); diff --git a/server/package-lock.json b/server/package-lock.json deleted file mode 100644 index 8049c6c..0000000 --- a/server/package-lock.json +++ /dev/null @@ -1,357 +0,0 @@ -{ - "name": "hack.chat-v2", - "version": "2.1.93", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "ascii-captcha": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/ascii-captcha/-/ascii-captcha-0.0.3.tgz", - "integrity": "sha1-NAtO1oVYOHEHsJVzBC/kc4v0mPk=" - }, - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, - "common-tags": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", - "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "cycle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" - }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" - }, - "deep-equal": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", - "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=" - }, - "didyoumean2": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/didyoumean2/-/didyoumean2-4.0.0.tgz", - "integrity": "sha512-7+OMIHqPDJ4uxeExQx8cSk26oD3KUloAQzi2R+3rmTU4IHvSDDmWZTQ6bmC4+MTw61DkYoh5ARxwS9MRoz0t2A==", - "requires": { - "leven": "^3.1.0", - "lodash.deburr": "^4.1.0" - } - }, - "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", - "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "glob": { - "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", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "i": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/i/-/i-0.3.6.tgz", - "integrity": "sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" - }, - "lodash.deburr": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.deburr/-/lodash.deburr-4.1.0.tgz", - "integrity": "sha1-3bG7s+8HRYwBd7oH3hRCLLAz/5s=" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, - "ncp": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz", - "integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "pkginfo": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", - "integrity": "sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=" - }, - "prompt": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.0.0.tgz", - "integrity": "sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4=", - "requires": { - "colors": "^1.1.2", - "pkginfo": "0.x.x", - "read": "1.0.x", - "revalidator": "0.1.x", - "utile": "0.3.x", - "winston": "2.1.x" - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "requires": { - "mute-stream": "~0.0.4" - } - }, - "readdir-recursive": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/readdir-recursive/-/readdir-recursive-0.0.4.tgz", - "integrity": "sha1-mvQ1q6nFi9gNvclIi025up8SMB8=" - }, - "revalidator": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", - "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=" - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "requires": { - "glob": "^7.1.3" - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "utile": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/utile/-/utile-0.3.0.tgz", - "integrity": "sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo=", - "requires": { - "async": "~0.9.0", - "deep-equal": "~0.2.1", - "i": "0.3.x", - "mkdirp": "0.x.x", - "ncp": "1.0.x", - "rimraf": "2.x.x" - } - }, - "winston": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.1.1.tgz", - "integrity": "sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4=", - "requires": { - "async": "~1.0.0", - "colors": "1.0.x", - "cycle": "1.0.x", - "eyes": "0.1.x", - "isstream": "0.1.x", - "pkginfo": "0.3.x", - "stack-trace": "0.0.x" - }, - "dependencies": { - "async": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", - "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" - }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" - }, - "pkginfo": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", - "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=" - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "ws": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", - "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==" - } - } -} diff --git a/server/package.json b/server/package.json deleted file mode 100644 index a6459d7..0000000 --- a/server/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "hack.chat-v2", - "version": "2.1.93", - "description": "a minimal distraction free chat application", - "main": "main.js", - "repository": { - "type": "git", - "url": "git+https://github.com/hack-chat/main.git" - }, - "engines": { - "node": ">= 8.10.0", - "npm": ">= 5.7.1" - }, - "scripts": { - "start": "node -r esm main.js", - "config": "node -r esm src/scripts/configure.js" - }, - "author": "Marzavec", - "license": "WTFPL", - "dependencies": { - "ascii-captcha": "0.0.3", - "chalk": "^3.0.0", - "common-tags": "^1.8.0", - "dateformat": "^3.0.3", - "didyoumean2": "^4.0.0", - "esm": "^3.2.25", - "fs-extra": "^8.1.0", - "prompt": "^1.0.0", - "readdir-recursive": "0.0.4", - "ws": "^7.2.3" - } -} diff --git a/server/src/scripts/configLib/SetupWizard.js b/server/src/scripts/configLib/SetupWizard.js deleted file mode 100644 index 3bb0823..0000000 --- a/server/src/scripts/configLib/SetupWizard.js +++ /dev/null @@ -1,115 +0,0 @@ -/* eslint no-bitwise: 0 */ -/* eslint global-require: 0 */ -/* eslint class-methods-use-this: 0 */ -/* eslint no-param-reassign: 0 */ -/* eslint no-console: 0 */ - -import { - start as _start, - get, -} from 'prompt'; - -/** - * Server setup wizard, quick server setup and all that jazz. . . - * @author Marzavec ( https://github.com/marzavec ) - * @version v2.0.0 - * @license WTFPL ( http://www.wtfpl.net/txt/copying/ ) - * @todo Convert to use the `enquirer` package instead - */ -class SetupWizard { - /** - * Create a `SetupWizard` instance for initializing the server's config.json - * @param {Object} serverConfig reference to the server config class - */ - constructor(serverConfig) { - this.serverConfig = serverConfig; - } - - /** - * Roll a d20 and begin the wizarding process - */ - async start() { - // load the current config to use as defaults, if available - 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(() => (~~(Math.random() * 36)).toString(36)).join(''); - - // load the setup questions & set their defaults - const questions = require('../setupSchema/Questions.js'); - questions.properties = this.setQuestionDefaults(questions.properties, currentConfig); - - // force password re-entry - questions.properties.adminTrip.default = ''; - questions.properties.adminTrip.required = true; - - // output the packages setup banner - require('../setupSchema/Banner.js'); - - // let's start playing 20 questions - _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) => { - if (typeof currentConfig[qName] !== 'undefined') { - questions[qName].default = currentConfig[qName]; - questions[qName].required = false; - } else { - questions[qName].required = true; - } - }); - - return questions; - } - - /** - * Looks like all the questions have been answered, check for errors or save - * the new config file - * - * @param {Object} err any errors generated by Prompt - * @param {Object} result the answers / new config setup - */ - async finalize(err, result) { - // output errors and die if needed - if (err) { - console.error(err); - process.exit(0); - } - - // initialize default mods config - 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') { - result.logErrDetailed = false; - } - - // finally create the actual JSON file - try { - this.serverConfig.config = result; - await this.serverConfig.save(); - } catch (e) { - console.error(`Couldn't write config to ${this.serverConfig.configPath} - ${e.stack}`); - } - - // output the packages final notice before quitting - require('../setupSchema/Footer.js'); - - process.exit(0); - } -} - -export default SetupWizard; diff --git a/server/src/scripts/configure.js b/server/src/scripts/configure.js deleted file mode 100644 index d96e0df..0000000 --- a/server/src/scripts/configure.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Server configuration script, to (re)configure server options - * @author Marzavec ( https://github.com/marzavec ) - * @version v2.0.0 - * @license WTFPL ( http://www.wtfpl.net/txt/copying/ ) - */ - -// import required classes -import { join } from 'path'; -import ConfigManager from '../serverLib/ConfigManager'; -import SetupWizard from './configLib/SetupWizard'; - -// import and initialize configManager & dependencies -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 deleted file mode 100644 index 5bb2066..0000000 --- a/server/src/scripts/setupSchema/Banner.js +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint no-console: 0 */ - -/** - * This script will be run before the package starts asking for the config data, - * used to output a simple guide for the coming questions, or to spam some sexy - * ascii art at the user. - * - */ - -import { stripIndents } from 'common-tags'; -import chalk from 'chalk'; - -// gotta have that sexy console -console.log(stripIndents` - ${chalk.magenta('°º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸°º¤ø,¸¸,ø¤º°`°º¤ø')} - ${chalk.gray('--------------(') + chalk.white(' HackChat Setup Wizard v2.0 ') + chalk.gray(')--------------')} - ${chalk.magenta('°º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸°º¤ø,¸¸,ø¤º°`°º¤ø')} - - For advanced setup, see the documentation at: - ${chalk.green('https://github.com/hack-chat/main/tree/master/documentation')} - - ${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 - \u200b -`); diff --git a/server/src/scripts/setupSchema/Footer.js b/server/src/scripts/setupSchema/Footer.js deleted file mode 100644 index 98b65a5..0000000 --- a/server/src/scripts/setupSchema/Footer.js +++ /dev/null @@ -1,11 +0,0 @@ -/* eslint no-console: 0 */ - -/** - * This script will be run once all questions have finished and no errors have - * occured. You can congratulate the user on their fine choice in software usage - * - */ - -console.log(''); -console.log('Config generated! You may now start the server normally.'); -console.log(''); diff --git a/server/src/scripts/setupSchema/Questions.js b/server/src/scripts/setupSchema/Questions.js deleted file mode 100644 index b62834f..0000000 --- a/server/src/scripts/setupSchema/Questions.js +++ /dev/null @@ -1,58 +0,0 @@ -/* eslint no-undef: 0 */ -/* eslint global-require: 0 */ - -/** - * This object contains Prompt ( https://www.npmjs.com/package/prompt ) style - * questions that the SetupWizard will require an answer to. Questions are asked - * in the order they are specified here. - * - * The resulting config.json file will be used by the server, accessed by the - * name specified. IE, a valid use is; config.adminName - * - */ - -const Questions = { - properties: { - tripSalt: { - description: 'Salt (leave as default)', - type: 'string', - hidden: true, - replace: '*', - before: (value) => { - salt = value; - return value; - }, - }, - - adminName: { - description: 'Admin Nickname', - pattern: /^"?[a-zA-Z0-9_]+"?$/, - type: 'string', - message: 'Nicks can only contain letters, numbers and underscores', - before: (value) => value.replace(/"/g, ''), - }, - - adminTrip: { - type: 'string', - hidden: true, - replace: '*', - description: 'Admin Password', - message: 'You must enter or re-enter a password', - before: (value) => { - const crypto = require('crypto'); - 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', - }, - }, -}; - -module.exports = Questions; diff --git a/server/src/serverLib/CommandManager.js b/server/src/serverLib/CommandManager.js deleted file mode 100644 index c1d9426..0000000 --- a/server/src/serverLib/CommandManager.js +++ /dev/null @@ -1,313 +0,0 @@ -/* eslint no-console: 0 */ - -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) { - /** - * 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 = []; - - /** - * 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() { - this.commands = []; - this.categories = []; - - const commandImports = this.core.dynamicImports.getImport(CmdDir); - let cmdErrors = ''; - Object.keys(commandImports).forEach((file) => { - const command = commandImports[file]; - const name = basename(file); - cmdErrors += this.validateAndLoad(command, file, name); - }); - - return cmdErrors; - } - - /** - * 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) { - const error = this.validateCommand(command); - - if (error) { - const errText = `Failed to load command module '${name}': ${error}`; - console.log(errText); - return errText; - } - - if (!command.category) { - const base = join(this.core.dynamicImports.base, 'commands'); - - let category = 'Uncategorized'; - if (file.indexOf(sep) > -1) { - category = dirname(relative(base, file)) - .replace(new RegExp(sep.replace('\\', '\\\\'), 'g'), '/'); - } - - // eslint-disable-next-line no-param-reassign - command.info.category = category; - - if (this.categories.indexOf(category) === -1) { - this.categories.push(category); - } - } - - if (typeof command.init === 'function') { - try { - command.init(this.core); - } catch (err) { - const errText = `Failed to initialize '${name}': ${err}`; - console.log(errText); - return errText; - } - } - - this.commands.push(command); - - return ''; - } - - /** - * 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 - */ - // eslint-disable-next-line class-methods-use-this - 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) { - return !category ? this.commands : this.commands.filter( - (c) => c.info.category.toLowerCase() === category.toLowerCase(), - ); - } - - /** - * All category names - * @public - * @readonly - * @return {Array} Array of command category names - */ - get categoriesList() { - return this.categories; - } - - /** - * Pulls command by name or alias - * @param {String} name name or alias of command - * @public - * @return {Object} Target command module object - */ - get(name) { - return this.findBy('name', name) - || this.commands.find( - (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); - } - - /** - * 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), - ); - } - - /** - * 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) { - // Try to find command first - const command = this.get(data.cmd); - - if (command) { - return this.execute(command, 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), { - threshold: 5, - thresholdType: 'edit-distance', - }); - - if (maybe) { - // Found a suggestion, pass it on to their dyslexic self - return this.handleCommand(server, socket, { - cmd: 'socketreply', - cmdKey: server.cmdKey, - text: `Command not found, did you mean: \`${maybe}\`?`, - }); - } - - // Request so mangled that I don't even. . . - return this.handleCommand(server, socket, { - cmd: 'socketreply', - cmdKey: server.cmdKey, - 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, payload) { - if (typeof command.requiredData !== 'undefined') { - const missing = []; - for (let i = 0, len = command.requiredData.length; i < len; i += 1) { - if (typeof payload[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`); - - this.handleCommand(server, socket, { - cmd: 'socketreply', - cmdKey: server.cmdKey, - text: `Failed to execute '${ - command.info.name - }': missing required ${missing.join(', ')}\n\n`, - }); - - return null; - } - } - - try { - return await command.run({ - core: this.core, - server, - socket, - payload, - }); - } catch (err) { - 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()); - } - - this.handleCommand(server, socket, { - cmd: 'socketreply', - cmdKey: server.cmdKey, - text: errText + err.toString(), - }); - - return null; - } - } -} - -export default CommandManager; diff --git a/server/src/serverLib/ConfigManager.js b/server/src/serverLib/ConfigManager.js deleted file mode 100644 index 85224f1..0000000 --- a/server/src/serverLib/ConfigManager.js +++ /dev/null @@ -1,105 +0,0 @@ -/* eslint no-console: 0 */ - -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 - * @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/ ) - */ -class ConfigManager { - /** - * Create a `ConfigManager` instance for managing application settings - * @param {String} basePath executing directory name; __dirname - */ - constructor(basePath = __dirname) { - /** - * Full path to config.json file - * @type {String} - */ - this.configPath = resolve(basePath, 'config/config.json'); - - if (!existsSync(this.configPath)) { - ensureFileSync(this.configPath); - } - } - - /** - * Loads config.json (main server config) into memory - * @public - * @return {(JSON|Boolean)} False if the config.json could not be loaded - */ - async load() { - try { - this.config = readJsonSync(this.configPath); - } catch (e) { - return false; - } - - return this.config; - } - - /** - * Creates backup of current config into configPath - * @private - * @return {String} Backed up config.json path - */ - backup() { - const backupPath = `${this.configPath}.${dateFormat('dd-mm-yy-HH-MM-ss')}.bak`; - copySync(this.configPath, backupPath); - - return backupPath; - } - - /** - * First makes a backup of the current `config.json`, then writes current config - * to disk - * @public - * @return {Boolean} False on failure - */ - save() { - const backupPath = this.backup(); - - try { - writeJSONSync(this.configPath, this.config, { - // Indent with two spaces - spaces: 2, - }); - removeSync(backupPath); - - return true; - } catch (err) { - console.log(`Failed to save config file: ${err}`); - - return false; - } - } - - /** - * 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 - */ - set(key, value) { - const realKey = `${key}`; - this.config[realKey] = value; - - return this.save(); - } -} - -export default ConfigManager; diff --git a/server/src/serverLib/CoreApp.js b/server/src/serverLib/CoreApp.js deleted file mode 100644 index 5fb7233..0000000 --- a/server/src/serverLib/CoreApp.js +++ /dev/null @@ -1,95 +0,0 @@ -/* eslint no-console: 0 */ - -import { join } from 'path'; -import { - CommandManager, - ConfigManager, - ImportsManager, - MainServer, - 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 { - /** - * Load config then initialize children - * @public - * @return {void} - */ - async init() { - await this.buildConfigManager(); - - this.buildImportManager(); - this.buildCommandsManager(); - this.buildStatsManager(); - this.buildMainServer(); - } - - /** - * 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) { - console.error('Missing config.json, have you run: npm run config'); - process.exit(0); - } - } - - /** - * Creates a new instance of the ImportsManager - * @private - * @return {void} - */ - buildImportManager() { - this.dynamicImports = new ImportsManager(join(__dirname, '../..')); - } - - /** - * Creates a new instance of the CommandManager and loads the command modules - * @private - * @return {void} - */ - buildCommandsManager() { - this.commands = new CommandManager(this); - this.commands.loadCommands(); - } - - /** - * 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()); - } - - /** - * Creates a new instance of the MainServer - * @private - * @return {void} - */ - buildMainServer() { - this.server = new MainServer(this); - } -} - -export { CoreApp as default }; diff --git a/server/src/serverLib/ImportsManager.js b/server/src/serverLib/ImportsManager.js deleted file mode 100644 index ac429a0..0000000 --- a/server/src/serverLib/ImportsManager.js +++ /dev/null @@ -1,124 +0,0 @@ -/* eslint global-require: 0 */ -/* eslint no-console: 0 */ - -import { - resolve, - basename as _basename, - relative, -} from 'path'; -import RecursiveRead from 'readdir-recursive'; - -/** - * Import managment base, used to load commands/protocol and configuration objects - * @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/ ) - */ -class ImportsManager { - /** - * Create an `ImportsManager` instance for (re)loading classes and config - * @param {String} basePath executing directory name; default __dirname - */ - 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() { - 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 - * @private - * @return {String} Load errors or empty if none - */ - loadDir(dirName) { - const dir = resolve(this.basePath, dirName); - - let errorText = ''; - try { - RecursiveRead.fileSync(dir).forEach((file) => { - const basename = _basename(file); - if (basename.startsWith('_') || !basename.endsWith('.js')) return; - - let imported; - try { - imported = require(file); // eslint-disable-line import/no-dynamic-require - - if (!this.imports[dirName]) { - this.imports[dirName] = {}; - } - - this.imports[dirName][file] = imported; - } catch (e) { - const err = `Unable to load modules from ${dirName} (${relative(dir, file)})\n${e}`; - errorText += err; - console.error(err); - } - }); - } catch (e) { - const err = `Unable to load modules from ${dirName}\n${e}`; - errorText += err; - console.error(err); - return errorText; - } - - return errorText; - } - - /** - * Unlink references to each loaded module, pray to google that gc knows it's job, - * then reinitialize this class to start the reload - * @public - * @return {String} Load errors or empty if none - */ - reloadDirCache() { - let errorText = ''; - - Object.keys(this.imports).forEach((dir) => { - Object.keys(this.imports[dir]).forEach((mod) => { - delete require.cache[require.resolve(mod)]; - }); - - errorText += this.loadDir(dir); - }); - - return errorText; - } - - /** - * 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) { - const imported = this.imports[dirName]; - - if (!imported) { - this.loadDir(dirName); - } - - return { ...this.imports[dirName] }; - } -} - -export default ImportsManager; diff --git a/server/src/serverLib/MainServer.js b/server/src/serverLib/MainServer.js deleted file mode 100644 index 745507d..0000000 --- a/server/src/serverLib/MainServer.js +++ /dev/null @@ -1,548 +0,0 @@ -/* eslint no-bitwise: 0 */ -/* eslint no-console: 0 */ - -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 - * @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/ ) - */ -class MainServer extends WsServer { - /** - * 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} - * @public - * @readonly - */ - get cmdKey() { - return this.internalCmdKey; - } - - /** - * Create ping interval and setup server event listeners - * @private - * @return {void} - */ - setupServer() { - this.heartBeat = setInterval(() => this.beatHeart(), ServerConst.PulseSpeed); - - this.on('error', (err) => { - this.handleError(err); - }); - - this.on('connection', (socket, request) => { - this.newConnection(socket, request); - }); - } - - /** - * Send empty `ping` frame to each client - * @private - * @return {void} - */ - beatHeart() { - const targetSockets = this.findSockets({}); - - if (targetSockets.length === 0) { - return; - } - - for (let i = 0, l = targetSockets.length; i < l; i += 1) { - try { - if (targetSockets[i].readyState === SocketReady) { - targetSockets[i].ping(); - } - } catch (e) { /* yolo */ } - } - } - - /** - * Bind listeners for the new socket created on connection to this class - * @param {ws#WebSocket} socket New socket object - * @param {Object} request Initial headers of the new connection - * @private - * @return {void} - */ - newConnection(socket, request) { - const newSocket = socket; - - newSocket.address = request.headers['x-forwarded-for'] || request.connection.remoteAddress; - - newSocket.on('message', (data) => { - this.handleData(socket, data); - }); - - newSocket.on('close', () => { - this.handleClose(socket); - }); - - newSocket.on('error', (err) => { - this.handleError(err); - }); - } - - /** - * Handle incoming messages from clients, parse and check command, then hand-off - * @param {ws#WebSocket} socket Calling socket object - * @param {String} data Message sent from client - * @private - * @return {void} - */ - handleData(socket, data) { - // Don't penalize yet, but check whether IP is rate-limited - 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.', - }); - - return; - } - - // Penalize here, but don't do anything about it - this.police.frisk(socket.address, 1); - - // Ignore ridiculously large packets - if (data.length > 65536) { - return; - } - - // Start sent data verification - let payload = null; - try { - payload = JSON.parse(data); - } catch (e) { - // Client sent malformed json, gtfo - socket.close(); - } - - if (payload === null) { - return; - } - - /** - * @todo make the following more flexible - * Issue #1: hard coded `cmd` check - * Issue #2: hard coded `cmd` value checks - */ - if (typeof payload.cmd !== 'string') { - return; - } - - if (typeof socket.channel === 'undefined' && (payload.cmd !== 'join' && payload.cmd !== 'session' && payload.cmd !== 'chat')) { - return; - } - - if (typeof this.cmdBlacklist[payload.cmd] === 'function') { - return; - } - // End @todo // - - // Execute `in` (incoming data) hooks and process results - payload = this.executeHooks('in', socket, payload); - - if (typeof payload === 'string') { - // A hook malfunctioned, reply with error - this.core.commands.handleCommand(this, socket, { - cmd: 'socketreply', - cmdKey: this.cmdKey, - text: payload, - }); - - return; - } if (payload === false) { - // A hook requested this data be dropped - return; - } - - // Finished verification & hooks, pass to command modules - this.core.commands.handleCommand(this, socket, payload); - } - - /** - * Pass socket close event to disconnection command module - * @param {ws#WebSocket} socket Closing socket object - * @private - * @return {void} - */ - handleClose(socket) { - this.core.commands.handleCommand(this, socket, { - cmd: 'disconnect', - cmdKey: this.cmdKey, - }); - } - - /** - * "Handle" server or socket errors - * @param {ErrorEvent} err The sad stuff - * @private - * @return {void} - */ - 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 {ws#WebSocket} socket The target client - * @example - * server.send({ - * cmd: 'info', - * text: 'Only targetSocket will see this' - * }, targetSocket); - * @public - * @return {void} - */ - send(payload, socket) { - let outgoingPayload = payload; - - // Add timestamp to command - outgoingPayload.time = Date.now(); - - // Execute `in` (incoming data) hooks and process results - outgoingPayload = this.executeHooks('out', socket, outgoingPayload); - - if (typeof outgoingPayload === 'string') { - // A hook malfunctioned, reply with error - this.core.commands.handleCommand(this, socket, { - cmd: 'socketreply', - cmdKey: this.cmdKey, - text: outgoingPayload, - }); - - return; - } if (outgoingPayload === false) { - // A hook requested this data be dropped - return; - } - - try { - if (socket.readyState === SocketReady) { - socket.send(JSON.stringify(outgoingPayload)); - } - } catch (e) { console.error(e); } - } - - /** - * Overload function for `this.send()` - * @param {Object} payload Object to convert to json for transmission - * @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) { - 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) { - const targetSockets = this.findSockets(filter); - - if (targetSockets.length === 0) { - return false; - } - - for (let i = 0, l = targetSockets.length; i < l; i += 1) { - this.send(payload, targetSockets[i]); - } - - return true; - } - - /** - * 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` - * @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) { - const filterAttribs = Object.keys(filter); - const reqCount = filterAttribs.length; - let curMatch; - const matches = []; - this.clients.forEach((socket) => { - // for (const socket of this.clients) { - curMatch = 0; - - for (let i = 0; i < reqCount; i += 1) { - if (typeof socket[filterAttribs[i]] !== 'undefined') { - switch (typeof filter[filterAttribs[i]]) { - case 'object': { - if (Array.isArray(filter[filterAttribs[i]])) { - if (filter[filterAttribs[i]].indexOf(socket[filterAttribs[i]]) !== -1) { - curMatch += 1; - } - } else if (socket[filterAttribs[i]] === filter[filterAttribs[i]]) { - curMatch += 1; - } - break; - } - - case 'function': { - if (filter[filterAttribs[i]](socket[filterAttribs[i]])) { - curMatch += 1; - } - break; - } - - default: { - if (socket[filterAttribs[i]] === filter[filterAttribs[i]]) { - curMatch += 1; - } - break; - } - } - } - } - - if (curMatch === reqCount) { - matches.push(socket); - } - }); - - return matches; - } - - /** - * Hashes target socket's remote address using non-static variable length salt - * encodes and shortens the output, returns that value - * @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) { - const sha = createHash('sha256'); - - if (typeof target === 'string') { - sha.update(target + this.ipSalt); - } else { - sha.update(target.address + this.ipSalt); - } - - return sha.digest('base64').substr(0, 15); - } - - /** - * (Re)loads all command module hooks, then sorts their order of operation by - * priority, ascending (0 being highest priority) - * @public - * @return {void} - */ - loadHooks() { - // clear current hooks (if any) - this.clearHooks(); - // notify each module to register their hooks (if any) - this.core.commands.initCommandHooks(this); - - let curHooks = []; - let hookObj = []; - - 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 += 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') { - // then outgoing - 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); - } - } - } - - /** - * 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 - * @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 = 25) { - if (typeof this.hooks[type] === 'undefined') { - this.hooks[type] = new Map(); - } - - if (!this.hooks[type].has(command)) { - this.hooks[type].set(command, []); - } - - this.hooks[type].get(command).push({ - run: hookFunction, - priority, - }); - } - - /** - * Loops through registered hooks & processes the results. Returned data will - * be one of three possiblities: - * 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 {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`) - * @public - * @return {Object|Boolean} - */ - executeHooks(type, socket, payload) { - const command = payload.cmd; - let newPayload = payload; - - if (typeof this.hooks[type] !== 'undefined') { - if (this.hooks[type].has(command)) { - const hooks = this.hooks[type].get(command); - - for (let i = 0, j = hooks.length; i < j; i += 1) { - try { - newPayload = hooks[i].run({ - core: this.core, - server: this, - socket, - payload: newPayload, - }); - } catch (err) { - const errText = `Hook failure, '${type}', '${command}': `; - if (this.core.config.logErrDetailed === true) { - console.log(errText + err.stack); - } else { - console.log(errText + err.toString()); - } - return errText + err.toString(); - } - - // A hook function may choose to return false to prevent all further processing - if (newPayload === false) { - return false; - } - } - } - } - - return newPayload; - } - - /** - * Wipe server hooks to make ready for module reload calls - * @public - * @return {void} - */ - clearHooks() { - this.hooks = {}; - } -} - -export default MainServer; diff --git a/server/src/serverLib/RateLimiter.js b/server/src/serverLib/RateLimiter.js deleted file mode 100644 index 9e526b7..0000000 --- a/server/src/serverLib/RateLimiter.js +++ /dev/null @@ -1,139 +0,0 @@ -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` - * @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() { - /** - * Data holder rate limit records - * @type {Object} - */ - this.records = {}; - - /** - * 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) { - let record = this.records[id]; - - if (!record) { - this.records[id] = { - time: Date.now(), - score: 0, - }; - - record = this.records[id]; - } - - return record; - } - - /** - * 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) { - const record = this.search(id); - - if (record.arrested) { - return true; - } - - // eslint-disable-next-line no-restricted-properties - record.score *= Math.pow(2, -(Date.now() - record.time) / this.halflife); - record.score += deltaScore; - record.time = Date.now(); - - if (record.score >= this.threshold) { - return true; - } - - return false; - } - - /** - * 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) { - const record = this.search(id); - - record.arrested = true; - this.hashes[hash] = id; - } - - /** - * 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) { - let targetId = id; - if (typeof this.hashes[targetId] !== 'undefined') { - targetId = this.hashes[targetId]; - } - - const record = this.search(targetId); - record.arrested = false; - } - - /** - * Clear all records - * @public - * @return {void} - */ - clear() { - this.records = {}; - this.hashes = []; - } -} - -export default RateLimiter; diff --git a/server/src/serverLib/StatsManager.js b/server/src/serverLib/StatsManager.js deleted file mode 100644 index b6e4f97..0000000 --- a/server/src/serverLib/StatsManager.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Simple generic stats collection script for events occurances (etc) - * @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 - */ - 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) { - 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) { - 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=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 = 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=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 = 1) { - this.set(key, (this.get(key) || 0) - amount); - } -} - -module.exports = StatsManager; diff --git a/server/src/serverLib/index.js b/server/src/serverLib/index.js deleted file mode 100644 index 21cfa14..0000000 --- a/server/src/serverLib/index.js +++ /dev/null @@ -1,8 +0,0 @@ -/* eslint global-require: 0 */ - -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 deleted file mode 100644 index 6836421..0000000 --- a/server/src/utility/Constants.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * 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, -}; diff --git a/test/addmod.test.js b/test/addmod.test.js new file mode 100644 index 0000000..fb32def --- /dev/null +++ b/test/addmod.test.js @@ -0,0 +1,78 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/admin/addmod.js'; +let importedModule; + +const mockPayload = { + cmd: 'addmod', + trip: 'newTrip', +} + +describe('Checking addmod module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by an admin', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should add new trip to the config', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(mocks.core.appConfig.data.globalMods[0].trip).to.equal(mockPayload.trip); + }); + + it('should inform the new mod', async () => { + mocks.server.findSockets = () => { + return [{}]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + mocks.core.appConfig.data.globalMods = []; + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/ban.test.js b/test/ban.test.js new file mode 100644 index 0000000..99af113 --- /dev/null +++ b/test/ban.test.js @@ -0,0 +1,145 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/mod/ban.js'; +let importedModule; + +const mockPayload = { + cmd: 'ban', + userid: 1234, +} + +describe('Checking ban module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by a mod', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should check for invalid legacy params', async () => { + mocks.authedSocket.hcProtocol = 1; + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should verify legacy params', async () => { + mocks.authedSocket.hcProtocol = 1; + mockPayload.nick = 5431; + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should accept legacy params', async () => { + mocks.authedSocket.hcProtocol = 1; + mockPayload.nick = 'lies'; + mocks.server.findSockets = (filterObj) => { + return false; + } + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should check for invalid params', async () => { + mocks.authedSocket.hcProtocol = 2; + mockPayload.userid = 'test'; + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should not ban mods', async () => { + mocks.authedSocket.hcProtocol = 2; + mockPayload.userid = 1234; + + mocks.server.findSockets = (filterObj) => { + return [mocks.authedSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should blacklist the ip', async () => { + mocks.authedSocket.hcProtocol = 2; + mockPayload.userid = 1234; + + mocks.server.findSockets = (filterObj) => { + if (typeof filterObj.level === 'function') { + filterObj.level(); + } + + return [mocks.plebSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(mocks.server.police.addresses[0]).to.be.a('string'); + }); + +}); \ No newline at end of file diff --git a/test/changecolor.test.js b/test/changecolor.test.js new file mode 100644 index 0000000..47500bb --- /dev/null +++ b/test/changecolor.test.js @@ -0,0 +1,126 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/changecolor.js'; +let importedModule; + +const mockPayload = { + cmd: 'changecolor', + color: '#000000', +} + +describe('Checking changecolor module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should ratelimit if required', async () => { + const oldRL = mocks.server.police.frisk; + mocks.server.police.frisk = () => true; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + mocks.server.police.frisk = oldRL; + + expect(resp).to.be.true; + }); + + it('should be invokable by all', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should check for invalid color type', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'changecolor', + color: false, + }, + }); + + expect(resp).to.be.false; + }); + + it('should check for invalid color', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'changecolor', + color: 'This is an invalid color', + }, + }); + + expect(resp).to.be.true; + }); + + it('should allow a color reset', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'changecolor', + color: 'reset', + }, + }); + + expect(resp).to.be.true; + }); + + it('should initialize hooks', async () => { + expect(() => importedModule.initHooks(mocks.server)).not.to.throw(); + }); + + it('should hook chat text to register /color', async () => { + const resp = importedModule.colorCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'changecolor', + color: 'reset', + }, + }); + + expect(resp).to.be.false; + }); +}); \ No newline at end of file diff --git a/test/changenick.test.js b/test/changenick.test.js new file mode 100644 index 0000000..cdc6c39 --- /dev/null +++ b/test/changenick.test.js @@ -0,0 +1,253 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/changenick.js'; +let importedModule; + +const mockPayload = { + cmd: 'changenick', + nick: 'newNick', +} + +describe('Checking changenick module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should ratelimit if required', async () => { + const oldRL = mocks.server.police.frisk; + mocks.server.police.frisk = () => true; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + mocks.server.police.frisk = oldRL; + + expect(resp).to.be.true; + }); + + it('should validate nick param', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'changenick', + nick: 1234, + }, + }); + + expect(resp).to.be.true; + }); + + it('should verify nick param', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'changenick', + nick: 'this is invalid', + }, + }); + + expect(resp).to.be.true; + }); + + it('should be invokable by all', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should prevent admin impersonation', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'changenick', + nick: 'admin', + }, + }); + + expect(resp).to.be.true; + }); + + it('should not update if there is no change', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'changenick', + nick: 'lies', + }, + }); + + expect(resp).to.be.true; + }); + + it('should allow them to change case', async () => { + const origFindSockets = mocks.server.findSockets; + mocks.server.findSockets = (filterObj) => { + if (typeof filterObj.nick === 'function') { + filterObj.nick('lies'); + } + + return [mocks.plebSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'changenick', + nick: 'Lies', + }, + }); + + mocks.server.findSockets = origFindSockets; + + expect(resp).to.be.true; + }); + + it('should not update if that nick exists', async () => { + const origFindSockets = mocks.server.findSockets; + mocks.server.findSockets = (filterObj) => { + if (typeof filterObj.nick === 'function') { + filterObj.nick('lies'); + } + + return [mocks.plebSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + mocks.server.findSockets = origFindSockets; + + expect(resp).to.be.true; + }); + + it('should output new user details to the channel', async () => { + const origFindSockets = mocks.server.findSockets; + const legacySocket = Object.assign({}, mocks.plebSocket); + legacySocket.hcProtocol = 1; + mocks.server.findSockets = (data) => { + if (typeof data.nick !== 'undefined' ) { + return []; + } + + return [mocks.plebSocket, legacySocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + mocks.server.findSockets = origFindSockets; + + expect(resp).to.be.true; + }); + + it('should initialize hooks', async () => { + expect(() => importedModule.initHooks(mocks.server)).not.to.throw(); + }); + + it('should hook should validate text input', async () => { + const resp = importedModule.nickCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: false, + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook should verify text starts with /nick', async () => { + const resp = importedModule.nickCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: 'No slash command', + }, + }); + + expect(resp).to.be.an('object'); + }); + + it('should hook should run with /nick', async () => { + const resp = importedModule.nickCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: '/nick test', + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook fail on mangled input', async () => { + const resp = importedModule.nickCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: '/nick ', + }, + }); + + expect(resp).to.be.false; + }); +}); \ No newline at end of file diff --git a/test/channels.test.js b/test/channels.test.js new file mode 100644 index 0000000..a4587b3 --- /dev/null +++ b/test/channels.test.js @@ -0,0 +1,65 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/utility/_Channels.js'; +let importedModule; + +describe('Checking channels module', () => { + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should reject empty channels', async () => { + const resp = importedModule.canJoinChannel('', {}); + expect(resp).to.be.a('number'); + }); + + it('should reject too long of channels', async () => { + const resp = importedModule.canJoinChannel('a'.repeat(121), {}); + expect(resp).to.be.a('number'); + }); + + it('should get channel data', async () => { + const newConfig = Object.assign({}, mocks.core.appConfig.data); + newConfig.permissions['test'] = {}; + const resp = importedModule.getChannelSettings(mocks.core.appConfig.data, 'test'); + expect(resp).to.be.an('object'); + }); + + it('should return empty array findUsers', async () => { + const resp = importedModule.findUsers({}, {}); + expect(resp).to.be.an('array'); + }); + + it('should limit results', async () => { + const oldFS = mocks.server.findSockets; + mocks.server.findSockets = (filterObj) => { + return [1, 2, 3]; + } + const resp = importedModule.findUsers(mocks.server, { + userid: 1234, + }, 1); + + mocks.server.findSockets = oldFS; + + expect(resp).to.be.an('array'); + }); + + it('should respond to banned sockets', async () => { + const newSocket = Object.assign({}, mocks.plebSocket); + newSocket.banned = true; + + const resp = importedModule.canJoinChannel('test', newSocket); + + expect(resp).to.be.an('number'); + }); + + it('should provide duplicate user checks', async () => { + const newSocket = Object.assign({}, mocks.plebSocket); + + const resp = importedModule.socketInChannel(mocks.server, 'test', newSocket); + + expect(resp).to.be.an('object'); + }); +}) \ No newline at end of file diff --git a/test/chat.test.js b/test/chat.test.js new file mode 100644 index 0000000..9615572 --- /dev/null +++ b/test/chat.test.js @@ -0,0 +1,198 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/chat.js'; +let importedModule; + +const mockPayload = { + cmd: 'chat', + channel: 'cake', + text: 'testing', +} + +describe('Checking chat module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable by all', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should ratelimit on invalid text', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + channel: 'cake', + text: [], + }, + }); + + expect(resp).to.be.false; + }); + + it('should ratelimit if required', async () => { + const oldRL = mocks.server.police.frisk; + mocks.server.police.frisk = () => true; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + mocks.server.police.frisk = oldRL; + + expect(resp).to.be.true; + }); + + it('should add sender admin label', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should add sender mod label', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.level = 999999; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should add color', async () => { + const newSocket = Object.assign({}, mocks.plebSocket); + newSocket.color = '000000'; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should initialize hooks', async () => { + expect(() => importedModule.initHooks(mocks.server)).not.to.throw(); + }); + + it('should hook for / based commands', async () => { + const resp = importedModule.commandCheckIn({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.an('object'); + }); + + it('should validate hook text param', async () => { + const resp = importedModule.commandCheckIn({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + channel: 'cake', + text: false, + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook for /myhash', async () => { + const resp = importedModule.commandCheckIn({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + channel: 'cake', + text: '/myhash', + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook for failed / commands, validating text input', async () => { + const resp = importedModule.finalCmdCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + channel: 'cake', + text: false, + }, + }); + + expect(resp).to.be.false; + }); + + it('should final hook should ignore if input doesnt start with /', async () => { + const resp = importedModule.finalCmdCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + channel: 'cake', + text: 'test', + }, + }); + + expect(resp).to.be.an('object'); + }); +}); \ No newline at end of file diff --git a/test/disconnect.test.js b/test/disconnect.test.js new file mode 100644 index 0000000..3ccdf18 --- /dev/null +++ b/test/disconnect.test.js @@ -0,0 +1,80 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/internal/disconnect.js'; +let importedModule; + +const mockPayload = { + cmd: 'disconnect', +} + +describe('Checking disconnect module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only internally', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should broadcast online remove event', async () => { + mockPayload.cmdKey = 'test'; + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should not broadcast online remove event if there is a duplicate', async () => { + const origFindSockets = mocks.server.findSockets; + mocks.server.findSockets = (data) => { + return []; + } + + mockPayload.cmdKey = 'test'; + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + mocks.server.findSockets = origFindSockets; + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/dumb.test.js b/test/dumb.test.js new file mode 100644 index 0000000..2c463c3 --- /dev/null +++ b/test/dumb.test.js @@ -0,0 +1,366 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/mod/dumb.js'; +let importedModule; + +const mockPayload = { + cmd: 'dumb', + nick: 'nick', + channel: 'cake', + userid: 1234, + allies: [], +} + +describe('Checking dumb module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module export functions + it('should export a random channel function', async () => { + const resp = importedModule.getChannel(); + + expect(resp).to.be.a('string'); + }); + + it('should export a common channel function', async () => { + const resp = importedModule.getChannel('common'); + + expect(resp).to.be.a('string'); + }); + + it('should initialize', async () => { + mocks.core.muzzledHashes = undefined; + const resp = importedModule.init(mocks.core); + + expect(mocks.core.muzzledHashes).to.be.an('object'); + }); + + it('should initialize hooks', async () => { + expect(() => importedModule.initHooks(mocks.server)).not.to.throw(); + }); + + // module main function + it('should be invokable only by a mod', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should shadow block whisper attempts', async () => { + mocks.core.muzzledHashes['testHash'] = true; + mocks.plebSocket.hcProtocol = 1; + + const resp = importedModule.whisperCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'whisper', + text: [], + channel: 'cake', + }, + }); + + expect(resp).to.be.false; + }); + + it('should shadow block chat attempts, validating input', async () => { + mocks.core.muzzledHashes['testHash'] = true; + mocks.plebSocket.hcProtocol = 1; + + const resp = importedModule.chatCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: [], + channel: 'cake', + }, + }); + + expect(resp).to.be.false; + }); + + it('should shadow block chat attempts', async () => { + mocks.core.muzzledHashes['testHash'] = true; + mocks.plebSocket.hcProtocol = 1; + + const resp = importedModule.chatCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: 'test', + channel: 'cake', + }, + }); + + expect(resp).to.be.false; + }); + + it('should shadow block chat attempts, checking for trips', async () => { + mocks.core.muzzledHashes['testHash'] = true; + mocks.plebSocket.hcProtocol = 1; + const newSocket = Object.assign({}, mocks.plebSocket); + newSocket.trip = 'test'; + + const resp = importedModule.chatCheck({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'chat', + text: 'test', + channel: 'cake', + }, + }); + + expect(resp).to.be.false; + }); + + it('should shadow block chat attempts, checking for color', async () => { + mocks.core.muzzledHashes['testHash'] = true; + mocks.plebSocket.hcProtocol = 1; + const newSocket = Object.assign({}, mocks.plebSocket); + newSocket.color = '000000'; + + const resp = importedModule.chatCheck({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'chat', + text: 'test', + channel: 'cake', + }, + }); + + expect(resp).to.be.false; + }); + + it('should shadow block chat attempts, checking for allies', async () => { + mocks.core.muzzledHashes['testHash'] = { + dumb: true, + allies: [1234], + }; + mocks.plebSocket.hcProtocol = 1; + const newSocket = Object.assign({}, mocks.plebSocket); + + const resp = importedModule.chatCheck({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'chat', + text: 'test', + channel: 'cake', + }, + }); + + expect(resp).to.be.false; + }); + + it('should shadow block invite attempts', async () => { + mocks.core.muzzledHashes['testHash'] = true; + mocks.plebSocket.hcProtocol = 1; + + const resp = importedModule.inviteCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: [], + channel: 'cake', + }, + }); + + expect(resp).to.be.true; + }); + + it('should shadow block invite attempts with ratelimiting', async () => { + const oldRL = mocks.server.police.frisk; + mocks.server.police.frisk = () => true; + + mocks.core.muzzledHashes['testHash'] = true; + mocks.plebSocket.hcProtocol = 1; + + const resp = importedModule.inviteCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: [], + channel: 'cake', + }, + }); + + mocks.server.police.frisk = oldRL; + + expect(resp).to.be.true; + }); + + it('should verify userid params on shadow block invite attempts', async () => { + mocks.core.muzzledHashes['testHash'] = true; + mocks.plebSocket.hcProtocol = 2; + + const resp = importedModule.inviteCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + userid: '1234', + text: [], + channel: 'cake', + }, + }); + + expect(resp).to.be.true; + }); + + it('should verify channel params on shadow block invite attempts', async () => { + mocks.core.muzzledHashes['testHash'] = true; + mocks.plebSocket.hcProtocol = 2; + + const resp = importedModule.inviteCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + userid: 1234, + text: [], + channel: false, + }, + }); + + expect(resp).to.be.true; + }); + + it('should accept an allies param', async () => { + mockPayload.allies = [1234, 5678]; + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should accept legacy params', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 1; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'dumb', + nick: false, + }, + }); + + expect(resp).to.be.true; + }); + + it('should accept params', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 2; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'dumb', + userid : false, + }, + }); + + expect(resp).to.be.true; + }); + + it('should handle users not found', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 2; + + const oldFS = mocks.server.findSockets; + mocks.server.findSockets = (filterObj) => { + return false; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'dumb', + userid : 0, + }, + }); + + mocks.server.findSockets = oldFS; + + expect(resp).to.be.true; + }); + + it('should not muzzle mods', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 2; + + const oldFS = mocks.server.findSockets; + mocks.server.findSockets = (filterObj) => { + return [newSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'dumb', + userid : 0, + }, + }); + + mocks.server.findSockets = oldFS; + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/emote.test.js b/test/emote.test.js new file mode 100644 index 0000000..26765c8 --- /dev/null +++ b/test/emote.test.js @@ -0,0 +1,113 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/emote.js'; +let importedModule; + +const mockPayload = { + cmd: 'emote', + channel: 'cake', + text: 'testing', +} + +describe('Checking emote module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable by all', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should not accept empty text', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'emote', + text: false, + }, + }); + + expect(resp).to.be.false; + }); + + it('should ratelimit if required', async () => { + const oldRL = mocks.server.police.frisk; + mocks.server.police.frisk = () => true; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + mocks.server.police.frisk = oldRL; + + expect(resp).to.be.true; + }); + + it('should include a users trip', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.trip = 'test'; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should initialize hooks', async () => { + expect(() => importedModule.initHooks(mocks.server)).not.to.throw(); + }); + + it('should hook a /me text command, verifying params', async () => { + const resp = importedModule.emoteCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'chat', + text: false, + }, + }); + + expect(resp).to.be.false; + }); +}); \ No newline at end of file diff --git a/test/forcecolor.test.js b/test/forcecolor.test.js new file mode 100644 index 0000000..be00c1d --- /dev/null +++ b/test/forcecolor.test.js @@ -0,0 +1,194 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/mod/forcecolor.js'; +let importedModule; + +const mockPayload = { + cmd: 'forcecolor', + userid: 1234, + color: '#000000', +} + +describe('Checking forcecolor module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by a mod', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should check for invalid nick', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'changecolor', + nick: false, + color: false, + }, + }); + + expect(resp).to.be.true; + }); + + it('should check for invalid color', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'changecolor', + nick: 'lies', + color: false, + }, + }); + + expect(resp).to.be.true; + }); + + it('should check accept color reset', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'changecolor', + nick: 'lies', + color: 'reset', + }, + }); + + expect(resp).to.be.true; + }); + + it('should check accept color', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'changecolor', + nick: 'lies', + color: 'invalid color', + }, + }); + + expect(resp).to.be.true; + }); + + it('should handle users not found', async () => { + const oldFS = mocks.server.findSockets; + mocks.server.findSockets = (filterObj) => { + return false; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'changecolor', + nick: 'lies', + color: '#000000', + }, + }); + + mocks.server.findSockets = oldFS; + + expect(resp).to.be.true; + }); + + it('should alert to invalid user', async () => { + const oldFS = mocks.server.findSockets; + mocks.server.findSockets = (filterObj) => { + return [mocks.plebSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'changecolor', + nick: 'lies', + color: '#000000', + }, + }); + + mocks.server.findSockets = oldFS; + + expect(resp).to.be.true; + }); + + it('should not color mods', async () => { + const oldFS = mocks.server.findSockets; + mocks.server.findSockets = (filterObj) => { + return [mocks.authedSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'changecolor', + nick: 'lies', + color: '#000000', + }, + }); + + mocks.server.findSockets = oldFS; + + expect(resp).to.be.true; + }); + + it('should initialize hooks', async () => { + expect(() => importedModule.initHooks(mocks.server)).not.to.throw(); + }); + + it('should validate chat text in hook', async () => { + const resp = importedModule.colorCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'chat', + }, + }); + + expect(resp).to.be.false; + }); +}); \ No newline at end of file diff --git a/test/help.test.js b/test/help.test.js new file mode 100644 index 0000000..d1fa2fd --- /dev/null +++ b/test/help.test.js @@ -0,0 +1,182 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/help.js'; +let importedModule; + +const mockPayload = { + cmd: 'help', + channel: 'cake', +} + +describe('Checking help module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable by all', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should ratelimit if required', async () => { + const oldRL = mocks.server.police.frisk; + mocks.server.police.frisk = () => true; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + mocks.server.police.frisk = oldRL; + + expect(resp).to.be.true; + }); + + it('should verify user input', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'help', + command: false, + }, + }); + + expect(resp).to.be.true; + }); + + it('should output over view', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'help', + }, + }); + + expect(resp).to.be.true; + }); + + it('should output specific info', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'help', + command: 'test', + }, + }); + + expect(resp).to.be.true; + }); + + it('should handle unknown commands', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'help', + command: 'undef', + }, + }); + + expect(resp).to.be.true; + }); + + it('should handle unknown aliases', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'help', + command: 'noalias', + }, + }); + + expect(resp).to.be.true; + }); + + it('should initialize hooks', async () => { + expect(() => importedModule.initHooks(mocks.server)).not.to.throw(); + }); + + it('should hook /help, verify params', async () => { + const resp = importedModule.helpCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: false, + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook /help', async () => { + const resp = importedModule.helpCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: '/help', + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook /help', async () => { + const resp = importedModule.helpCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: 'no cmd', + }, + }); + + expect(resp).to.be.an('object'); + }); + +}); \ No newline at end of file diff --git a/test/invite.test.js b/test/invite.test.js new file mode 100644 index 0000000..e590371 --- /dev/null +++ b/test/invite.test.js @@ -0,0 +1,230 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/invite.js'; +let importedModule; + +const mockPayload = { + cmd: 'invite', + channel: 'cake', + text: 'testing', +} + +describe('Checking invite module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module export functions + it('should export a random channel function', async () => { + const resp = importedModule.getChannel(); + + expect(resp).to.be.a('string'); + }); + + it('should export a common channel function', async () => { + const resp = importedModule.getChannel('common'); + + expect(resp).to.be.a('string'); + }); + + // module main function + it('should be invokable by all', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should ratelimit if required', async () => { + const oldRL = mocks.server.police.frisk; + mocks.server.police.frisk = () => true; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + mocks.server.police.frisk = oldRL; + + expect(resp).to.be.true; + }); + + it('should validate channel legacy param', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 1; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'invite', + nick: 'test', + }, + }); + + expect(resp).to.be.true; + }); + + it('should validate nick legacy param', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 1; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'invite', + channel: 1234, + }, + }); + + expect(resp).to.be.true; + }); + + it('should validate userid param', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 2; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'invite', + userid: 1234, + }, + }); + + expect(resp).to.be.true; + }); + + it('should validate channel param', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 2; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'invite', + channel: 1234, + }, + }); + + expect(resp).to.be.true; + }); + + it('should handle user 404', async () => { + const oldFS = mocks.server.findSockets; + mockPayload.nick = 'lies'; + mocks.server.findSockets = (filterObj) => { + return false; + } + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 1; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'invite', + channel: 'cake', + nick: 'lies', + userid: 1234, + }, + }); + + mocks.server.findSockets = oldFS; + + expect(resp).to.be.true; + }); + + it('should handle legacy users', async () => { + const oldFS = mocks.server.findSockets; + mockPayload.nick = 'lies'; + mocks.server.findSockets = (filterObj) => { + return [{ + hcProtocol: 1, + }]; + } + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 1; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'invite', + channel: 'cake', + nick: 'lies', + userid: 1234, + }, + }); + + mocks.server.findSockets = oldFS; + + expect(resp).to.be.true; + }); + + it('should handle invites', async () => { + const oldFS = mocks.server.findSockets; + mockPayload.nick = 'lies'; + mocks.server.findSockets = (filterObj) => { + return [{ + hcProtocol: 2, + }]; + } + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 2; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'invite', + channel: 'cake', + nick: 'lies', + userid: 1234, + }, + }); + + mocks.server.findSockets = oldFS; + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/join.test.js b/test/join.test.js new file mode 100644 index 0000000..6867d2d --- /dev/null +++ b/test/join.test.js @@ -0,0 +1,288 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/join.js'; +let importedModule; + +const mockPayload = { + cmd: 'join', + channel: 'cake', + text: 'testing', +} + +describe('Checking join module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable by all', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should ratelimit if required', async () => { + const oldRL = mocks.server.police.frisk; + mocks.server.police.frisk = () => true; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + mocks.server.police.frisk = oldRL; + + expect(resp).to.be.true; + }); + + it('should upgrade legacy users', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = undefined; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'join', + nick: 'test#test', + channel: 'cake', + }, + }); + + expect(resp).to.be.true; + }); + + it('should fail on invalid channels', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = undefined; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'join', + nick: 'test#test', + channel: false, + }, + }); + + expect(resp).to.be.true; + }); + + it('should allow join only if not already joined', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.channel = undefined; + newSocket.hcProtocol = undefined; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'join', + nick: 'test#test', + channel: 'cake', + }, + }); + + expect(resp).to.be.true; + }); + + it('should allow join only user has a valid name', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.channel = undefined; + newSocket.hcProtocol = undefined; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'join', + nick: 't e s t#test', + channel: 'cake', + }, + }); + + expect(resp).to.be.true; + }); + + it('should prevent admin impersonation', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.channel = undefined; + newSocket.hcProtocol = undefined; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'join', + nick: 'admin#test', + channel: 'cake', + }, + }); + + expect(resp).to.be.true; + }); + + it('should prevent two of the same name in the same channel', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.channel = undefined; + newSocket.hcProtocol = undefined; + + mocks.server.findSockets = (filterObj) => { + return false; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'join', + nick: 'admin#test', + channel: 'cake', + }, + }); + + expect(resp).to.be.true; + }); + + it('should announce new user', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.channel = undefined; + newSocket.hcProtocol = undefined; + + mocks.server.findSockets = (filterObj) => { + if (filterObj.nick) { + if (typeof filterObj.nick === 'function') { + filterObj.nick('nick'); + } + + return false; + } else { + return [mocks.plebSocket]; + } + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'join', + nick: 'admin#test', + channel: 'cake', + }, + }); + + expect(resp).to.be.true; + }); + + it('should restore a join', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + + const resp = await importedModule.restoreJoin({ + server: mocks.server, + socket: newSocket, + channel: 'test', + }); + + expect(resp).to.be.true; + }); + + it('should accept a restoration refusal', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.banned = true; + + const resp = await importedModule.restoreJoin({ + server: mocks.server, + socket: newSocket, + channel: 'test', + }); + + expect(resp).to.be.true; + }); + + it('should account for duplicate connections', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + const newServer = Object.assign({}, mocks.server); + const origFindSockets = mocks.server.findSockets; + + newServer.findSockets = (filterObj) => { + if (typeof filterObj.nick !== 'undefined') { + filterObj.nick('nick'); + } + return [mocks.authedSocket]; + } + + const resp = await importedModule.restoreJoin({ + server: newServer, + socket: newSocket, + channel: 'test', + }); + + mocks.server.findSockets = origFindSockets; + + expect(resp).to.be.true; + }); + + it('should handle non-duplicate connections', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + const newServer = Object.assign({}, mocks.server); + const origFindSockets = mocks.server.findSockets; + let alreadyRan = false; + + newServer.findSockets = (filterObj) => { + if (alreadyRan === false) { + alreadyRan = true; + return [mocks.authedSocket]; + } + + return []; + } + + const resp = await importedModule.restoreJoin({ + server: newServer, + socket: newSocket, + channel: 'test', + }); + + mocks.server.findSockets = origFindSockets; + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/kick.test.js b/test/kick.test.js new file mode 100644 index 0000000..dd78403 --- /dev/null +++ b/test/kick.test.js @@ -0,0 +1,171 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/mod/kick.js'; +let importedModule; + +const mockPayload = { + cmd: 'kick', + userid: 1234, + to: 'no_cake', +} + +describe('Checking kick module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by a mod', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should validate legacy params', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 1; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: { + cmd: 'kick', + }, + }); + + expect(resp).to.be.true; + }); + + it('should handle no users found', async () => { + mocks.authedSocket.hcProtocol = 2; + mocks.server.findSockets = (filterObj) => { + if (typeof filterObj.nick === 'function') { + filterObj.nick('lies'); + } + + return []; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'kick', + userid: 1234, + to: 'test', + }, + }); + + expect(resp).to.be.true; + }); + + it('should validate params', async () => { + mocks.server.findSockets = (filterObj) => { + if (typeof filterObj.nick === 'function') { + filterObj.nick('lies'); + } + + return [mocks.plebSocket]; + } + + mocks.authedSocket.hcProtocol = 2; + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'kick', + userid: false, + }, + }); + + expect(resp).to.be.true; + }); + + it('should accept a "to" param', async () => { + mocks.authedSocket.hcProtocol = 2; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'kick', + userid: 1234, + to: 'test', + }, + }); + + expect(resp).to.be.true; + }); + + it('should kick to random channel', async () => { + mocks.authedSocket.hcProtocol = 2; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'kick', + userid: 1234, + }, + }); + + expect(resp).to.be.true; + }); + + it('should not kick mods', async () => { + mocks.authedSocket.hcProtocol = 2; + mocks.server.findSockets = (filterObj) => { + if (typeof filterObj.nick === 'function') { + filterObj.nick('lies'); + } + + return [mocks.authedSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'kick', + userid: 1234, + to: 'test', + }, + }); + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/legacyFunctions.test.js b/test/legacyFunctions.test.js new file mode 100644 index 0000000..d0b3f92 --- /dev/null +++ b/test/legacyFunctions.test.js @@ -0,0 +1,52 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/utility/_LegacyFunctions.js'; +let importedModule; + +describe('Checking legacyFunctions module', () => { + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should handle pass and password', async () => { + const resp = importedModule.upgradeLegacyJoin(mocks.server, mocks.plebSocket, { + nick: 'test#test', + password: 'test', + }); + expect(resp).to.be.an('object'); + }); + + it('should handle mod label', async () => { + const resp = importedModule.legacyLevelToLabel(9999999); + expect(resp).to.equal('admin'); + }); + + it('should handle mod label', async () => { + const resp = importedModule.legacyLevelToLabel(999999); + expect(resp).to.equal('mod'); + }); + + it('should provide duplicate user checks', async () => { + const newSocket = Object.assign({}, mocks.plebSocket); + newSocket.trip = false; + + const resp = importedModule.legacyWhisperOut({ + cmd: 'whisper', + }, newSocket); + + expect(resp).to.be.an('object'); + }); + + it('should apply missing user id', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.userid = undefined; + + const resp = importedModule.upgradeLegacyJoin(mocks.server, newSocket, { + nick: 'test#test', + password: 'test', + }); + expect(resp).to.be.an('object'); + }); +}) \ No newline at end of file diff --git a/test/listusers.test.js b/test/listusers.test.js new file mode 100644 index 0000000..ff107eb --- /dev/null +++ b/test/listusers.test.js @@ -0,0 +1,68 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/admin/listusers.js'; +let importedModule; + +const mockPayload = { + cmd: 'listusers', +} + +describe('Checking listusers module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by an admin', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should send a reply', async () => { + mocks.server.findSockets = (filterObj) => { + if (typeof filterObj.channel === 'function') { + filterObj.channel(); + } + + return [{}]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/mockImports.js b/test/mockImports.js new file mode 100644 index 0000000..48df539 --- /dev/null +++ b/test/mockImports.js @@ -0,0 +1,115 @@ +const mocks = { + core: { + sessionKey: 'test', + appConfig: { + data: { + globalMods: [], + permissions: [], + channels: { + test: { + owned: false, + } + }, + tripSalt: 'test', + adminTrip: '', + }, + write: async () => '', + }, + muzzledHashes: [], + stats: { + increment: () => 1, + decrement: () => 1, + get: () => 1, + set: () => 1, + }, + dynamicImports: { + reloadDirCache: () => '', + }, + commands: { + reloadCommands: () => '', + commands: [], + categoriesList: ['test'], + all: () => [{ + info: { + name: 'test', + category: 'test', + }, + }], + get: (name) => { + if (name === 'undef') { + return undefined; + } else if(name === 'noalias') { + return { + info: { + name: 'test', + category: 'test', + } + } + } else { + return { + info: { + name: 'test', + category: 'test', + aliases: ['testing'], + } + } + } + }, + }, + configManager: { + save: () => true, + }, + }, + server : { + police: { + addresses: [], + frisk: () => false, + arrest: (address) => mocks.server.police.addresses.push(address), + }, + findSockets: () => [], + reply: () => true, + broadcast: (data, filterObj) => { + if (typeof filterObj.level === 'function') { + filterObj.level(); + } + + return true; + }, + send: () => true, + cmdKey: 'test', + registerHook: () => true, + loadHooks: () => true, + clients: [{ + channel: 'cake', + address: '127.0.0.1', + }], + getSocketHash: () => 'test', + }, + plebSocket: { + level: 100, + address: '127.0.0.1', + channel: 'cake', + channels: [], + terminate: () => true, + nick: 'lies', + hcProtocol: 2, + hash: 'testHash', + uType: 'user', + userid: 1234, + }, + authedSocket: { + level: 9999999, + address: '127.0.0.1', + channel: 'cake', + channels: [], + terminate: () => true, + hcProtocol: 2, + nick: '[ignore this]', + trip: 'and this', + hash: 'testHash', + uType: 'admin', + userid: 1234, + }, +}; + +export default mocks; diff --git a/test/morestats.test.js b/test/morestats.test.js new file mode 100644 index 0000000..e79ef2e --- /dev/null +++ b/test/morestats.test.js @@ -0,0 +1,95 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/morestats.js'; +let importedModule; + +const mockPayload = { + cmd: 'morestats', + channel: 'cake', +} + +describe('Checking morestats module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable by all', async () => { + const newSocket = Object.assign({}, mocks.plebSocket); + newSocket.channel = 'programming'; + mocks.server.clients = [ + newSocket, + ]; + mocks.core.stats.get = (type) => { + if (type === 'start-time') { + return process.hrtime(); + } + + return false; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should initialize hooks', async () => { + expect(() => importedModule.initHooks(mocks.server)).not.to.throw(); + }); + + it('should validate params with /stats', async () => { + const resp = importedModule.statsCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + }, + }); + + expect(resp).to.be.false; + }); + + it('should run with /stats', async () => { + const resp = importedModule.statsCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: '/stats', + }, + }); + + expect(resp).to.be.false; + }); + +}); \ No newline at end of file diff --git a/test/ping.test.js b/test/ping.test.js new file mode 100644 index 0000000..c5fd541 --- /dev/null +++ b/test/ping.test.js @@ -0,0 +1,50 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/ping.js'; +let importedModule; + +const mockPayload = { + cmd: 'ping', + channel: 'cake', + text: 'testing', +} + +describe('Checking ping module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable by all', async () => { + expect(() => importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + })).not.to.throw(); + }); + +}); \ No newline at end of file diff --git a/test/reload.test.js b/test/reload.test.js new file mode 100644 index 0000000..80f4b08 --- /dev/null +++ b/test/reload.test.js @@ -0,0 +1,89 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/admin/reload.js'; +let importedModule; + +const mockPayload = { + cmd: 'reload', +} + +describe('Checking reload module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by an admin', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should reload server commands', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should report reload errors', async () => { + mocks.core.commands.reloadCommands = () => 'This is an error'; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: + mockPayload, + }); + + mocks.core.commands.reloadCommands = () => ''; + + expect(resp).to.be.true; + }); + + it('should report an optional reason', async () => { + mockPayload.reason = 'This is a reason'; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/removemod.test.js b/test/removemod.test.js new file mode 100644 index 0000000..555199c --- /dev/null +++ b/test/removemod.test.js @@ -0,0 +1,76 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/admin/removemod.js'; +let importedModule; + +const mockPayload = { + cmd: 'removemod', + trip: 'newTrip', +} + +describe('Checking removemod module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by an admin', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should remove trip from the config', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(mocks.core.appConfig.data.globalMods[0]).to.be.undefined; + }); + + it('should inform the ex-mod', async () => { + mocks.server.findSockets = () => { + return [{}]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/saveconfig.test.js b/test/saveconfig.test.js new file mode 100644 index 0000000..8da22ae --- /dev/null +++ b/test/saveconfig.test.js @@ -0,0 +1,92 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/admin/saveconfig.js'; +let importedModule; + +const mockPayload = { + cmd: 'saveconfig', +} + +describe('Checking saveconfig module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by an admin', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should force a config save', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should report errors', async () => { + mocks.core.appConfig.write = () => { + throw new Error; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + mocks.core.appConfig.write = () => ''; + + expect(resp).to.be.true; + }); + + it('should broadcast save notice', async () => { + mocks.server.findSockets = (filterObj) => { + return [mocks.plebSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/session.test.js b/test/session.test.js new file mode 100644 index 0000000..c977155 --- /dev/null +++ b/test/session.test.js @@ -0,0 +1,250 @@ +import { expect } from 'chai'; +import jsonwebtoken from 'jsonwebtoken'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/session.js'; +let importedModule; + +const mockPayload = { + cmd: 'session', + token: 'testing', +} + +describe('Checking session module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should initialize', async () => { + const resp = importedModule.init(mocks.core); + expect(mocks.core).to.be.an('object'); + }); + + it('should provide current session string', async () => { + const newCore = Object.assign({}, mocks.core); + + const resp = await importedModule.getSession(mocks.plebSocket, newCore); + + expect(resp).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + it('should initialize', async () => { + const newCore = Object.assign({}, mocks.core); + newCore.sessionKey = undefined; + const resp = importedModule.init(newCore); + + expect(newCore.sessionKey).to.not.equal(undefined); + }); + + // module main function + it('should be invokable by all', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should notify about required token', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'session', + }, + }); + + expect(resp).to.be.false; + }); + + it('should notify about invalid token', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'session', + token: 'false', + }, + }); + + expect(resp).to.be.false; + }); + + it('should accept valid token', async () => { + const newCore = Object.assign({}, mocks.core); + newCore.sessionKey = 'test'; + const token = jsonwebtoken.sign({ + nick: 'test', + channel: 'test', + }, newCore.sessionKey); + + const resp = await importedModule.run({ + core: newCore, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'session', + token: token, + }, + }); + + expect(resp).to.be.false; + }); + + it('should require a session channel value', async () => { + const newCore = Object.assign({}, mocks.core); + newCore.sessionKey = 'test'; + const token = jsonwebtoken.sign({ + test: 'test', + }, newCore.sessionKey); + + const resp = await importedModule.run({ + core: newCore, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'session', + token: token, + }, + }); + + expect(resp).to.be.false; + }); + + it('should require session channels value', async () => { + const newCore = Object.assign({}, mocks.core); + newCore.sessionKey = 'test'; + const token = jsonwebtoken.sign({ + channel: 'test', + }, newCore.sessionKey); + + const resp = await importedModule.run({ + core: newCore, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'session', + token: token, + }, + }); + + expect(resp).to.be.false; + }); + + it('should require session color value', async () => { + const newCore = Object.assign({}, mocks.core); + newCore.sessionKey = 'test'; + const token = jsonwebtoken.sign({ + channel: 'test', + channels: ['test'], + }, newCore.sessionKey); + + const resp = await importedModule.run({ + core: newCore, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'session', + token: token, + }, + }); + + expect(resp).to.be.false; + }); + + it('should require session isBot value', async () => { + const newCore = Object.assign({}, mocks.core); + newCore.sessionKey = 'test'; + const token = jsonwebtoken.sign({ + channel: 'test', + channels: ['test'], + color: 'ffffff', + }, newCore.sessionKey); + + const resp = await importedModule.run({ + core: newCore, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'session', + token: token, + }, + }); + + expect(resp).to.be.false; + }); + + it('should require session level value', async () => { + const newCore = Object.assign({}, mocks.core); + newCore.sessionKey = 'test'; + const token = jsonwebtoken.sign({ + channel: 'test', + channels: ['test'], + color: 'ffffff', + isBot: false, + }, newCore.sessionKey); + + const resp = await importedModule.run({ + core: newCore, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'session', + token: token, + }, + }); + + expect(resp).to.be.false; + }); + + it('should require session level value', async () => { + const newCore = Object.assign({}, mocks.core); + newCore.sessionKey = 'test'; + const token = jsonwebtoken.sign({ + channel: 'test', + channels: ['test'], + color: 'ffffff', + isBot: false, + nick: 'test', + }, newCore.sessionKey); + + const resp = await importedModule.run({ + core: newCore, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'session', + token: token, + }, + }); + + expect(resp).to.be.false; + }); +}); \ No newline at end of file diff --git a/test/shout.test.js b/test/shout.test.js new file mode 100644 index 0000000..923148a --- /dev/null +++ b/test/shout.test.js @@ -0,0 +1,65 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/admin/shout.js'; +let importedModule; + +const mockPayload = { + cmd: 'shout', + text: 'This is a shout', +} + +describe('Checking shout module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by an admin', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should do the broadcast', async () => { + mocks.server.findSockets = () => { + return [{}]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/socketreply.test.js b/test/socketreply.test.js new file mode 100644 index 0000000..2919bbc --- /dev/null +++ b/test/socketreply.test.js @@ -0,0 +1,61 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/internal/socketreply.js'; +let importedModule; + +const mockPayload = { + cmd: 'disconnect', +} + +describe('Checking socketreply module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only internally', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should broadcast warning event', async () => { + mockPayload.cmdKey = 'test'; + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); +}); \ No newline at end of file diff --git a/test/speak.test.js b/test/speak.test.js new file mode 100644 index 0000000..1215b9c --- /dev/null +++ b/test/speak.test.js @@ -0,0 +1,71 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/mod/speak.js'; +let importedModule; + +const mockPayload = { + cmd: 'speak', + ip: '127.0.0.1', +} + +describe('Checking speak module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by a mod', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should initialize', async () => { + mocks.core.muzzledHashes = undefined; + const resp = importedModule.init(mocks.core); + + expect(mocks.core.muzzledHashes).to.be.an('object'); + }); + + it('should validate params', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'speak', + }, + }); + + expect(resp).to.be.true; + }); + +}); \ No newline at end of file diff --git a/test/stats.test.js b/test/stats.test.js new file mode 100644 index 0000000..d2a7c2c --- /dev/null +++ b/test/stats.test.js @@ -0,0 +1,48 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/stats.js'; +let importedModule; + +const mockPayload = { + cmd: 'stats', +} + +describe('Checking stats module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable by all', async () => { + expect(() => importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + })).not.to.throw(); + }); + +}); \ No newline at end of file diff --git a/test/uac.test.js b/test/uac.test.js new file mode 100644 index 0000000..be017e1 --- /dev/null +++ b/test/uac.test.js @@ -0,0 +1,67 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/utility/_UAC.js'; +let importedModule; + +describe('Checking UAC module', () => { + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should handle channel owners', async () => { + const resp = importedModule.isChannelOwner(9999999); + expect(resp).to.be.true; + }); + + it('should handle channel mods', async () => { + const resp = importedModule.isChannelModerator(9999999); + expect(resp).to.be.true; + }); + + it('should handle channel mods', async () => { + const resp = importedModule.isChannelTrusted(9999999); + expect(resp).to.be.true; + }); + + it('should handle channel mods', async () => { + const resp = importedModule.isTrustedUser(9999999); + expect(resp).to.be.true; + }); + + it('should return false on bad nickname', async () => { + const resp = importedModule.verifyNickname(); + expect(resp).to.be.false; + }); + + it('should return default perms', async () => { + const resp = importedModule.getUserPerms(false); + expect(resp).to.be.an('object'); + }); + + it('should return admin level labels', async () => { + const newConfig = Object.assign({}, mocks.core.appConfig.data); + newConfig.adminTrip = 'Tt8H7c'; + const resp = importedModule.getUserPerms('test', 'salt', newConfig, 'cake'); + expect(resp).to.be.an('object'); + }); + + it('should return mod level labels', async () => { + const newConfig = Object.assign({}, mocks.core.appConfig.data); + newConfig.globalMods = [{ + trip: 'Tt8H7c', + }]; + const resp = importedModule.getUserPerms('test', 'salt', newConfig, 'cake'); + expect(resp).to.be.an('object'); + }); + + it('should return ownership info', async () => { + const newConfig = Object.assign({}, mocks.core.appConfig.data); + newConfig.permissions['cake'] = { + owned: true, + }; + const resp = importedModule.getUserPerms('test', 'salt', newConfig, 'cake'); + expect(resp).to.be.an('object'); + }); +}) \ No newline at end of file diff --git a/test/unban.test.js b/test/unban.test.js new file mode 100644 index 0000000..e986014 --- /dev/null +++ b/test/unban.test.js @@ -0,0 +1,64 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/mod/unban.js'; +let importedModule; + +const mockPayload = { + cmd: 'unban', + ip: '127.0.0.1', +} + +describe('Checking unban module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by a mod', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + + it('should require ip or hash', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.authedSocket, + payload: { + cmd: 'ban', + }, + }); + + expect(resp).to.be.true; + }); + +}); \ No newline at end of file diff --git a/test/unbanall.test.js b/test/unbanall.test.js new file mode 100644 index 0000000..f716b7d --- /dev/null +++ b/test/unbanall.test.js @@ -0,0 +1,50 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/mod/unbanall.js'; +let importedModule; + +const mockPayload = { + cmd: 'unbanall', +} + +describe('Checking unbanall module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable only by a mod', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.false; + }); + +}); \ No newline at end of file diff --git a/test/whisper.test.js b/test/whisper.test.js new file mode 100644 index 0000000..4e45332 --- /dev/null +++ b/test/whisper.test.js @@ -0,0 +1,269 @@ +import { expect } from 'chai'; +import mocks from './mockImports.js'; + +const modulePath = '../commands/core/whisper.js'; +let importedModule; + +const mockPayload = { + cmd: 'whisper', + text: 'testing', + userid: 1234, + nick: 'test', +} + +describe('Checking whisper module', () => { + // module meta data + it('should be importable', async () => { + importedModule = await import(modulePath); + expect(importedModule).to.not.be.a('string'); + }); + + it('should be named', async () => { + expect(importedModule.info.name).to.be.a('string'); + }); + + it('should be categorized', async () => { + expect(importedModule.info.category).to.be.a('string'); + }); + + it('should be described', async () => { + expect(importedModule.info.description).to.be.a('string'); + }); + + it('should be documented', async () => { + expect(importedModule.info.usage).to.be.a('string'); + }); + + it('should be invokable', async () => { + expect(importedModule.run).to.be.a('function'); + }); + + // module main function + it('should be invokable by all', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should reject invalid text', async () => { + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'whisper', + text: false, + }, + }); + + expect(resp).to.be.false; + }); + + it('should handle legacy users', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 1; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should ratelimit if required', async () => { + const oldRL = mocks.server.police.frisk; + mocks.server.police.frisk = () => true; + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: mockPayload, + }); + + mocks.server.police.frisk = oldRL; + + expect(resp).to.be.true; + }); + + it('should handle 404 users', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 1; + + mocks.server.findSockets = (filterObj) => { + return false; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should handle legacy users in', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 1; + + mocks.server.findSockets = (filterObj) => { + return [mocks.authedSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should handle legacy users out', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + newSocket.hcProtocol = 1; + + mocks.server.findSockets = (filterObj) => { + return [newSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should handle users out', async () => { + const newSocket = Object.assign({}, mocks.authedSocket); + + mocks.server.findSockets = (filterObj) => { + return [newSocket]; + } + + const resp = await importedModule.run({ + core: mocks.core, + server: mocks.server, + socket: newSocket, + payload: mockPayload, + }); + + expect(resp).to.be.true; + }); + + it('should initialize hooks', async () => { + expect(() => importedModule.initHooks(mocks.server)).not.to.throw(); + }); + + it('should hook for /whisper chat commands, verifying params', async () => { + const resp = importedModule.whisperCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: false, + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook for /whisper chat commands', async () => { + const resp = importedModule.whisperCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: '/whisper user stuff', + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook for /w chat commands', async () => { + const resp = importedModule.whisperCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: '/w user stuff', + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook for /w chat commands, validating params', async () => { + const resp = importedModule.whisperCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: '/whisper ', + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook for /reply chat commands', async () => { + const resp = importedModule.whisperCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: '/reply ', + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook for /r chat commands', async () => { + const resp = importedModule.whisperCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: '/r ', + }, + }); + + expect(resp).to.be.false; + }); + + it('should hook only certain triggers', async () => { + const resp = importedModule.whisperCheck({ + core: mocks.core, + server: mocks.server, + socket: mocks.plebSocket, + payload: { + cmd: 'chat', + text: 'normal text', + }, + }); + + expect(resp).to.be.an('object'); + }); +}); \ No newline at end of file