diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..26fb431
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,2 @@
+src/
+dist/
\ No newline at end of file
diff --git a/.eslintrc.json b/.eslintrc.json
index 738756d..0471021 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,6 +1,9 @@
{
+ "parser": "@typescript-eslint/parser",
"extends": [
- "eslint:recommended"
+ "eslint:recommended",
+ "plugin:@typescript-eslint/eslint-recommended",
+ "plugin:@typescript-eslint/recommended"
],
"env": {
"node": true,
@@ -9,11 +12,25 @@
},
"parserOptions": {
"ecmaVersion": 2018,
- "sourceType": "module",
- "allowImportExportEverywhere": true
+ "sourceType": "module"
},
"rules": {
"no-var": "error",
- "no-console": "off"
+ "no-console": "off",
+ "@typescript-eslint/camelcase": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/member-delimiter-style": [
+ "error",
+ {
+ "multiline": {
+ "delimiter": "semi",
+ "requireLast": true
+ },
+ "singleline": {
+ "delimiter": "semi",
+ "requireLast": true
+ }
+ }
+ ]
}
}
\ No newline at end of file
diff --git a/.github/workflows/dockerimage.yml b/.github/workflows/dockerimage.yml
new file mode 100644
index 0000000..63eb23c
--- /dev/null
+++ b/.github/workflows/dockerimage.yml
@@ -0,0 +1,20 @@
+name: Docker Image CI
+
+on:
+ push:
+ branches:
+ - master
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v1
+ - name: Build the Docker image
+ run: docker build . --file Dockerfile --tag peerjs/peerjs-server:latest
+ - name: Publish to Registry
+ uses: elgohr/Publish-Docker-Github-Action@master
+ with:
+ name: peerjs/peerjs-server:latest
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
diff --git a/.gitignore b/.gitignore
index e372c24..16bd87a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,4 +14,6 @@ results
node_modules
npm-debug.log
-.idea
\ No newline at end of file
+.idea
+.cache
+.vscode
\ No newline at end of file
diff --git a/.gitpod.yml b/.gitpod.yml
new file mode 100644
index 0000000..2e958b0
--- /dev/null
+++ b/.gitpod.yml
@@ -0,0 +1,7 @@
+tasks:
+ - init: npm i
+ command: npm start
+
+ports:
+ - port: 9000
+ onOpen: open-preview
diff --git a/Dockerfile b/Dockerfile
index 4455519..1e896fe 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,10 +2,8 @@ FROM node:alpine
RUN mkdir /peer-server
WORKDIR /peer-server
COPY bin ./bin
+COPY dist ./dist
COPY package.json .
-COPY src ./src
-COPY config ./config
-COPY app.json .
RUN npm install
EXPOSE 9000
ENTRYPOINT ["node", "bin/peerjs"]
diff --git a/README.md b/README.md
index 3564c94..16fd9a3 100644
--- a/README.md
+++ b/README.md
@@ -1,26 +1,34 @@
[](https://travis-ci.org/peers/peerjs-server)
+[](https://www.npmjs.com/package/peer)
+[](https://www.npmjs.com/package/peer)
# PeerServer: A server for PeerJS #
-This fork of peerjs-server adds functionality to set a custom ID generation fucntion. [Commit](https://github.com/ajmar/peerjs-server/commit/2552e9d)
-
PeerServer helps broker connections between PeerJS clients. Data is not proxied through the server.
+Run your own server on Gitpod!
+
+[](https://gitpod.io/#https://github.com/peers/peerjs-server)
+
## [https://peerjs.com](https://peerjs.com)
### Run PeerServer
-1. Clone app:
+1. Install PeerServer from npm or github:
+
+#### NPM
```bash
-git clone https://github.com/peers/peerjs-server.git
+npm install peer
```
-2. Install dependencies:
+#### github
+
```bash
+git clone https://github.com/peers/peerjs-server.git#master
npm install
```
-3. Run the server:
+2. Run the server:
```bash
$> peerjs --port 9000 --key peerjs --path /myapp
@@ -38,7 +46,9 @@ import {PeerServer} from 'peerjs-server';
const server = PeerServer({port: 9000, path: '/myapp'});
```
-Connecting to the server from PeerJS:
+3. Check that server works: open browser with [http://localhost:9000/myapp](http://localhost:9000/myapp) It should returns JSON with name, description and website fields.
+
+### Connecting to the server from PeerJS:
```html
```
-Using HTTPS: Simply pass in PEM-encoded certificate and key.
+### Using HTTPS: Simply pass in PEM-encoded certificate and key.
```javascript
import fs from 'fs';
@@ -61,7 +71,7 @@ const server = PeerServer({
});
```
-#### Running PeerServer behind a reverse proxy
+### Running PeerServer behind a reverse proxy
Make sure to set the `proxied` option, otherwise IP based limiting will fail.
The option is passed verbatim to the
@@ -74,6 +84,20 @@ import {PeerServer} from 'peerjs-server';
const server = PeerServer({port: 9000, path: '/myapp', proxied: true});
```
+
+### Custom client ID generation
+
+You can specify a custom function to use to generate client IDs.
+
+```javascript
+const genRandomId = () => {
+ // Original generation algorithm
+ return (Math.random().toString(36) + '0000000000000000000').substr(2, 16);
+}
+
+const server = PeerServer({port: 9000, path: '/myapp', proxied: true, genRandomId: genRandomId });
+```
+
### Combining with existing express app
```javascript
@@ -146,7 +170,7 @@ This will start a peerjs server on port 9000 exposed on port 9000.
## Problems?
-Discuss PeerJS on our Google Group:
-https://groups.google.com/forum/?fromgroups#!forum/peerjs
+Discuss PeerJS on our Telegram chat:
+https://t.me/joinchat/ENhPuhTvhm8WlIxTjQf7Og
Please post any bugs as a Github issue.
diff --git a/bin/peerjs b/bin/peerjs
index 01c4a8f..9d45ca8 100755
--- a/bin/peerjs
+++ b/bin/peerjs
@@ -1,69 +1,70 @@
#!/usr/bin/env node
+// tslint:disable
-const path = require('path');
-const pkg = require('../package.json');
-const fs = require('fs');
+const path = require("path");
+const pkg = require("../package.json");
+const fs = require("fs");
const version = pkg.version;
-const PeerServer = require('../src').PeerServer;
-const opts = require('optimist')
- .usage('Usage: $0')
+const { PeerServer } = require("../dist/src");
+const opts = require("optimist")
+ .usage("Usage: $0")
.options({
expire_timeout: {
demand: false,
- alias: 't',
- description: 'timeout (milliseconds)',
+ alias: "t",
+ description: "timeout (milliseconds)",
default: 5000
},
concurrent_limit: {
demand: false,
- alias: 'c',
- description: 'concurrent limit',
+ alias: "c",
+ description: "concurrent limit",
default: 5000
},
alive_timeout: {
demand: false,
- description: 'broken connection check timeout (milliseconds)',
+ description: "broken connection check timeout (milliseconds)",
default: 60000
},
key: {
demand: false,
- alias: 'k',
- description: 'connection key',
- default: 'peerjs'
+ alias: "k",
+ description: "connection key",
+ default: "peerjs"
},
sslkey: {
demand: false,
- description: 'path to SSL key'
+ description: "path to SSL key"
},
sslcert: {
demand: false,
- description: 'path to SSL certificate'
+ description: "path to SSL certificate"
},
port: {
demand: true,
- alias: 'p',
- description: 'port'
+ alias: "p",
+ description: "port"
},
path: {
demand: false,
- description: 'custom path',
- default: '/'
+ description: "custom path",
+ default: "/"
},
allow_discovery: {
demand: false,
- description: 'allow discovery of peers'
+ description: "allow discovery of peers"
},
proxied: {
demand: false,
- description: 'Set true if PeerServer stays behind a reverse proxy',
+ description: "Set true if PeerServer stays behind a reverse proxy",
default: false
}
})
- .boolean('allow_discovery')
+ .boolean("allow_discovery")
.argv;
-process.on('uncaughtException', function (e) {
- console.error('Error: ' + e);
+process.on("uncaughtException", function (e) {
+ console.error("Error: " + e);
});
if (opts.sslkey || opts.sslcert) {
@@ -76,8 +77,8 @@ if (opts.sslkey || opts.sslcert) {
delete opts.sslkey;
delete opts.sslcert;
} else {
- console.error('Warning: PeerServer will not run because either ' +
- 'the key or the certificate has not been provided.');
+ console.error("Warning: PeerServer will not run because either " +
+ "the key or the certificate has not been provided.");
process.exit(1);
}
}
@@ -88,15 +89,15 @@ const server = PeerServer(opts, server => {
const port = server.address().port;
console.log(
- 'Started PeerServer on %s, port: %s, path: %s (v. %s)',
- host, port, userPath || '/', version
+ "Started PeerServer on %s, port: %s, path: %s (v. %s)",
+ host, port, userPath || "/", version
);
});
-server.on('connection', client => {
+server.on("connection", client => {
console.log(`Client connected: ${client.getId()}`);
});
-server.on('disconnect', client => {
+server.on("disconnect", client => {
console.log(`Client disconnected: ${client.getId()}`);
});
diff --git a/changelog.md b/changelog.md
index 8f8987f..5701358 100644
--- a/changelog.md
+++ b/changelog.md
@@ -2,8 +2,10 @@
### vNEXT 0.3.0
-* refactoring (add ESLint, split code into small unit) Thanks to @d07RiV @zhou-yg
-* update deps
+* Convert project to TypeScript 3.7.3.
+* Use UUID when generate client id - #152
+* Refactoring (add ESLint, split code into small unit) Thanks to @d07RiV @zhou-yg
+* Update deps.
### 0.2.6
diff --git a/config/index.js b/config/index.js
deleted file mode 100644
index 3b0ecb4..0000000
--- a/config/index.js
+++ /dev/null
@@ -1,15 +0,0 @@
-module.exports = {
- port: 9000,
- expire_timeout: 5000,
- alive_timeout: 60000,
- key: 'peerjs',
- path: '/myapp',
- concurrent_limit: 5000,
- allow_discovery: false,
- proxied: false,
- cleanup_out_msgs: 1000,
- ssl: {
- key: '',
- cert: ''
- }
-};
diff --git a/dist/app.json b/dist/app.json
new file mode 100644
index 0000000..6490e45
--- /dev/null
+++ b/dist/app.json
@@ -0,0 +1,5 @@
+{
+ "name": "PeerJS Server",
+ "description": "A server side element to broker connections between PeerJS clients.",
+ "website": "http://peerjs.com/"
+}
diff --git a/dist/config/index.js b/dist/config/index.js
new file mode 100644
index 0000000..b95d622
--- /dev/null
+++ b/dist/config/index.js
@@ -0,0 +1,18 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const defaultConfig = {
+ port: 9000,
+ expire_timeout: 5000,
+ alive_timeout: 60000,
+ key: "peerjs",
+ path: "/myapp",
+ concurrent_limit: 5000,
+ allow_discovery: false,
+ proxied: false,
+ cleanup_out_msgs: 1000,
+ ssl: {
+ key: "",
+ cert: ""
+ }
+};
+exports.default = defaultConfig;
diff --git a/dist/src/api/index.js b/dist/src/api/index.js
new file mode 100644
index 0000000..ed7fabc
--- /dev/null
+++ b/dist/src/api/index.js
@@ -0,0 +1,24 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const body_parser_1 = __importDefault(require("body-parser"));
+const cors_1 = __importDefault(require("cors"));
+const express_1 = __importDefault(require("express"));
+const app_json_1 = __importDefault(require("../../app.json"));
+const auth_1 = require("./middleware/auth");
+const calls_1 = __importDefault(require("./v1/calls"));
+const public_1 = __importDefault(require("./v1/public"));
+exports.Api = ({ config, realm, messageHandler }) => {
+ const authMiddleware = new auth_1.AuthMiddleware(config, realm);
+ const app = express_1.default.Router();
+ const jsonParser = body_parser_1.default.json();
+ app.use(cors_1.default());
+ app.get("/", (_, res) => {
+ res.send(app_json_1.default);
+ });
+ app.use("/:key", public_1.default({ config, realm }));
+ app.use("/:key/:id/:token", authMiddleware.handle, jsonParser, calls_1.default({ realm, messageHandler }));
+ return app;
+};
diff --git a/dist/src/api/middleware/auth/index.js b/dist/src/api/middleware/auth/index.js
new file mode 100644
index 0000000..11d15ca
--- /dev/null
+++ b/dist/src/api/middleware/auth/index.js
@@ -0,0 +1,27 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const enums_1 = require("../../../enums");
+class AuthMiddleware {
+ constructor(config, realm) {
+ this.config = config;
+ this.realm = realm;
+ }
+ handle(req, res, next) {
+ const { id, token, key } = req.params;
+ if (key !== this.config.key) {
+ return res.status(401).send(enums_1.Errors.INVALID_KEY);
+ }
+ if (!id) {
+ return res.sendStatus(401);
+ }
+ const client = this.realm.getClientById(id);
+ if (!client) {
+ return res.sendStatus(401);
+ }
+ if (client.getToken() && token !== client.getToken()) {
+ return res.status(401).send(enums_1.Errors.INVALID_TOKEN);
+ }
+ next();
+ }
+}
+exports.AuthMiddleware = AuthMiddleware;
diff --git a/dist/src/api/middleware/middleware.js b/dist/src/api/middleware/middleware.js
new file mode 100644
index 0000000..c8ad2e5
--- /dev/null
+++ b/dist/src/api/middleware/middleware.js
@@ -0,0 +1,2 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
diff --git a/dist/src/api/v1/calls/index.js b/dist/src/api/v1/calls/index.js
new file mode 100644
index 0000000..17ae5e3
--- /dev/null
+++ b/dist/src/api/v1/calls/index.js
@@ -0,0 +1,32 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const express_1 = __importDefault(require("express"));
+exports.default = ({ realm, messageHandler }) => {
+ const app = express_1.default.Router();
+ const handle = (req, res, next) => {
+ const { id } = req.params;
+ if (!id)
+ return next();
+ const client = realm.getClientById(id);
+ if (!client) {
+ throw new Error(`client not found:${id}`);
+ }
+ const { type, dst, payload } = req.body;
+ const message = {
+ type,
+ src: id,
+ dst,
+ payload
+ };
+ messageHandler.handle(client, message);
+ res.sendStatus(200);
+ };
+ app.post("/offer", handle);
+ app.post("/candidate", handle);
+ app.post("/answer", handle);
+ app.post("/leave", handle);
+ return app;
+};
diff --git a/dist/src/api/v1/public/index.js b/dist/src/api/v1/public/index.js
new file mode 100644
index 0000000..1bf69f9
--- /dev/null
+++ b/dist/src/api/v1/public/index.js
@@ -0,0 +1,23 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const express_1 = __importDefault(require("express"));
+exports.default = ({ config, realm }) => {
+ const app = express_1.default.Router();
+ // Retrieve guaranteed random ID.
+ app.get("/id", (_, res) => {
+ res.contentType("html");
+ res.send(realm.generateClientId());
+ });
+ // Get a list of all peers for a key, enabled by the `allowDiscovery` flag.
+ app.get("/peers", (_, res) => {
+ if (config.allow_discovery) {
+ const clientsIds = realm.getClientsIds();
+ return res.send(clientsIds);
+ }
+ res.sendStatus(401);
+ });
+ return app;
+};
diff --git a/dist/src/config/index.js b/dist/src/config/index.js
new file mode 100644
index 0000000..b95d622
--- /dev/null
+++ b/dist/src/config/index.js
@@ -0,0 +1,18 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const defaultConfig = {
+ port: 9000,
+ expire_timeout: 5000,
+ alive_timeout: 60000,
+ key: "peerjs",
+ path: "/myapp",
+ concurrent_limit: 5000,
+ allow_discovery: false,
+ proxied: false,
+ cleanup_out_msgs: 1000,
+ ssl: {
+ key: "",
+ cert: ""
+ }
+};
+exports.default = defaultConfig;
diff --git a/dist/src/enums.js b/dist/src/enums.js
new file mode 100644
index 0000000..7670504
--- /dev/null
+++ b/dist/src/enums.js
@@ -0,0 +1,21 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var Errors;
+(function (Errors) {
+ Errors["INVALID_KEY"] = "Invalid key provided";
+ Errors["INVALID_TOKEN"] = "Invalid token provided";
+ Errors["INVALID_WS_PARAMETERS"] = "No id, token, or key supplied to websocket server";
+ Errors["CONNECTION_LIMIT_EXCEED"] = "Server has reached its concurrent user limit";
+})(Errors = exports.Errors || (exports.Errors = {}));
+var MessageType;
+(function (MessageType) {
+ MessageType["OPEN"] = "OPEN";
+ MessageType["LEAVE"] = "LEAVE";
+ MessageType["CANDIDATE"] = "CANDIDATE";
+ MessageType["OFFER"] = "OFFER";
+ MessageType["ANSWER"] = "ANSWER";
+ MessageType["EXPIRE"] = "EXPIRE";
+ MessageType["HEARTBEAT"] = "HEARTBEAT";
+ MessageType["ID_TAKEN"] = "ID-TAKEN";
+ MessageType["ERROR"] = "ERROR";
+})(MessageType = exports.MessageType || (exports.MessageType = {}));
diff --git a/dist/src/index.js b/dist/src/index.js
new file mode 100644
index 0000000..dc4a6fb
--- /dev/null
+++ b/dist/src/index.js
@@ -0,0 +1,52 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const express_1 = __importDefault(require("express"));
+const http_1 = __importDefault(require("http"));
+const https_1 = __importDefault(require("https"));
+const config_1 = __importDefault(require("./config"));
+const instance_1 = require("./instance");
+function ExpressPeerServer(server, options) {
+ const app = express_1.default();
+ const newOptions = Object.assign(Object.assign({}, config_1.default), options);
+ if (newOptions.proxied) {
+ app.set("trust proxy", newOptions.proxied === "false" ? false : !!newOptions.proxied);
+ }
+ app.on("mount", () => {
+ if (!server) {
+ throw new Error("Server is not passed to constructor - " +
+ "can't start PeerServer");
+ }
+ instance_1.createInstance({ app, server, options: newOptions });
+ });
+ return app;
+}
+exports.ExpressPeerServer = ExpressPeerServer;
+function PeerServer(options = {}, callback) {
+ const app = express_1.default();
+ const newOptions = Object.assign(Object.assign({}, config_1.default), options);
+ let path = newOptions.path;
+ const port = newOptions.port;
+ if (!path.startsWith('/')) {
+ path = "/" + path;
+ }
+ if (!path.endsWith('/')) {
+ path += "/";
+ }
+ let server;
+ if (newOptions.ssl && newOptions.ssl.key && newOptions.ssl.cert) {
+ server = https_1.default.createServer(options.ssl, app);
+ // @ts-ignore
+ delete newOptions.ssl;
+ }
+ else {
+ server = http_1.default.createServer(app);
+ }
+ const peerjs = ExpressPeerServer(server, newOptions);
+ app.use(peerjs);
+ server.listen(port, () => { var _a; return (_a = callback) === null || _a === void 0 ? void 0 : _a(server); });
+ return peerjs;
+}
+exports.PeerServer = PeerServer;
diff --git a/dist/src/instance.js b/dist/src/instance.js
new file mode 100644
index 0000000..458e01c
--- /dev/null
+++ b/dist/src/instance.js
@@ -0,0 +1,51 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const realm_1 = require("./models/realm");
+const checkBrokenConnections_1 = require("./services/checkBrokenConnections");
+const messagesExpire_1 = require("./services/messagesExpire");
+const webSocketServer_1 = require("./services/webSocketServer");
+const messageHandler_1 = require("./messageHandler");
+const api_1 = require("./api");
+exports.createInstance = ({ app, server, options }) => {
+ const config = options;
+ const realm = new realm_1.Realm();
+ const messageHandler = new messageHandler_1.MessageHandler(realm);
+ const api = api_1.Api({ config, realm, messageHandler });
+ const messagesExpire = new messagesExpire_1.MessagesExpire({ realm, config, messageHandler });
+ const checkBrokenConnections = new checkBrokenConnections_1.CheckBrokenConnections({
+ realm,
+ config,
+ onClose: client => {
+ app.emit("disconnect", client);
+ }
+ });
+ app.use(options.path, api);
+ const wss = new webSocketServer_1.WebSocketServer({
+ server,
+ realm,
+ config
+ });
+ wss.on("connection", (client) => {
+ const messageQueue = realm.getMessageQueueById(client.getId());
+ if (messageQueue) {
+ let message;
+ while (message = messageQueue.readMessage()) {
+ messageHandler.handle(client, message);
+ }
+ realm.clearMessageQueue(client.getId());
+ }
+ app.emit("connection", client);
+ });
+ wss.on("message", (client, message) => {
+ app.emit("message", client, message);
+ messageHandler.handle(client, message);
+ });
+ wss.on("close", (client) => {
+ app.emit("disconnect", client);
+ });
+ wss.on("error", (error) => {
+ app.emit("error", error);
+ });
+ messagesExpire.startMessagesExpiration();
+ checkBrokenConnections.start();
+};
diff --git a/dist/src/messageHandler/handler.js b/dist/src/messageHandler/handler.js
new file mode 100644
index 0000000..c8ad2e5
--- /dev/null
+++ b/dist/src/messageHandler/handler.js
@@ -0,0 +1,2 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
diff --git a/dist/src/messageHandler/handlers/heartbeat/index.js b/dist/src/messageHandler/handlers/heartbeat/index.js
new file mode 100644
index 0000000..d292fec
--- /dev/null
+++ b/dist/src/messageHandler/handlers/heartbeat/index.js
@@ -0,0 +1,9 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.HeartbeatHandler = (client) => {
+ if (client) {
+ const nowTime = new Date().getTime();
+ client.setLastPing(nowTime);
+ }
+ return true;
+};
diff --git a/dist/src/messageHandler/handlers/index.js b/dist/src/messageHandler/handlers/index.js
new file mode 100644
index 0000000..f053a44
--- /dev/null
+++ b/dist/src/messageHandler/handlers/index.js
@@ -0,0 +1,6 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var heartbeat_1 = require("./heartbeat");
+exports.HeartbeatHandler = heartbeat_1.HeartbeatHandler;
+var transmission_1 = require("./transmission");
+exports.TransmissionHandler = transmission_1.TransmissionHandler;
diff --git a/dist/src/messageHandler/handlers/transmission/index.js b/dist/src/messageHandler/handlers/transmission/index.js
new file mode 100644
index 0000000..5183eb4
--- /dev/null
+++ b/dist/src/messageHandler/handlers/transmission/index.js
@@ -0,0 +1,58 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const enums_1 = require("../../../enums");
+exports.TransmissionHandler = ({ realm }) => {
+ const handle = (client, message) => {
+ const type = message.type;
+ const srcId = message.src;
+ const dstId = message.dst;
+ const destinationClient = realm.getClientById(dstId);
+ // User is connected!
+ if (destinationClient) {
+ const socket = destinationClient.getSocket();
+ try {
+ if (socket) {
+ const data = JSON.stringify(message);
+ socket.send(data);
+ }
+ else {
+ // Neither socket no res available. Peer dead?
+ throw new Error("Peer dead");
+ }
+ }
+ catch (e) {
+ // This happens when a peer disconnects without closing connections and
+ // the associated WebSocket has not closed.
+ // Tell other side to stop trying.
+ if (socket) {
+ socket.close();
+ }
+ else {
+ realm.removeClientById(destinationClient.getId());
+ }
+ handle(client, {
+ type: enums_1.MessageType.LEAVE,
+ src: dstId,
+ dst: srcId
+ });
+ }
+ }
+ else {
+ // Wait for this client to connect/reconnect (XHR) for important
+ // messages.
+ const ignoredTypes = [enums_1.MessageType.LEAVE, enums_1.MessageType.EXPIRE];
+ if (!ignoredTypes.includes(type) && dstId) {
+ realm.addMessageToQueue(dstId, message);
+ }
+ else if (type === enums_1.MessageType.LEAVE && !dstId) {
+ realm.removeClientById(srcId);
+ }
+ else {
+ // Unavailable destination specified with message LEAVE or EXPIRE
+ // Ignore
+ }
+ }
+ return true;
+ };
+ return handle;
+};
diff --git a/dist/src/messageHandler/handlersRegistry.js b/dist/src/messageHandler/handlersRegistry.js
new file mode 100644
index 0000000..6875bd7
--- /dev/null
+++ b/dist/src/messageHandler/handlersRegistry.js
@@ -0,0 +1,20 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+class HandlersRegistry {
+ constructor() {
+ this.handlers = new Map();
+ }
+ registerHandler(messageType, handler) {
+ if (this.handlers.has(messageType))
+ return;
+ this.handlers.set(messageType, handler);
+ }
+ handle(client, message) {
+ const { type } = message;
+ const handler = this.handlers.get(type);
+ if (!handler)
+ return false;
+ return handler(client, message);
+ }
+}
+exports.HandlersRegistry = HandlersRegistry;
diff --git a/dist/src/messageHandler/index.js b/dist/src/messageHandler/index.js
new file mode 100644
index 0000000..c8393ca
--- /dev/null
+++ b/dist/src/messageHandler/index.js
@@ -0,0 +1,31 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const enums_1 = require("../enums");
+const handlers_1 = require("./handlers");
+const handlersRegistry_1 = require("./handlersRegistry");
+class MessageHandler {
+ constructor(realm, handlersRegistry = new handlersRegistry_1.HandlersRegistry()) {
+ this.handlersRegistry = handlersRegistry;
+ const transmissionHandler = handlers_1.TransmissionHandler({ realm });
+ const heartbeatHandler = handlers_1.HeartbeatHandler;
+ const handleTransmission = (client, { type, src, dst, payload }) => {
+ return transmissionHandler(client, {
+ type,
+ src,
+ dst,
+ payload,
+ });
+ };
+ const handleHeartbeat = (client, message) => heartbeatHandler(client, message);
+ this.handlersRegistry.registerHandler(enums_1.MessageType.HEARTBEAT, handleHeartbeat);
+ this.handlersRegistry.registerHandler(enums_1.MessageType.OFFER, handleTransmission);
+ this.handlersRegistry.registerHandler(enums_1.MessageType.ANSWER, handleTransmission);
+ this.handlersRegistry.registerHandler(enums_1.MessageType.CANDIDATE, handleTransmission);
+ this.handlersRegistry.registerHandler(enums_1.MessageType.LEAVE, handleTransmission);
+ this.handlersRegistry.registerHandler(enums_1.MessageType.EXPIRE, handleTransmission);
+ }
+ handle(client, message) {
+ return this.handlersRegistry.handle(client, message);
+ }
+}
+exports.MessageHandler = MessageHandler;
diff --git a/dist/src/messageHandler/messageHandlers.js b/dist/src/messageHandler/messageHandlers.js
new file mode 100644
index 0000000..01b1e06
--- /dev/null
+++ b/dist/src/messageHandler/messageHandlers.js
@@ -0,0 +1,20 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+class MessageHandlers {
+ constructor() {
+ this.handlers = new Map();
+ }
+ registerHandler(messageType, handler) {
+ if (this.handlers.has(messageType))
+ return;
+ this.handlers.set(messageType, handler);
+ }
+ handle(client, message) {
+ const { type } = message;
+ const handler = this.handlers.get(type);
+ if (!handler)
+ return false;
+ return handler(client, message);
+ }
+}
+exports.MessageHandlers = MessageHandlers;
diff --git a/dist/src/models/client.js b/dist/src/models/client.js
new file mode 100644
index 0000000..79473e4
--- /dev/null
+++ b/dist/src/models/client.js
@@ -0,0 +1,33 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+class Client {
+ constructor({ id, token }) {
+ this.socket = null;
+ this.lastPing = new Date().getTime();
+ this.id = id;
+ this.token = token;
+ }
+ getId() {
+ return this.id;
+ }
+ getToken() {
+ return this.token;
+ }
+ getSocket() {
+ return this.socket;
+ }
+ setSocket(socket) {
+ this.socket = socket;
+ }
+ getLastPing() {
+ return this.lastPing;
+ }
+ setLastPing(lastPing) {
+ this.lastPing = lastPing;
+ }
+ send(data) {
+ var _a;
+ (_a = this.socket) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify(data));
+ }
+}
+exports.Client = Client;
diff --git a/dist/src/models/message.js b/dist/src/models/message.js
new file mode 100644
index 0000000..c8ad2e5
--- /dev/null
+++ b/dist/src/models/message.js
@@ -0,0 +1,2 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
diff --git a/dist/src/models/messageQueue.js b/dist/src/models/messageQueue.js
new file mode 100644
index 0000000..fc04ea6
--- /dev/null
+++ b/dist/src/models/messageQueue.js
@@ -0,0 +1,25 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+class MessageQueue {
+ constructor() {
+ this.lastReadAt = new Date().getTime();
+ this.messages = [];
+ }
+ getLastReadAt() {
+ return this.lastReadAt;
+ }
+ addMessage(message) {
+ this.messages.push(message);
+ }
+ readMessage() {
+ if (this.messages.length > 0) {
+ this.lastReadAt = new Date().getTime();
+ return this.messages.shift();
+ }
+ return undefined;
+ }
+ getMessages() {
+ return this.messages;
+ }
+}
+exports.MessageQueue = MessageQueue;
diff --git a/dist/src/models/realm.js b/dist/src/models/realm.js
new file mode 100644
index 0000000..53fc672
--- /dev/null
+++ b/dist/src/models/realm.js
@@ -0,0 +1,52 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const v4_1 = __importDefault(require("uuid/v4"));
+const messageQueue_1 = require("./messageQueue");
+class Realm {
+ constructor() {
+ this.clients = new Map();
+ this.messageQueues = new Map();
+ }
+ getClientsIds() {
+ return [...this.clients.keys()];
+ }
+ getClientById(clientId) {
+ return this.clients.get(clientId);
+ }
+ getClientsIdsWithQueue() {
+ return [...this.messageQueues.keys()];
+ }
+ setClient(client, id) {
+ this.clients.set(id, client);
+ }
+ removeClientById(id) {
+ const client = this.getClientById(id);
+ if (!client)
+ return false;
+ this.clients.delete(id);
+ return true;
+ }
+ getMessageQueueById(id) {
+ return this.messageQueues.get(id);
+ }
+ addMessageToQueue(id, message) {
+ if (!this.getMessageQueueById(id)) {
+ this.messageQueues.set(id, new messageQueue_1.MessageQueue());
+ }
+ this.getMessageQueueById(id).addMessage(message);
+ }
+ clearMessageQueue(id) {
+ this.messageQueues.delete(id);
+ }
+ generateClientId() {
+ let clientId = v4_1.default();
+ while (this.getClientById(clientId)) {
+ clientId = v4_1.default();
+ }
+ return clientId;
+ }
+}
+exports.Realm = Realm;
diff --git a/dist/src/services/checkBrokenConnections/index.js b/dist/src/services/checkBrokenConnections/index.js
new file mode 100644
index 0000000..f0e7115
--- /dev/null
+++ b/dist/src/services/checkBrokenConnections/index.js
@@ -0,0 +1,50 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const DEFAULT_CHECK_INTERVAL = 300;
+class CheckBrokenConnections {
+ constructor({ realm, config, checkInterval = DEFAULT_CHECK_INTERVAL, onClose }) {
+ this.timeoutId = null;
+ this.realm = realm;
+ this.config = config;
+ this.onClose = onClose;
+ this.checkInterval = checkInterval;
+ }
+ start() {
+ if (this.timeoutId) {
+ clearTimeout(this.timeoutId);
+ }
+ this.timeoutId = setTimeout(() => {
+ this.checkConnections();
+ this.timeoutId = null;
+ this.start();
+ }, this.checkInterval);
+ }
+ stop() {
+ if (this.timeoutId) {
+ clearTimeout(this.timeoutId);
+ this.timeoutId = null;
+ }
+ }
+ checkConnections() {
+ var _a, _b, _c;
+ const clientsIds = this.realm.getClientsIds();
+ const now = new Date().getTime();
+ const { alive_timeout: aliveTimeout } = this.config;
+ for (const clientId of clientsIds) {
+ const client = this.realm.getClientById(clientId);
+ const timeSinceLastPing = now - client.getLastPing();
+ if (timeSinceLastPing < aliveTimeout)
+ continue;
+ try {
+ (_a = client.getSocket()) === null || _a === void 0 ? void 0 : _a.close();
+ }
+ finally {
+ this.realm.clearMessageQueue(clientId);
+ this.realm.removeClientById(clientId);
+ client.setSocket(null);
+ (_c = (_b = this).onClose) === null || _c === void 0 ? void 0 : _c.call(_b, client);
+ }
+ }
+ }
+}
+exports.CheckBrokenConnections = CheckBrokenConnections;
diff --git a/dist/src/services/messagesExpire/index.js b/dist/src/services/messagesExpire/index.js
new file mode 100644
index 0000000..9e9d6f2
--- /dev/null
+++ b/dist/src/services/messagesExpire/index.js
@@ -0,0 +1,53 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const enums_1 = require("../../enums");
+class MessagesExpire {
+ constructor({ realm, config, messageHandler }) {
+ this.timeoutId = null;
+ this.realm = realm;
+ this.config = config;
+ this.messageHandler = messageHandler;
+ }
+ startMessagesExpiration() {
+ if (this.timeoutId) {
+ clearTimeout(this.timeoutId);
+ }
+ // Clean up outstanding messages
+ this.timeoutId = setTimeout(() => {
+ this.pruneOutstanding();
+ this.timeoutId = null;
+ this.startMessagesExpiration();
+ }, this.config.cleanup_out_msgs);
+ }
+ stopMessagesExpiration() {
+ if (this.timeoutId) {
+ clearTimeout(this.timeoutId);
+ this.timeoutId = null;
+ }
+ }
+ pruneOutstanding() {
+ const destinationClientsIds = this.realm.getClientsIdsWithQueue();
+ const now = new Date().getTime();
+ const maxDiff = this.config.expire_timeout;
+ const seen = {};
+ for (const destinationClientId of destinationClientsIds) {
+ const messageQueue = this.realm.getMessageQueueById(destinationClientId);
+ const lastReadDiff = now - messageQueue.getLastReadAt();
+ if (lastReadDiff < maxDiff)
+ continue;
+ const messages = messageQueue.getMessages();
+ for (const message of messages) {
+ if (!seen[message.src]) {
+ this.messageHandler.handle(undefined, {
+ type: enums_1.MessageType.EXPIRE,
+ src: message.dst,
+ dst: message.src
+ });
+ seen[message.src] = true;
+ }
+ }
+ this.realm.clearMessageQueue(destinationClientId);
+ }
+ }
+}
+exports.MessagesExpire = MessagesExpire;
diff --git a/dist/src/services/webSocketServer/index.js b/dist/src/services/webSocketServer/index.js
new file mode 100644
index 0000000..fde0b03
--- /dev/null
+++ b/dist/src/services/webSocketServer/index.js
@@ -0,0 +1,92 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const events_1 = __importDefault(require("events"));
+const url_1 = __importDefault(require("url"));
+const ws_1 = __importDefault(require("ws"));
+const enums_1 = require("../../enums");
+const client_1 = require("../../models/client");
+const WS_PATH = 'peerjs';
+class WebSocketServer extends events_1.default {
+ constructor({ server, realm, config }) {
+ super();
+ this.setMaxListeners(0);
+ this.realm = realm;
+ this.config = config;
+ const path = this.config.path;
+ this.path = `${path}${path.endsWith('/') ? "" : "/"}${WS_PATH}`;
+ this.socketServer = new ws_1.default.Server({ path: this.path, server });
+ this.socketServer.on("connection", (socket, req) => this._onSocketConnection(socket, req));
+ this.socketServer.on("error", (error) => this._onSocketError(error));
+ }
+ _onSocketConnection(socket, req) {
+ const { query = {} } = url_1.default.parse(req.url, true);
+ const { id, token, key } = query;
+ if (!id || !token || !key) {
+ return this._sendErrorAndClose(socket, enums_1.Errors.INVALID_WS_PARAMETERS);
+ }
+ if (key !== this.config.key) {
+ return this._sendErrorAndClose(socket, enums_1.Errors.INVALID_KEY);
+ }
+ const client = this.realm.getClientById(id);
+ if (client) {
+ if (token !== client.getToken()) {
+ // ID-taken, invalid token
+ socket.send(JSON.stringify({
+ type: enums_1.MessageType.ID_TAKEN,
+ payload: { msg: "ID is taken" }
+ }));
+ return socket.close();
+ }
+ return this._configureWS(socket, client);
+ }
+ this._registerClient({ socket, id, token });
+ }
+ _onSocketError(error) {
+ // handle error
+ this.emit("error", error);
+ }
+ _registerClient({ socket, id, token }) {
+ // Check concurrent limit
+ const clientsCount = this.realm.getClientsIds().length;
+ if (clientsCount >= this.config.concurrent_limit) {
+ return this._sendErrorAndClose(socket, enums_1.Errors.CONNECTION_LIMIT_EXCEED);
+ }
+ const newClient = new client_1.Client({ id, token });
+ this.realm.setClient(newClient, id);
+ socket.send(JSON.stringify({ type: enums_1.MessageType.OPEN }));
+ this._configureWS(socket, newClient);
+ }
+ _configureWS(socket, client) {
+ client.setSocket(socket);
+ // Cleanup after a socket closes.
+ socket.on("close", () => {
+ if (client.getSocket() === socket) {
+ this.realm.removeClientById(client.getId());
+ this.emit("close", client);
+ }
+ });
+ // Handle messages from peers.
+ socket.on("message", (data) => {
+ try {
+ const message = JSON.parse(data);
+ message.src = client.getId();
+ this.emit("message", client, message);
+ }
+ catch (e) {
+ this.emit("error", e);
+ }
+ });
+ this.emit("connection", client);
+ }
+ _sendErrorAndClose(socket, msg) {
+ socket.send(JSON.stringify({
+ type: enums_1.MessageType.ERROR,
+ payload: { msg }
+ }));
+ socket.close();
+ }
+}
+exports.WebSocketServer = WebSocketServer;
diff --git a/dist/src/services/webSocketServer/webSocket.js b/dist/src/services/webSocketServer/webSocket.js
new file mode 100644
index 0000000..c8ad2e5
--- /dev/null
+++ b/dist/src/services/webSocketServer/webSocket.js
@@ -0,0 +1,2 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
diff --git a/package-lock.json b/package-lock.json
index 0131cba..3f43aaa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -22,14 +22,6 @@
"chalk": "^2.0.0",
"esutils": "^2.0.2",
"js-tokens": "^4.0.0"
- },
- "dependencies": {
- "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
- }
}
},
"@sinonjs/commons": {
@@ -42,9 +34,9 @@
}
},
"@sinonjs/formatio": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz",
- "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==",
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz",
+ "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==",
"dev": true,
"requires": {
"@sinonjs/commons": "^1",
@@ -68,6 +60,209 @@
"integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==",
"dev": true
},
+ "@types/body-parser": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.1.tgz",
+ "integrity": "sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w==",
+ "requires": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/chai": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.0.tgz",
+ "integrity": "sha512-zw8UvoBEImn392tLjxoavuonblX/4Yb9ha4KBU10FirCfwgzhKO0dvyJSF9ByxV1xK1r2AgnAi/tvQaLgxQqxA==",
+ "dev": true
+ },
+ "@types/connect": {
+ "version": "3.4.32",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
+ "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/cors": {
+ "version": "2.8.6",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.6.tgz",
+ "integrity": "sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==",
+ "requires": {
+ "@types/express": "*"
+ }
+ },
+ "@types/eslint-visitor-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+ "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
+ "dev": true
+ },
+ "@types/express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-VfH/XCP0QbQk5B5puLqTLEeFgR8lfCJHZJKkInZ9mkYd+u8byX0kztXEQxEk4wZXJs8HI+7km2ALXjn4YKcX9w==",
+ "requires": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "@types/express-serve-static-core": {
+ "version": "4.16.9",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.9.tgz",
+ "integrity": "sha512-GqpaVWR0DM8FnRUJYKlWgyARoBUAVfRIeVDZQKOttLFp5SmhhF9YFIYeTPwMd/AXfxlP7xVO2dj1fGu0Q+krKQ==",
+ "requires": {
+ "@types/node": "*",
+ "@types/range-parser": "*"
+ }
+ },
+ "@types/json-schema": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz",
+ "integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==",
+ "dev": true
+ },
+ "@types/mime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz",
+ "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw=="
+ },
+ "@types/mocha": {
+ "version": "5.2.7",
+ "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
+ "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "10.14.16",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.16.tgz",
+ "integrity": "sha512-/opXIbfn0P+VLt+N8DE4l8Mn8rbhiJgabU96ZJ0p9mxOkIks5gh6RUnpHak7Yh0SFkyjO/ODbxsQQPV2bpMmyA=="
+ },
+ "@types/range-parser": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
+ "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
+ },
+ "@types/serve-static": {
+ "version": "1.13.3",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz",
+ "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==",
+ "requires": {
+ "@types/express-serve-static-core": "*",
+ "@types/mime": "*"
+ }
+ },
+ "@types/uuid": {
+ "version": "3.4.6",
+ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.6.tgz",
+ "integrity": "sha512-cCdlC/1kGEZdEglzOieLDYBxHsvEOIg7kp/2FYyVR9Pxakq+Qf/inL3RKQ+PA8gOlI/NnL+fXmQH12nwcGzsHw==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/ws": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz",
+ "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@typescript-eslint/eslint-plugin": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.11.0.tgz",
+ "integrity": "sha512-G2HHA1vpMN0EEbUuWubiCCfd0R3a30BB+UdvnFkxwZIxYEGOrWEXDv8tBFO9f44CWc47Xv9lLM3VSn4ORLI2bA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/experimental-utils": "2.11.0",
+ "eslint-utils": "^1.4.3",
+ "functional-red-black-tree": "^1.0.1",
+ "regexpp": "^3.0.0",
+ "tsutils": "^3.17.1"
+ }
+ },
+ "@typescript-eslint/experimental-utils": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.11.0.tgz",
+ "integrity": "sha512-YxcA/y0ZJaCc/fB/MClhcDxHI0nOBB7v2/WxBju2cOTanX7jO9ttQq6Fy4yW9UaY5bPd9xL3cun3lDVqk67sPQ==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.3",
+ "@typescript-eslint/typescript-estree": "2.11.0",
+ "eslint-scope": "^5.0.0"
+ }
+ },
+ "@typescript-eslint/parser": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.11.0.tgz",
+ "integrity": "sha512-DyGXeqhb3moMioEFZIHIp7oXBBh7dEfPTzGrlyP0Mi9ScCra4SWEGs3kPd18mG7Sy9Wy8z88zmrw5tSGL6r/6A==",
+ "dev": true,
+ "requires": {
+ "@types/eslint-visitor-keys": "^1.0.0",
+ "@typescript-eslint/experimental-utils": "2.11.0",
+ "@typescript-eslint/typescript-estree": "2.11.0",
+ "eslint-visitor-keys": "^1.1.0"
+ }
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.11.0.tgz",
+ "integrity": "sha512-HGY4+d4MagO6cKMcKfIKaTMxcAv7dEVnji2Zi+vi5VV8uWAM631KjAB5GxFcexMYrwKT0EekRiiGK1/Sd7VFGA==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.1",
+ "eslint-visitor-keys": "^1.1.0",
+ "glob": "^7.1.6",
+ "is-glob": "^4.0.1",
+ "lodash.unescape": "4.0.1",
+ "semver": "^6.3.0",
+ "tsutils": "^3.17.1"
+ },
+ "dependencies": {
+ "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"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
"accepts": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
@@ -78,15 +273,15 @@
}
},
"acorn": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz",
- "integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
+ "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
"dev": true
},
"acorn-jsx": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.2.tgz",
- "integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz",
+ "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==",
"dev": true
},
"ajv": {
@@ -101,6 +296,15 @@
"uri-js": "^4.2.2"
}
},
+ "ansi-align": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
+ "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.0.0"
+ }
+ },
"ansi-colors": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
@@ -108,12 +312,12 @@
"dev": true
},
"ansi-escapes": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz",
- "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz",
+ "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==",
"dev": true,
"requires": {
- "type-fest": "^0.5.2"
+ "type-fest": "^0.8.1"
}
},
"ansi-regex": {
@@ -131,6 +335,33 @@
"color-convert": "^1.9.0"
}
},
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ },
+ "dependencies": {
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ }
+ }
+ },
+ "arg": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.2.tgz",
+ "integrity": "sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg==",
+ "dev": true
+ },
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -140,6 +371,24 @@
"sprintf-js": "~1.0.2"
}
},
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "dev": true
+ },
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@@ -151,15 +400,11 @@
"integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=",
"dev": true
},
- "array-includes": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
- "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.2",
- "es-abstract": "^1.7.0"
- }
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true
},
"assertion-error": {
"version": "1.1.0",
@@ -167,23 +412,102 @@
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
"dev": true
},
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "dev": true
+ },
"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-each": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
+ "dev": true
+ },
"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=="
},
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+ "dev": true
+ },
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "dev": true,
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+ "dev": true
+ },
"body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
@@ -211,6 +535,29 @@
}
}
},
+ "boxen": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
+ "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==",
+ "dev": true,
+ "requires": {
+ "ansi-align": "^2.0.0",
+ "camelcase": "^4.0.0",
+ "chalk": "^2.0.1",
+ "cli-boxes": "^1.0.0",
+ "string-width": "^2.0.0",
+ "term-size": "^1.2.0",
+ "widest-line": "^2.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+ "dev": true
+ }
+ }
+ },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -221,17 +568,69 @@
"concat-map": "0.0.1"
}
},
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
"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
},
+ "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==",
+ "dev": true
+ },
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
},
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "dev": true,
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
"callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -244,6 +643,12 @@
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
+ "capture-stack-trace": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
+ "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==",
+ "dev": true
+ },
"chai": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
@@ -292,6 +697,84 @@
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
"dev": true
},
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dev": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ }
+ }
+ },
+ "ci-info": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
+ "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
+ "dev": true
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "cli-boxes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
+ "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=",
+ "dev": true
+ },
"cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@@ -308,21 +791,59 @@
"dev": true
},
"cliui": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
- "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"dev": true,
"requires": {
- "string-width": "^2.1.1",
- "strip-ansi": "^4.0.0",
- "wrap-ansi": "^2.0.0"
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-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
+ },
+ "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
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "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"
+ }
+ }
}
},
- "code-point-at": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
- "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dev": true,
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
},
"color-convert": {
"version": "1.9.3",
@@ -339,17 +860,31 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+ "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=",
"dev": true
},
- "contains-path": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
- "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
- "dev": true
+ "configstore": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
+ "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^4.1.0",
+ "graceful-fs": "^4.1.2",
+ "make-dir": "^1.0.0",
+ "unique-string": "^1.0.0",
+ "write-file-atomic": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ }
},
"content-disposition": {
"version": "0.5.3",
@@ -374,15 +909,36 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
"cors": {
- "version": "2.8.5",
- "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
- "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "version": "2.8.4",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz",
+ "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=",
"requires": {
"object-assign": "^4",
"vary": "^1"
}
},
+ "create-error-class": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
+ "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
+ "dev": true,
+ "requires": {
+ "capture-stack-trace": "^1.0.0"
+ }
+ },
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -396,6 +952,12 @@
"which": "^1.2.9"
}
},
+ "crypto-random-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
+ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=",
+ "dev": true
+ },
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -404,18 +966,18 @@
"ms": "2.0.0"
}
},
- "debug-log": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz",
- "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=",
- "dev": true
- },
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
"dev": true
},
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true
+ },
"deep-eql": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
@@ -425,6 +987,12 @@
"type-detect": "^4.0.0"
}
},
+ "deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true
+ },
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -440,25 +1008,44 @@
"object-keys": "^1.0.12"
}
},
- "deglob": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/deglob/-/deglob-4.0.0.tgz",
- "integrity": "sha512-nrUWPTcQ4ap7KWCSeWNDXUgIe4A3nSbsp9cmWrxbKOOxUxLpAVzU1aeatYZfjE+lVHO1lUjXpBmoxOgPYbV5lg==",
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
"dev": true,
"requires": {
- "find-root": "^1.0.0",
- "glob": "^7.0.5",
- "ignore": "^5.0.0",
- "pkg-config": "^1.1.0",
- "run-parallel": "^1.1.2",
- "uniq": "^1.0.1"
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
},
"dependencies": {
- "ignore": {
- "version": "5.1.4",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz",
- "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==",
- "dev": true
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
}
}
},
@@ -487,15 +1074,30 @@
"esutils": "^2.0.2"
}
},
+ "dot-prop": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
+ "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
+ "dev": true,
+ "requires": {
+ "is-obj": "^1.0.0"
+ }
+ },
+ "duplexer3": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
+ "dev": true
+ },
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"encodeurl": {
@@ -503,15 +1105,6 @@
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
- "end-of-stream": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
- "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
- "dev": true,
- "requires": {
- "once": "^1.4.0"
- }
- },
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -558,9 +1151,9 @@
"dev": true
},
"eslint": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.2.1.tgz",
- "integrity": "sha512-ES7BzEzr0Q6m5TK9i+/iTpKjclXitOdDK4vT07OqbkBT2/VcN/gO9EL1C4HlK3TAOXYv2ItcmbVR9jO1MR0fJg==",
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.7.2.tgz",
+ "integrity": "sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
@@ -570,19 +1163,19 @@
"debug": "^4.0.1",
"doctrine": "^3.0.0",
"eslint-scope": "^5.0.0",
- "eslint-utils": "^1.4.2",
+ "eslint-utils": "^1.4.3",
"eslint-visitor-keys": "^1.1.0",
- "espree": "^6.1.0",
+ "espree": "^6.1.2",
"esquery": "^1.0.1",
"esutils": "^2.0.2",
"file-entry-cache": "^5.0.1",
"functional-red-black-tree": "^1.0.1",
"glob-parent": "^5.0.0",
- "globals": "^11.7.0",
+ "globals": "^12.1.0",
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
- "inquirer": "^6.4.1",
+ "inquirer": "^7.0.0",
"is-glob": "^4.0.0",
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
@@ -591,7 +1184,7 @@
"minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
- "optionator": "^0.8.2",
+ "optionator": "^0.8.3",
"progress": "^2.0.0",
"regexpp": "^2.0.1",
"semver": "^6.1.2",
@@ -617,46 +1210,18 @@
"ms": "^2.1.1"
}
},
- "doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2"
- }
- },
- "eslint-utils": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz",
- "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==",
- "dev": true,
- "requires": {
- "eslint-visitor-keys": "^1.0.0"
- }
- },
- "js-yaml": {
- "version": "3.13.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
- "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
- "dev": true,
- "requires": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- }
- },
- "lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
- "dev": true
- },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
+ "regexpp": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+ "dev": true
+ },
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -680,153 +1245,6 @@
}
}
},
- "eslint-config-semistandard": {
- "version": "15.0.0",
- "resolved": "https://registry.npmjs.org/eslint-config-semistandard/-/eslint-config-semistandard-15.0.0.tgz",
- "integrity": "sha512-volIMnosUvzyxGkYUA5QvwkahZZLeUx7wcS0+7QumPn+MMEBbV6P7BY1yukamMst0w3Et3QZlCjQEwQ8tQ6nug==",
- "dev": true
- },
- "eslint-config-standard": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.0.0.tgz",
- "integrity": "sha512-bV6e2LFvJEetrLjVAy4KWPOUsIhPWr040c649MigTPR6yUtaGuOt6CEAyNeez2lRiC+2+vjGWa02byjs25EB3A==",
- "dev": true
- },
- "eslint-config-standard-jsx": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-8.0.0.tgz",
- "integrity": "sha512-Abs/WP+638KfkHI1J961yAztpMhYFvEMTqD4GMUZObAO9yOmLaQZlJY6xke1ty1+zhY4G58AuvHo3ht6avAEVQ==",
- "dev": true
- },
- "eslint-import-resolver-node": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz",
- "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==",
- "dev": true,
- "requires": {
- "debug": "^2.6.9",
- "resolve": "^1.5.0"
- }
- },
- "eslint-module-utils": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz",
- "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==",
- "dev": true,
- "requires": {
- "debug": "^2.6.8",
- "pkg-dir": "^2.0.0"
- }
- },
- "eslint-plugin-es": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz",
- "integrity": "sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw==",
- "dev": true,
- "requires": {
- "eslint-utils": "^1.3.0",
- "regexpp": "^2.0.1"
- }
- },
- "eslint-plugin-import": {
- "version": "2.18.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz",
- "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==",
- "dev": true,
- "requires": {
- "array-includes": "^3.0.3",
- "contains-path": "^0.1.0",
- "debug": "^2.6.9",
- "doctrine": "1.5.0",
- "eslint-import-resolver-node": "^0.3.2",
- "eslint-module-utils": "^2.4.0",
- "has": "^1.0.3",
- "minimatch": "^3.0.4",
- "object.values": "^1.1.0",
- "read-pkg-up": "^2.0.0",
- "resolve": "^1.11.0"
- },
- "dependencies": {
- "doctrine": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
- "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2",
- "isarray": "^1.0.0"
- }
- }
- }
- },
- "eslint-plugin-node": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-9.1.0.tgz",
- "integrity": "sha512-ZwQYGm6EoV2cfLpE1wxJWsfnKUIXfM/KM09/TlorkukgCAwmkgajEJnPCmyzoFPQQkmvo5DrW/nyKutNIw36Mw==",
- "dev": true,
- "requires": {
- "eslint-plugin-es": "^1.4.0",
- "eslint-utils": "^1.3.1",
- "ignore": "^5.1.1",
- "minimatch": "^3.0.4",
- "resolve": "^1.10.1",
- "semver": "^6.1.0"
- },
- "dependencies": {
- "ignore": {
- "version": "5.1.4",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz",
- "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==",
- "dev": true
- },
- "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-plugin-promise": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz",
- "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==",
- "dev": true
- },
- "eslint-plugin-react": {
- "version": "7.14.3",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz",
- "integrity": "sha512-EzdyyBWC4Uz2hPYBiEJrKCUi2Fn+BJ9B/pJQcjw5X+x/H2Nm59S4MJIvL4O5NEE0+WbnQwEBxWY03oUk+Bc3FA==",
- "dev": true,
- "requires": {
- "array-includes": "^3.0.3",
- "doctrine": "^2.1.0",
- "has": "^1.0.3",
- "jsx-ast-utils": "^2.1.0",
- "object.entries": "^1.1.0",
- "object.fromentries": "^2.0.0",
- "object.values": "^1.1.0",
- "prop-types": "^15.7.2",
- "resolve": "^1.10.1"
- },
- "dependencies": {
- "doctrine": {
- "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"
- }
- }
- }
- },
- "eslint-plugin-standard": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz",
- "integrity": "sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ==",
- "dev": true
- },
"eslint-scope": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
@@ -838,12 +1256,12 @@
}
},
"eslint-utils": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz",
- "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==",
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+ "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
"dev": true,
"requires": {
- "eslint-visitor-keys": "^1.0.0"
+ "eslint-visitor-keys": "^1.1.0"
}
},
"eslint-visitor-keys": {
@@ -853,13 +1271,13 @@
"dev": true
},
"espree": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.0.tgz",
- "integrity": "sha512-boA7CHRLlVWUSg3iL5Kmlt/xT3Q+sXnKoRYYzj1YeM10A76TEJBbotV5pKbnK42hEUIr121zTv+QLRM5LsCPXQ==",
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz",
+ "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==",
"dev": true,
"requires": {
- "acorn": "^7.0.0",
- "acorn-jsx": "^5.0.0",
+ "acorn": "^7.1.0",
+ "acorn-jsx": "^5.1.0",
"eslint-visitor-keys": "^1.1.0"
}
},
@@ -894,9 +1312,9 @@
"dev": true
},
"esutils": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
- "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true
},
"etag": {
@@ -904,19 +1322,39 @@
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
- "execa": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
- "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
"dev": true,
"requires": {
- "cross-spawn": "^6.0.0",
- "get-stream": "^4.0.0",
- "is-stream": "^1.1.0",
- "npm-run-path": "^2.0.0",
- "p-finally": "^1.0.0",
- "signal-exit": "^3.0.0",
- "strip-eof": "^1.0.0"
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
}
},
"express": {
@@ -956,6 +1394,27 @@
"vary": "~1.1.2"
}
},
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dev": true,
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
"external-editor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
@@ -965,15 +1424,69 @@
"chardet": "^0.7.0",
"iconv-lite": "^0.4.24",
"tmp": "^0.0.33"
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dev": true,
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
},
"dependencies": {
- "iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
"dev": true,
"requires": {
- "safer-buffer": ">= 2.1.2 < 3"
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
}
}
}
@@ -985,9 +1498,9 @@
"dev": true
},
"fast-json-stable-stringify": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
- "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+ "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
},
"fast-levenshtein": {
@@ -997,9 +1510,9 @@
"dev": true
},
"figures": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/figures/-/figures-3.0.0.tgz",
- "integrity": "sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz",
+ "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==",
"dev": true,
"requires": {
"escape-string-regexp": "^1.0.5"
@@ -1014,6 +1527,29 @@
"flat-cache": "^2.0.1"
}
},
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
"finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
@@ -1028,12 +1564,6 @@
"unpipe": "~1.0.0"
}
},
- "find-root": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
- "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
- "dev": true
- },
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
@@ -1061,6 +1591,17 @@
"flatted": "^2.0.0",
"rimraf": "2.6.3",
"write": "1.0.3"
+ },
+ "dependencies": {
+ "rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ }
}
},
"flatted": {
@@ -1069,11 +1610,26 @@
"integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
"dev": true
},
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
},
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@@ -1085,6 +1641,554 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
+ "fsevents": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
+ "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "nan": "^2.12.1",
+ "node-pre-gyp": "^0.12.0"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "fs-minipass": {
+ "version": "1.2.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minipass": {
+ "version": "2.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.2.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "needle": {
+ "version": "2.3.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.12.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "npm-packlist": {
+ "version": "1.4.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "5.7.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "4.4.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.3.4",
+ "minizlib": "^1.1.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.2"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -1109,21 +2213,12 @@
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
"dev": true
},
- "get-stdin": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz",
- "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==",
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
"dev": true
},
- "get-stream": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
- "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
- "dev": true,
- "requires": {
- "pump": "^3.0.0"
- }
- },
"glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
@@ -1139,19 +2234,58 @@
}
},
"glob-parent": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz",
- "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
+ "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
},
+ "global-dirs": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
+ "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
+ "dev": true,
+ "requires": {
+ "ini": "^1.3.4"
+ }
+ },
"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
+ "version": "12.3.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz",
+ "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.8.1"
+ }
+ },
+ "got": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
+ "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
+ "dev": true,
+ "requires": {
+ "create-error-class": "^3.0.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^3.0.0",
+ "is-redirect": "^1.0.0",
+ "is-retry-allowed": "^1.0.0",
+ "is-stream": "^1.0.0",
+ "lowercase-keys": "^1.0.0",
+ "safe-buffer": "^5.0.1",
+ "timed-out": "^4.0.0",
+ "unzip-response": "^2.0.1",
+ "url-parse-lax": "^1.0.0"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ }
+ }
},
"graceful-fs": {
"version": "4.2.2",
@@ -1186,6 +2320,44 @@
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
"dev": true
},
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
@@ -1210,22 +2382,43 @@
"toidentifier": "1.0.0"
}
},
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
"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
},
+ "ignore-by-default": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=",
+ "dev": true
+ },
"import-fresh": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz",
- "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==",
+ "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==",
"dev": true,
"requires": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
}
},
+ "import-lazy": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+ "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
+ "dev": true
+ },
"imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -1247,10 +2440,16 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "dev": true
+ },
"inquirer": {
- "version": "6.5.1",
- "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.1.tgz",
- "integrity": "sha512-uxNHBeQhRXIoHWTSNYUFhQVrHYFThIt6IVo2fFmSe8aBwdR3/w6b58hJpiL/fMukFkvGzjg+hSxFtwvVmKZmXw==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz",
+ "integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==",
"dev": true,
"requires": {
"ansi-escapes": "^4.2.1",
@@ -1269,15 +2468,9 @@
},
"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
- },
- "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==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"dev": true
},
"is-fullwidth-code-point": {
@@ -1286,21 +2479,26 @@
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
- "lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
- "dev": true
- },
"string-width": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz",
- "integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+ "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^5.2.0"
+ "strip-ansi": "^6.0.0"
+ },
+ "dependencies": {
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ }
}
},
"strip-ansi": {
@@ -1310,31 +2508,68 @@
"dev": true,
"requires": {
"ansi-regex": "^4.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
+ }
}
}
}
},
- "invert-kv": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
- "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
- "dev": true
- },
"ipaddr.js": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
"integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
},
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
"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-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
"is-buffer": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
- "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
+ "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==",
"dev": true
},
"is-callable": {
@@ -1343,12 +2578,72 @@
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
"dev": true
},
+ "is-ci": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
+ "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^1.5.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
"is-date-object": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
"dev": true
},
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true
+ }
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true
+ },
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -1370,12 +2665,84 @@
"is-extglob": "^2.1.1"
}
},
+ "is-installed-globally": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
+ "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
+ "dev": true,
+ "requires": {
+ "global-dirs": "^0.1.0",
+ "is-path-inside": "^1.0.0"
+ }
+ },
+ "is-npm": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
+ "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=",
+ "dev": true
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+ "dev": true
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "^1.0.1"
+ }
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
"is-promise": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
"dev": true
},
+ "is-redirect": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
+ "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=",
+ "dev": true
+ },
"is-regex": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
@@ -1385,6 +2752,12 @@
"has": "^1.0.1"
}
},
+ "is-retry-allowed": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz",
+ "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=",
+ "dev": true
+ },
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
@@ -1400,6 +2773,12 @@
"has-symbols": "^1.0.0"
}
},
+ "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": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -1412,6 +2791,12 @@
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -1446,29 +2831,25 @@
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
"dev": true
},
- "jsx-ast-utils": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.1.tgz",
- "integrity": "sha512-v3FxCcAf20DayI+uxnCuw795+oOIkVu6EnJ1+kSzhqqTZHNkTZ7B66ZgLp4oLJ/gbA64cI0B7WRoHZMSRdyVRQ==",
- "dev": true,
- "requires": {
- "array-includes": "^3.0.3",
- "object.assign": "^4.1.0"
- }
- },
"just-extend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz",
"integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==",
"dev": true
},
- "lcid": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
- "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "kind-of": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "dev": true
+ },
+ "latest-version": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
+ "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
"dev": true,
"requires": {
- "invert-kv": "^2.0.0"
+ "package-json": "^4.0.0"
}
},
"levn": {
@@ -1482,14 +2863,14 @@
}
},
"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=",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
- "parse-json": "^2.2.0",
- "pify": "^2.0.0",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
"strip-bom": "^3.0.0"
}
},
@@ -1509,6 +2890,12 @@
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
},
+ "lodash.unescape": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz",
+ "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=",
+ "dev": true
+ },
"log-symbols": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
@@ -1524,22 +2911,50 @@
"integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==",
"dev": true
},
- "loose-envify": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
- "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "lowercase-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
"dev": true,
"requires": {
- "js-tokens": "^3.0.0 || ^4.0.0"
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
}
},
- "map-age-cleaner": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
- "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
"dev": true,
"requires": {
- "p-defer": "^1.0.0"
+ "pify": "^3.0.0"
+ }
+ },
+ "make-error": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
+ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
+ "dev": true
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "dev": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dev": true,
+ "requires": {
+ "object-visit": "^1.0.0"
}
},
"media-typer": {
@@ -1547,16 +2962,11 @@
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
- "mem": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
- "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
- "dev": true,
- "requires": {
- "map-age-cleaner": "^0.1.1",
- "mimic-fn": "^2.0.0",
- "p-is-promise": "^2.0.0"
- }
+ "memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=",
+ "dev": true
},
"merge-descriptors": {
"version": "1.0.1",
@@ -1568,6 +2978,27 @@
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
@@ -1606,6 +3037,27 @@
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
},
+ "mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "dev": true,
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
@@ -1624,9 +3076,9 @@
}
},
"mocha": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz",
- "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==",
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.2.tgz",
+ "integrity": "sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A==",
"dev": true,
"requires": {
"ansi-colors": "3.2.3",
@@ -1649,9 +3101,9 @@
"supports-color": "6.0.0",
"which": "1.3.1",
"wide-align": "1.1.3",
- "yargs": "13.2.2",
- "yargs-parser": "13.0.0",
- "yargs-unparser": "1.5.0"
+ "yargs": "13.3.0",
+ "yargs-parser": "13.1.1",
+ "yargs-unparser": "1.6.0"
},
"dependencies": {
"debug": {
@@ -1671,6 +3123,15 @@
}
}
},
+ "mock-socket": {
+ "version": "8.0.5",
+ "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-8.0.5.tgz",
+ "integrity": "sha512-dE2EbcxJKQCeYLZSsI7BAiMZCe/bHbJ2LHb5aGwUuDmfoOINEJ8QI6qYJ85NHsSNkNa90F3s6onZcmt/+MppFA==",
+ "dev": true,
+ "requires": {
+ "url-parse": "^1.2.0"
+ }
+ },
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -1682,6 +3143,32 @@
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
"dev": true
},
+ "nan": {
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
+ "dev": true,
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
"natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -1700,9 +3187,9 @@
"dev": true
},
"nise": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.1.tgz",
- "integrity": "sha512-edFWm0fsFG2n318rfEnKlTZTkjlbVOFF9XIA+fj+Ed+Qz1laYW2lobwavWoMzGrYDHH1EpiNJgDfvGnkZztR/g==",
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz",
+ "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==",
"dev": true,
"requires": {
"@sinonjs/formatio": "^3.2.1",
@@ -1719,9 +3206,9 @@
"dev": true
},
"path-to-regexp": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
- "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+ "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"dev": true,
"requires": {
"isarray": "0.0.1"
@@ -1739,6 +3226,50 @@
"semver": "^5.7.0"
}
},
+ "nodemon": {
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.1.tgz",
+ "integrity": "sha512-/DXLzd/GhiaDXXbGId5BzxP1GlsqtMGM9zTmkWrgXtSqjKmGSbLicM/oAy4FR0YWm14jCHRwnR31AHS2dYFHrg==",
+ "dev": true,
+ "requires": {
+ "chokidar": "^2.1.5",
+ "debug": "^3.1.0",
+ "ignore-by-default": "^1.0.1",
+ "minimatch": "^3.0.4",
+ "pstree.remy": "^1.1.6",
+ "semver": "^5.5.0",
+ "supports-color": "^5.2.0",
+ "touch": "^3.1.0",
+ "undefsafe": "^2.0.2",
+ "update-notifier": "^2.5.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
"normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@@ -1751,6 +3282,29 @@
"validate-npm-package-license": "^3.0.1"
}
},
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "npm-run-all": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
+ "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "chalk": "^2.4.1",
+ "cross-spawn": "^6.0.5",
+ "memorystream": "^0.3.1",
+ "minimatch": "^3.0.4",
+ "pidtree": "^0.3.0",
+ "read-pkg": "^3.0.0",
+ "shell-quote": "^1.6.1",
+ "string.prototype.padend": "^3.0.0"
+ }
+ },
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -1760,23 +3314,69 @@
"path-key": "^2.0.0"
}
},
- "number-is-nan": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
- "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true
- },
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dev": true,
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-inspect": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
+ "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
+ "dev": true
+ },
"object-keys": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz",
"integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==",
"dev": true
},
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
"object.assign": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
@@ -1789,50 +3389,67 @@
"object-keys": "^1.0.11"
}
},
- "object.entries": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz",
- "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.12.0",
- "function-bind": "^1.1.1",
- "has": "^1.0.3"
- }
- },
- "object.fromentries": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz",
- "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.2",
- "es-abstract": "^1.11.0",
- "function-bind": "^1.1.1",
- "has": "^1.0.1"
- }
- },
"object.getownpropertydescriptors": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
- "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.2",
- "es-abstract": "^1.5.1"
- }
- },
- "object.values": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz",
- "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz",
+ "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
- "es-abstract": "^1.12.0",
- "function-bind": "^1.1.1",
- "has": "^1.0.3"
+ "es-abstract": "^1.17.0-next.1"
+ },
+ "dependencies": {
+ "es-abstract": {
+ "version": "1.17.0-next.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz",
+ "integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==",
+ "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.1.4",
+ "is-regex": "^1.0.4",
+ "object-inspect": "^1.7.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.0",
+ "string.prototype.trimleft": "^2.1.0",
+ "string.prototype.trimright": "^2.1.0"
+ }
+ },
+ "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,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "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
+ },
+ "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
+ }
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
}
},
"on-finished": {
@@ -1871,36 +3488,17 @@
}
},
"optionator": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
- "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
"dev": true,
"requires": {
"deep-is": "~0.1.3",
- "fast-levenshtein": "~2.0.4",
+ "fast-levenshtein": "~2.0.6",
"levn": "~0.3.0",
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2",
- "wordwrap": "~1.0.0"
- },
- "dependencies": {
- "wordwrap": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
- "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
- "dev": true
- }
- }
- },
- "os-locale": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
- "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
- "dev": true,
- "requires": {
- "execa": "^1.0.0",
- "lcid": "^2.0.0",
- "mem": "^4.0.0"
+ "word-wrap": "~1.2.3"
}
},
"os-tmpdir": {
@@ -1909,24 +3507,12 @@
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
- "p-defer": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
- "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
- "dev": true
- },
"p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
"dev": true
},
- "p-is-promise": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
- "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
- "dev": true
- },
"p-limit": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
@@ -1951,6 +3537,18 @@
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
+ "package-json": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
+ "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
+ "dev": true,
+ "requires": {
+ "got": "^6.7.1",
+ "registry-auth-token": "^3.0.1",
+ "registry-url": "^3.0.3",
+ "semver": "^5.1.0"
+ }
+ },
"parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -1961,12 +3559,13 @@
}
},
"parse-json": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
- "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
"dev": true,
"requires": {
- "error-ex": "^1.2.0"
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
}
},
"parseurl": {
@@ -1974,6 +3573,18 @@
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
},
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "dev": true
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+ "dev": true
+ },
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
@@ -1986,6 +3597,12 @@
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+ "dev": true
+ },
"path-key": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
@@ -2004,12 +3621,12 @@
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"path-type": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
- "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
"dev": true,
"requires": {
- "pify": "^2.0.0"
+ "pify": "^3.0.0"
}
},
"pathval": {
@@ -2018,123 +3635,23 @@
"integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
"dev": true
},
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "pidtree": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz",
+ "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==",
"dev": true
},
- "pkg-conf": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz",
- "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==",
- "dev": true,
- "requires": {
- "find-up": "^3.0.0",
- "load-json-file": "^5.2.0"
- },
- "dependencies": {
- "load-json-file": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz",
- "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.15",
- "parse-json": "^4.0.0",
- "pify": "^4.0.1",
- "strip-bom": "^3.0.0",
- "type-fest": "^0.3.0"
- }
- },
- "parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
- "dev": true,
- "requires": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
- }
- },
- "pify": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
- "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
- "dev": true
- },
- "type-fest": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
- "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==",
- "dev": true
- }
- }
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
},
- "pkg-config": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz",
- "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=",
- "dev": true,
- "requires": {
- "debug-log": "^1.0.0",
- "find-root": "^1.0.0",
- "xtend": "^4.0.1"
- }
- },
- "pkg-dir": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
- "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
- "dev": true,
- "requires": {
- "find-up": "^2.1.0"
- },
- "dependencies": {
- "find-up": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
- "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
- "dev": true,
- "requires": {
- "locate-path": "^2.0.0"
- }
- },
- "locate-path": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
- "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
- "dev": true,
- "requires": {
- "p-locate": "^2.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "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,
- "requires": {
- "p-try": "^1.0.0"
- }
- },
- "p-locate": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
- "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
- "dev": true,
- "requires": {
- "p-limit": "^1.1.0"
- }
- },
- "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
- }
- }
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "dev": true
},
"prelude-ls": {
"version": "1.1.2",
@@ -2142,23 +3659,24 @@
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
"dev": true
},
+ "prepend-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ },
"progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
- "prop-types": {
- "version": "15.7.2",
- "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
- "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
- "dev": true,
- "requires": {
- "loose-envify": "^1.4.0",
- "object-assign": "^4.1.1",
- "react-is": "^16.8.1"
- }
- },
"proxy-addr": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
@@ -2168,15 +3686,17 @@
"ipaddr.js": "1.9.0"
}
},
- "pump": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
- "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+ "dev": true
+ },
+ "pstree.remy": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz",
+ "integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==",
+ "dev": true
},
"punycode": {
"version": "2.1.1",
@@ -2189,6 +3709,12 @@
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
},
+ "querystringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
+ "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
+ "dev": true
+ },
"range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -2215,82 +3741,114 @@
}
}
},
- "react-is": {
- "version": "16.9.0",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz",
- "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==",
- "dev": true
- },
- "read-pkg": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
- "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+ "rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"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"
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
},
"dependencies": {
- "find-up": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
- "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
- "dev": true,
- "requires": {
- "locate-path": "^2.0.0"
- }
- },
- "locate-path": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
- "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
- "dev": true,
- "requires": {
- "p-locate": "^2.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "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,
- "requires": {
- "p-try": "^1.0.0"
- }
- },
- "p-locate": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
- "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
- "dev": true,
- "requires": {
- "p-limit": "^1.1.0"
- }
- },
- "p-try": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
- "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
}
}
},
+ "read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
"regexpp": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
- "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz",
+ "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==",
+ "dev": true
+ },
+ "registry-auth-token": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
+ "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==",
+ "dev": true,
+ "requires": {
+ "rc": "^1.1.6",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "registry-url": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
+ "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
+ "dev": true,
+ "requires": {
+ "rc": "^1.0.1"
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "repeat-element": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+ "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
"dev": true
},
"require-directory": {
@@ -2305,6 +3863,12 @@
"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=",
+ "dev": true
+ },
"resolve": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
@@ -2320,6 +3884,12 @@
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true
},
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "dev": true
+ },
"restore-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
@@ -2330,10 +3900,16 @@
"signal-exit": "^3.0.2"
}
},
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "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.0",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz",
+ "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==",
"dev": true,
"requires": {
"glob": "^7.1.3"
@@ -2348,16 +3924,10 @@
"is-promise": "^2.1.0"
}
},
- "run-parallel": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz",
- "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==",
- "dev": true
- },
"rxjs": {
- "version": "6.5.2",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz",
- "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==",
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz",
+ "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==",
"dev": true,
"requires": {
"tslib": "^1.9.0"
@@ -2368,124 +3938,35 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
- "semistandard": {
- "version": "14.0.1",
- "resolved": "https://registry.npmjs.org/semistandard/-/semistandard-14.0.1.tgz",
- "integrity": "sha512-/zLjilCminmmEmYkK6/Z2RYKijQ2NDG9V0DMvPG9mHBdlv2jtu/EEFTdiz/rishopglyuHCOEjkSYI4hD8poJA==",
- "dev": true,
- "requires": {
- "eslint": "~6.1.0",
- "eslint-config-semistandard": "~15.0.0",
- "eslint-config-standard": "~14.0.0",
- "eslint-config-standard-jsx": "~8.0.0",
- "eslint-plugin-import": "~2.18.0",
- "eslint-plugin-node": "~9.1.0",
- "eslint-plugin-promise": "~4.2.1",
- "eslint-plugin-react": "~7.14.2",
- "eslint-plugin-standard": "~4.0.0",
- "standard-engine": "^12.0.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
- },
- "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"
- }
- },
- "eslint": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.1.0.tgz",
- "integrity": "sha512-QhrbdRD7ofuV09IuE2ySWBz0FyXCq0rriLTZXZqaWSI79CVtHVRdkFuFTViiqzZhkCgfOh9USpriuGN2gIpZDQ==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.0.0",
- "ajv": "^6.10.0",
- "chalk": "^2.1.0",
- "cross-spawn": "^6.0.5",
- "debug": "^4.0.1",
- "doctrine": "^3.0.0",
- "eslint-scope": "^5.0.0",
- "eslint-utils": "^1.3.1",
- "eslint-visitor-keys": "^1.0.0",
- "espree": "^6.0.0",
- "esquery": "^1.0.1",
- "esutils": "^2.0.2",
- "file-entry-cache": "^5.0.1",
- "functional-red-black-tree": "^1.0.1",
- "glob-parent": "^5.0.0",
- "globals": "^11.7.0",
- "ignore": "^4.0.6",
- "import-fresh": "^3.0.0",
- "imurmurhash": "^0.1.4",
- "inquirer": "^6.4.1",
- "is-glob": "^4.0.0",
- "js-yaml": "^3.13.1",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.3.0",
- "lodash": "^4.17.14",
- "minimatch": "^3.0.4",
- "mkdirp": "^0.5.1",
- "natural-compare": "^1.4.0",
- "optionator": "^0.8.2",
- "progress": "^2.0.0",
- "regexpp": "^2.0.1",
- "semver": "^6.1.2",
- "strip-ansi": "^5.2.0",
- "strip-json-comments": "^3.0.1",
- "table": "^5.2.3",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- },
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "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"
- }
- },
- "strip-json-comments": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
- "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
- "dev": true
- }
- }
- },
"semver": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
"dev": true
},
+ "semver-diff": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
+ "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
+ "dev": true,
+ "requires": {
+ "semver": "^5.0.3"
+ }
+ },
"send": {
"version": "0.17.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
@@ -2530,6 +4011,29 @@
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"dev": true
},
+ "set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
"setprototypeof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
@@ -2550,6 +4054,12 @@
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
"dev": true
},
+ "shell-quote": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.1.tgz",
+ "integrity": "sha512-2kUqeAGnMAu6YrTPX4E3LfxacH9gKljzVjlkUeSqY0soGwK4KLl7TURXCem712tkhBCeeaFP9QK4dKn88s3Icg==",
+ "dev": true
+ },
"signal-exit": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
@@ -2557,17 +4067,17 @@
"dev": true
},
"sinon": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.4.1.tgz",
- "integrity": "sha512-7s9buHGHN/jqoy/v4bJgmt0m1XEkCEd/tqdHXumpBp0JSujaT4Ng84JU5wDdK4E85ZMq78NuDe0I3NAqXY8TFg==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz",
+ "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==",
"dev": true,
"requires": {
"@sinonjs/commons": "^1.4.0",
"@sinonjs/formatio": "^3.2.1",
- "@sinonjs/samsam": "^3.3.2",
+ "@sinonjs/samsam": "^3.3.3",
"diff": "^3.5.0",
"lolex": "^4.2.0",
- "nise": "^1.5.1",
+ "nise": "^1.5.2",
"supports-color": "^5.5.0"
},
"dependencies": {
@@ -2593,6 +4103,160 @@
"is-fullwidth-code-point": "^2.0.0"
}
},
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "dev": true,
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "source-map-resolve": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
+ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
+ "dev": true,
+ "requires": {
+ "atob": "^2.1.1",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-support": {
+ "version": "0.5.16",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz",
+ "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "dev": true
+ },
"spdx-correct": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
@@ -2625,29 +4289,39 @@
"integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
"dev": true
},
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
- "standard-engine": {
- "version": "12.0.0",
- "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-12.0.0.tgz",
- "integrity": "sha512-gJIIRb0LpL7AHyGbN9+hJ4UJns37lxmNTnMGRLC8CFrzQ+oB/K60IQjKNgPBCB2VP60Ypm6f8DFXvhVWdBOO+g==",
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
"dev": true,
"requires": {
- "deglob": "^4.0.0",
- "get-stdin": "^7.0.0",
- "minimist": "^1.1.0",
- "pkg-conf": "^3.1.0"
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
},
"dependencies": {
- "minimist": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
- "dev": true
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
}
}
},
@@ -2666,6 +4340,46 @@
"strip-ansi": "^4.0.0"
}
},
+ "string.prototype.padend": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz",
+ "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.4.3",
+ "function-bind": "^1.0.2"
+ }
+ },
+ "string.prototype.trimleft": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz",
+ "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "function-bind": "^1.1.1"
+ }
+ },
+ "string.prototype.trimright": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz",
+ "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "function-bind": "^1.1.1"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
@@ -2720,10 +4434,10 @@
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
- "lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "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
},
"string-width": {
@@ -2748,6 +4462,49 @@
}
}
},
+ "term-size": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
+ "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=",
+ "dev": true,
+ "requires": {
+ "execa": "^0.7.0"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "execa": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ }
+ }
+ },
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -2760,6 +4517,12 @@
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true
},
+ "timed-out": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
+ "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=",
+ "dev": true
+ },
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -2769,17 +4532,115 @@
"os-tmpdir": "~1.0.2"
}
},
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
},
+ "touch": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
+ "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
+ "dev": true,
+ "requires": {
+ "nopt": "~1.0.10"
+ },
+ "dependencies": {
+ "nopt": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
+ "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
+ "dev": true,
+ "requires": {
+ "abbrev": "1"
+ }
+ }
+ }
+ },
+ "ts-node": {
+ "version": "8.5.4",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.5.4.tgz",
+ "integrity": "sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw==",
+ "dev": true,
+ "requires": {
+ "arg": "^4.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "source-map-support": "^0.5.6",
+ "yn": "^3.0.0"
+ },
+ "dependencies": {
+ "diff": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz",
+ "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==",
+ "dev": true
+ }
+ }
+ },
"tslib": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
"dev": true
},
+ "tsutils": {
+ "version": "3.17.1",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz",
+ "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -2796,9 +4657,9 @@
"dev": true
},
"type-fest": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz",
- "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"dev": true
},
"type-is": {
@@ -2810,17 +4671,117 @@
"mime-types": "~2.1.24"
}
},
- "uniq": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
- "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=",
+ "typescript": {
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz",
+ "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==",
"dev": true
},
+ "undefsafe": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz",
+ "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=",
+ "dev": true,
+ "requires": {
+ "debug": "^2.2.0"
+ }
+ },
+ "union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ }
+ },
+ "unique-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
+ "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
+ "dev": true,
+ "requires": {
+ "crypto-random-string": "^1.0.0"
+ }
+ },
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dev": true,
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true
+ }
+ }
+ },
+ "unzip-response": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
+ "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=",
+ "dev": true
+ },
+ "upath": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz",
+ "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==",
+ "dev": true
+ },
+ "update-notifier": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz",
+ "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==",
+ "dev": true,
+ "requires": {
+ "boxen": "^1.2.1",
+ "chalk": "^2.0.1",
+ "configstore": "^3.0.0",
+ "import-lazy": "^2.1.0",
+ "is-ci": "^1.0.10",
+ "is-installed-globally": "^0.1.0",
+ "is-npm": "^1.0.0",
+ "latest-version": "^3.0.0",
+ "semver-diff": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ }
+ },
"uri-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
@@ -2830,11 +4791,53 @@
"punycode": "^2.1.0"
}
},
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "dev": true
+ },
+ "url-parse": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
+ "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
+ "dev": true,
+ "requires": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "url-parse-lax": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
+ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
+ "dev": true,
+ "requires": {
+ "prepend-http": "^1.0.1"
+ }
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+ "dev": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
+ "uuid": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
+ "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
+ },
"v8-compile-cache": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",
@@ -2880,54 +4883,67 @@
"string-width": "^1.0.2 || 2"
}
},
+ "widest-line": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
+ "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1"
+ }
+ },
+ "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==",
+ "dev": true
+ },
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
},
"wrap-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
- "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"dev": true,
"requires": {
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1"
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
},
"dependencies": {
"ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "dev": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
+ "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
},
"string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "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": "^2.0.0"
+ "ansi-regex": "^4.1.0"
}
}
}
@@ -2947,6 +4963,17 @@
"mkdirp": "^0.5.1"
}
},
+ "write-file-atomic": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
+ "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ },
"ws": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.1.2.tgz",
@@ -2955,10 +4982,10 @@
"async-limiter": "^1.0.0"
}
},
- "xtend": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
- "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "xdg-basedir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
+ "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=",
"dev": true
},
"y18n": {
@@ -2967,23 +4994,28 @@
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
"dev": true
},
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ },
"yargs": {
- "version": "13.2.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz",
- "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==",
+ "version": "13.3.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",
+ "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==",
"dev": true,
"requires": {
- "cliui": "^4.0.0",
+ "cliui": "^5.0.0",
"find-up": "^3.0.0",
"get-caller-file": "^2.0.1",
- "os-locale": "^3.1.0",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
- "yargs-parser": "^13.0.0"
+ "yargs-parser": "^13.1.1"
},
"dependencies": {
"ansi-regex": {
@@ -2992,6 +5024,12 @@
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
+ "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
+ },
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
@@ -3015,9 +5053,9 @@
}
},
"yargs-parser": {
- "version": "13.0.0",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz",
- "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==",
+ "version": "13.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
+ "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
@@ -3025,59 +5063,21 @@
}
},
"yargs-unparser": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz",
- "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz",
+ "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==",
"dev": true,
"requires": {
"flat": "^4.1.0",
- "lodash": "^4.17.11",
- "yargs": "^12.0.5"
- },
- "dependencies": {
- "get-caller-file": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
- "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
- "dev": true
- },
- "require-main-filename": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
- "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
- "dev": true
- },
- "yargs": {
- "version": "12.0.5",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
- "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
- "dev": true,
- "requires": {
- "cliui": "^4.0.0",
- "decamelize": "^1.2.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^1.0.1",
- "os-locale": "^3.0.0",
- "require-directory": "^2.1.1",
- "require-main-filename": "^1.0.1",
- "set-blocking": "^2.0.0",
- "string-width": "^2.0.0",
- "which-module": "^2.0.0",
- "y18n": "^3.2.1 || ^4.0.0",
- "yargs-parser": "^11.1.1"
- }
- },
- "yargs-parser": {
- "version": "11.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
- "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
- "dev": true,
- "requires": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- }
- }
+ "lodash": "^4.17.15",
+ "yargs": "^13.3.0"
}
+ },
+ "yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "dev": true
}
}
}
diff --git a/package.json b/package.json
index 9a5ea99..65b2d29 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "peer",
"version": "0.3.0",
"description": "PeerJS server component",
- "main": "src/index.js",
+ "main": "dist/peerjs.server.min.js",
"bin": {
"peerjs": "./bin/peerjs"
},
@@ -13,22 +13,47 @@
"author": "Michelle Bu, Eric Zhang",
"license": "MIT",
"scripts": {
- "test": "eslint . && mocha \"test/**/*.js\"",
- "start": "bin/peerjs --port ${PORT:=9000}"
+ "build": "tsc",
+ "clean": "rimraf ./dist",
+ "lint": "eslint --ext .js,.ts .",
+ "tsc": "tsc",
+ "prebuild": "npm run lint",
+ "test": "npm run lint && mocha -r ts-node/register \"test/**/*\"",
+ "start": "bin/peerjs --port ${PORT:=9000}",
+ "dev:start": "npm-run-all build start",
+ "dev": "nodemon --watch src -e ts --exec npm run dev:start"
+ },
+ "release": {
+ "branch": "master"
},
"dependencies": {
- "body-parser": "^1.19.0",
- "cors": "~2.8.4",
- "express": "^4.17.1",
- "optimist": "~0.6.1",
- "ws": "^7.1.2"
+ "@types/cors": "2.8.6",
+ "@types/express": "4.17.1",
+ "@types/ws": "6.0.4",
+ "body-parser": "1.19.0",
+ "cors": "2.8.4",
+ "express": "4.17.1",
+ "optimist": "0.6.1",
+ "uuid": "3.3.3",
+ "ws": "7.1.2"
},
"devDependencies": {
+ "@types/chai": "^4.1.7",
+ "@types/mocha": "^5.2.7",
+ "@types/node": "^10.14.16",
+ "@types/uuid": "3.4.6",
+ "@typescript-eslint/eslint-plugin": "^2.11.0",
+ "@typescript-eslint/parser": "^2.11.0",
"chai": "^4.2.0",
- "eslint": "^6.2.1",
- "mocha": "^6.2.0",
- "semistandard": "^14.0.1",
- "sinon": "^7.4.1"
+ "eslint": "^6.7.2",
+ "mocha": "^6.2.2",
+ "mock-socket": "8.0.5",
+ "nodemon": "1.19.1",
+ "npm-run-all": "4.1.5",
+ "rimraf": "3.0.0",
+ "sinon": "7.5.0",
+ "ts-node": "8.5.4",
+ "typescript": "3.7.3"
},
"engines": {
"node": ">=10"
diff --git a/src/api/index.js b/src/api/index.js
deleted file mode 100644
index 86f3a07..0000000
--- a/src/api/index.js
+++ /dev/null
@@ -1,23 +0,0 @@
-const express = require('express');
-const cors = require('cors');
-const bodyParser = require('body-parser');
-const publicContent = require('../../app.json');
-
-module.exports = ({ config, realm, messageHandler }) => {
- const authMiddleware = require('./middleware/auth')({ config, realm });
-
- const app = express.Router();
-
- const jsonParser = bodyParser.json();
-
- app.use(cors());
-
- app.get('/', (req, res) => {
- res.send(publicContent);
- });
-
- app.use('/:key', require('./v1/public')({ config, realm }));
- app.use('/:key/:id/:token', authMiddleware, jsonParser, require('./v1/calls')({ realm, messageHandler }));
-
- return app;
-};
diff --git a/src/api/index.ts b/src/api/index.ts
new file mode 100644
index 0000000..257bf24
--- /dev/null
+++ b/src/api/index.ts
@@ -0,0 +1,33 @@
+import bodyParser from "body-parser";
+import cors from "cors";
+import express from "express";
+import publicContent from "../../app.json";
+import { IConfig } from "../config";
+import { IMessageHandler } from "../messageHandler";
+import { IRealm } from "../models/realm";
+import { AuthMiddleware } from "./middleware/auth";
+import CallsApi from "./v1/calls";
+import PublicApi from "./v1/public";
+
+export const Api = ({ config, realm, messageHandler }: {
+ config: IConfig;
+ realm: IRealm;
+ messageHandler: IMessageHandler;
+}): express.Router => {
+ const authMiddleware = new AuthMiddleware(config, realm);
+
+ const app = express.Router();
+
+ const jsonParser = bodyParser.json();
+
+ app.use(cors());
+
+ app.get("/", (_, res) => {
+ res.send(publicContent);
+ });
+
+ app.use("/:key", PublicApi({ config, realm }));
+ app.use("/:key/:id/:token", authMiddleware.handle, jsonParser, CallsApi({ realm, messageHandler }));
+
+ return app;
+};
diff --git a/src/api/middleware/auth/index.js b/src/api/middleware/auth/index.js
deleted file mode 100644
index 498bb5f..0000000
--- a/src/api/middleware/auth/index.js
+++ /dev/null
@@ -1,25 +0,0 @@
-const { Errors } = require('../../../enums');
-
-module.exports = ({ config, realm }) => (req, res, next) => {
- const { id, token, key } = req.params;
-
- if (key !== config.key) {
- return res.status(401).send(Errors.INVALID_KEY);
- }
-
- if (!id) {
- return res.sendStatus(401);
- }
-
- const client = realm.getClientById(id);
-
- if (!client) {
- return res.sendStatus(401);
- }
-
- if (client.getToken() && token !== client.getToken()) {
- return res.status(401).send(Errors.INVALID_TOKEN);
- }
-
- next();
-};
diff --git a/src/api/middleware/auth/index.ts b/src/api/middleware/auth/index.ts
new file mode 100644
index 0000000..c46e206
--- /dev/null
+++ b/src/api/middleware/auth/index.ts
@@ -0,0 +1,35 @@
+import express from "express";
+import { IConfig } from "../../../config";
+import { Errors } from "../../../enums";
+import { IRealm } from "../../../models/realm";
+import { IMiddleware } from "../middleware";
+
+export class AuthMiddleware implements IMiddleware {
+
+ constructor(private readonly config: IConfig, private readonly realm: IRealm) { }
+
+ public handle(req: express.Request, res: express.Response, next: express.NextFunction): any {
+ const { id, token, key } = req.params;
+
+ if (key !== this.config.key) {
+ return res.status(401).send(Errors.INVALID_KEY);
+ }
+
+ if (!id) {
+ return res.sendStatus(401);
+ }
+
+ const client = this.realm.getClientById(id);
+
+ if (!client) {
+ return res.sendStatus(401);
+ }
+
+ if (client.getToken() && token !== client.getToken()) {
+ return res.status(401).send(Errors.INVALID_TOKEN);
+ }
+
+ next();
+ }
+
+}
diff --git a/src/api/middleware/middleware.ts b/src/api/middleware/middleware.ts
new file mode 100644
index 0000000..9c28f9d
--- /dev/null
+++ b/src/api/middleware/middleware.ts
@@ -0,0 +1,5 @@
+import express from "express";
+
+export interface IMiddleware {
+ handle(req: express.Request, res: express.Response, next: express.NextFunction): any;
+}
diff --git a/src/api/v1/calls/index.js b/src/api/v1/calls/index.js
deleted file mode 100644
index d022cda..0000000
--- a/src/api/v1/calls/index.js
+++ /dev/null
@@ -1,36 +0,0 @@
-const express = require('express');
-
-module.exports = ({ realm, messageHandler }) => {
- const app = express.Router();
-
- const handle = (req, res, next) => {
- const { id } = req.params;
-
- if (!id) return next();
-
- const client = realm.getClientById(id);
-
- const { type, dst, payload } = req.body;
-
- const message = {
- type,
- src: id,
- dst,
- payload
- };
-
- messageHandler(client, message);
-
- res.sendStatus(200);
- };
-
- app.post('/offer', handle);
-
- app.post('/candidate', handle);
-
- app.post('/answer', handle);
-
- app.post('/leave', handle);
-
- return app;
-};
diff --git a/src/api/v1/calls/index.ts b/src/api/v1/calls/index.ts
new file mode 100644
index 0000000..ea42f8c
--- /dev/null
+++ b/src/api/v1/calls/index.ts
@@ -0,0 +1,40 @@
+import express from "express";
+import { IMessageHandler } from "../../../messageHandler";
+import { IMessage } from "../../../models/message";
+import { IRealm } from "../../../models/realm";
+
+export default ({ realm, messageHandler }: { realm: IRealm, messageHandler: IMessageHandler; }): express.Router => {
+ const app = express.Router();
+
+ const handle = (req: express.Request, res: express.Response, next: express.NextFunction): any => {
+ const { id } = req.params;
+
+ if (!id) return next();
+
+ const client = realm.getClientById(id);
+
+ if (!client) {
+ throw new Error(`client not found:${id}`);
+ }
+
+ const { type, dst, payload } = req.body;
+
+ const message: IMessage = {
+ type,
+ src: id,
+ dst,
+ payload
+ };
+
+ messageHandler.handle(client, message);
+
+ res.sendStatus(200);
+ };
+
+ app.post("/offer", handle);
+ app.post("/candidate", handle);
+ app.post("/answer", handle);
+ app.post("/leave", handle);
+
+ return app;
+};
diff --git a/src/api/v1/public/index.js b/src/api/v1/public/index.ts
similarity index 52%
rename from src/api/v1/public/index.js
rename to src/api/v1/public/index.ts
index f500aa1..fc22229 100644
--- a/src/api/v1/public/index.js
+++ b/src/api/v1/public/index.ts
@@ -1,16 +1,20 @@
-const express = require('express');
+import express from "express";
+import { IConfig } from "../../../config";
+import { IRealm } from "../../../models/realm";
-module.exports = ({ config, realm }) => {
+export default ({ config, realm }: {
+ config: IConfig, realm: IRealm
+}): express.Router => {
const app = express.Router();
// Retrieve guaranteed random ID.
- app.get('/id', (req, res) => {
- res.contentType = 'text/html';
+ app.get("/id", (_, res: express.Response) => {
+ res.contentType("html");
res.send(realm.generateClientId(config.genRandomId));
});
// Get a list of all peers for a key, enabled by the `allowDiscovery` flag.
- app.get('/peers', (req, res) => {
+ app.get("/peers", (_, res: express.Response) => {
if (config.allow_discovery) {
const clientsIds = realm.getClientsIds();
diff --git a/src/config/index.ts b/src/config/index.ts
new file mode 100644
index 0000000..3683e73
--- /dev/null
+++ b/src/config/index.ts
@@ -0,0 +1,33 @@
+export interface IConfig {
+ readonly port: number;
+ readonly expire_timeout: number;
+ readonly alive_timeout: number;
+ readonly key: string;
+ readonly path: string;
+ readonly concurrent_limit: number;
+ readonly allow_discovery: boolean;
+ readonly proxied: boolean | string;
+ readonly cleanup_out_msgs: number;
+ readonly ssl?: {
+ key: string;
+ cert: string;
+ };
+}
+
+const defaultConfig: IConfig = {
+ port: 9000,
+ expire_timeout: 5000,
+ alive_timeout: 60000,
+ key: "peerjs",
+ path: "/myapp",
+ concurrent_limit: 5000,
+ allow_discovery: false,
+ proxied: false,
+ cleanup_out_msgs: 1000,
+ ssl: {
+ key: "",
+ cert: ""
+ }
+};
+
+export default defaultConfig;
diff --git a/src/enums.js b/src/enums.js
deleted file mode 100644
index 93044a4..0000000
--- a/src/enums.js
+++ /dev/null
@@ -1,18 +0,0 @@
-module.exports.Errors = {
- INVALID_KEY: 'Invalid key provided',
- INVALID_TOKEN: 'Invalid token provided',
- INVALID_WS_PARAMETERS: 'No id, token, or key supplied to websocket server',
- CONNECTION_LIMIT_EXCEED: 'Server has reached its concurrent user limit'
-};
-
-module.exports.MessageType = {
- OPEN: 'OPEN',
- LEAVE: 'LEAVE',
- CANDIDATE: 'CANDIDATE',
- OFFER: 'OFFER',
- ANSWER: 'ANSWER',
- EXPIRE: 'EXPIRE',
- HEARTBEAT: 'HEARTBEAT',
- ID_TAKEN: 'ID-TAKEN',
- ERROR: 'ERROR'
-};
diff --git a/src/enums.ts b/src/enums.ts
new file mode 100644
index 0000000..008c7e6
--- /dev/null
+++ b/src/enums.ts
@@ -0,0 +1,18 @@
+export enum Errors {
+ INVALID_KEY = "Invalid key provided",
+ INVALID_TOKEN = "Invalid token provided",
+ INVALID_WS_PARAMETERS = "No id, token, or key supplied to websocket server",
+ CONNECTION_LIMIT_EXCEED = "Server has reached its concurrent user limit"
+}
+
+export enum MessageType {
+ OPEN = "OPEN",
+ LEAVE = "LEAVE",
+ CANDIDATE = "CANDIDATE",
+ OFFER = "OFFER",
+ ANSWER = "ANSWER",
+ EXPIRE = "EXPIRE",
+ HEARTBEAT = "HEARTBEAT",
+ ID_TAKEN = "ID-TAKEN",
+ ERROR = "ERROR"
+}
diff --git a/src/index.js b/src/index.js
deleted file mode 100644
index ea3d9e0..0000000
--- a/src/index.js
+++ /dev/null
@@ -1,134 +0,0 @@
-const express = require('express');
-const http = require('http');
-const https = require('https');
-
-const defaultConfig = require('../config');
-const WebSocketServer = require('./services/webSocketServer');
-const Realm = require('./models/realm');
-
-const init = ({ app, server, options }) => {
- const config = options;
- const realm = new Realm();
- const messageHandler = require('./messageHandler')({ realm });
- const api = require('./api')({ config, realm, messageHandler });
-
- const { startMessagesExpiration } = require('./services/messagesExpire')({ realm, config, messageHandler });
- const checkBrokenConnections = require('./services/checkBrokenConnections')({
- realm, config, onClose: (client) => {
- app.emit('disconnect', client);
- }
- });
-
- app.use(options.path, api);
-
- const wss = new WebSocketServer({
- server,
- realm,
- config: {
- ...config,
- }
- });
-
- wss.on('connection', client => {
- const messageQueue = realm.getMessageQueueById(client.getId());
-
- if (messageQueue) {
- let message;
- // eslint-disable-next-line no-cond-assign
- while (message = messageQueue.readMessage()) {
- messageHandler(client, message);
- }
- realm.clearMessageQueue(client.getId());
- }
-
- app.emit('connection', client);
- });
-
- wss.on('message', (client, message) => {
- app.emit('message', client, message);
- messageHandler(client, message);
- });
-
- wss.on('close', client => {
- app.emit('disconnect', client);
- });
-
- wss.on('error', error => {
- app.emit('error', error);
- });
-
- startMessagesExpiration();
-
- checkBrokenConnections.start();
-};
-
-function ExpressPeerServer(server, options) {
- const app = express();
-
- options = {
- ...defaultConfig,
- ...options
- };
-
- if (options.proxied) {
- app.set('trust proxy', options.proxied === 'false' ? false : options.proxied);
- }
-
- app.on('mount', () => {
- if (!server) {
- throw new Error('Server is not passed to constructor - ' +
- 'can\'t start PeerServer');
- }
-
- init({ app, server, options });
- });
-
- return app;
-}
-
-function PeerServer(options = {}, callback) {
- const app = express();
-
- options = {
- ...defaultConfig,
- ...options
- };
-
- let path = options.path;
- const port = options.port;
-
- if (path[0] !== '/') {
- path = '/' + path;
- }
-
- if (path[path.length - 1] !== '/') {
- path += '/';
- }
-
- let server;
-
- if (options.ssl && options.ssl.key && options.ssl.cert) {
- server = https.createServer(options.ssl, app);
- delete options.ssl;
- } else {
- server = http.createServer(app);
- }
-
- const peerjs = ExpressPeerServer(server, options);
- app.use(peerjs);
-
- if (callback) {
- server.listen(port, () => {
- callback(server);
- });
- } else {
- server.listen(port);
- }
-
- return peerjs;
-}
-
-exports = module.exports = {
- ExpressPeerServer: ExpressPeerServer,
- PeerServer: PeerServer
-};
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000..61f55b3
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,77 @@
+import express from "express";
+import http from "http";
+import https from "https";
+import { Server } from "net";
+
+import defaultConfig, { IConfig } from "./config";
+import { createInstance } from "./instance";
+
+type Optional = {
+ [P in keyof T]?: (T[P] | undefined);
+};
+
+function ExpressPeerServer(server: Server, options?: IConfig) {
+ const app = express();
+
+ const newOptions: IConfig = {
+ ...defaultConfig,
+ ...options
+ };
+
+ if (newOptions.proxied) {
+ app.set("trust proxy", newOptions.proxied === "false" ? false : !!newOptions.proxied);
+ }
+
+ app.on("mount", () => {
+ if (!server) {
+ throw new Error("Server is not passed to constructor - " +
+ "can't start PeerServer");
+ }
+
+ createInstance({ app, server, options: newOptions });
+ });
+
+ return app;
+}
+
+function PeerServer(options: Optional = {}, callback?: (server: Server) => void) {
+ const app = express();
+
+ const newOptions: IConfig = {
+ ...defaultConfig,
+ ...options
+ };
+
+ let path = newOptions.path;
+ const port = newOptions.port;
+
+ if (!path.startsWith('/')) {
+ path = "/" + path;
+ }
+
+ if (!path.endsWith('/')) {
+ path += "/";
+ }
+
+ let server: Server;
+
+ if (newOptions.ssl && newOptions.ssl.key && newOptions.ssl.cert) {
+ server = https.createServer(options.ssl!, app);
+ // @ts-ignore
+ delete newOptions.ssl;
+ } else {
+ server = http.createServer(app);
+ }
+
+ const peerjs = ExpressPeerServer(server, newOptions);
+ app.use(peerjs);
+
+ server.listen(port, () => callback?.(server));
+
+ return peerjs;
+}
+
+export {
+ ExpressPeerServer,
+ PeerServer
+};
diff --git a/src/instance.ts b/src/instance.ts
new file mode 100644
index 0000000..cd8cc66
--- /dev/null
+++ b/src/instance.ts
@@ -0,0 +1,71 @@
+import express from "express";
+import { Server } from "net";
+import { IClient } from "./models/client";
+import { IMessage } from "./models/message";
+import { Realm } from "./models/realm";
+import { IRealm } from "./models/realm";
+import { CheckBrokenConnections } from "./services/checkBrokenConnections";
+import { IMessagesExpire, MessagesExpire } from "./services/messagesExpire";
+import { IWebSocketServer, WebSocketServer } from "./services/webSocketServer";
+import { MessageHandler } from "./messageHandler";
+import { Api } from "./api";
+import { IConfig } from "./config";
+
+export const createInstance = ({ app, server, options }: {
+ app: express.Application,
+ server: Server,
+ options: IConfig;
+}): void => {
+ const config = options;
+ const realm: IRealm = new Realm();
+ const messageHandler = new MessageHandler(realm);
+
+ const api = Api({ config, realm, messageHandler });
+ const messagesExpire: IMessagesExpire = new MessagesExpire({ realm, config, messageHandler });
+ const checkBrokenConnections = new CheckBrokenConnections({
+ realm,
+ config,
+ onClose: client => {
+ app.emit("disconnect", client);
+ }
+ });
+
+ app.use(options.path, api);
+
+ const wss: IWebSocketServer = new WebSocketServer({
+ server,
+ realm,
+ config
+ });
+
+ wss.on("connection", (client: IClient) => {
+ const messageQueue = realm.getMessageQueueById(client.getId());
+
+ if (messageQueue) {
+ let message: IMessage | undefined;
+
+ while (message = messageQueue.readMessage()) {
+ messageHandler.handle(client, message);
+ }
+ realm.clearMessageQueue(client.getId());
+ }
+
+ app.emit("connection", client);
+ });
+
+ wss.on("message", (client: IClient, message: IMessage) => {
+ app.emit("message", client, message);
+ messageHandler.handle(client, message);
+ });
+
+ wss.on("close", (client: IClient) => {
+ app.emit("disconnect", client);
+ });
+
+ wss.on("error", (error: Error) => {
+ app.emit("error", error);
+ });
+
+ messagesExpire.startMessagesExpiration();
+ checkBrokenConnections.start();
+};
\ No newline at end of file
diff --git a/src/messageHandler/handler.ts b/src/messageHandler/handler.ts
new file mode 100644
index 0000000..4c81fde
--- /dev/null
+++ b/src/messageHandler/handler.ts
@@ -0,0 +1,4 @@
+import { IClient } from "../models/client";
+import { IMessage } from "../models/message";
+
+export type Handler = (client: IClient | undefined, message: IMessage) => boolean;
diff --git a/src/messageHandler/handlers/heartbeat/index.js b/src/messageHandler/handlers/heartbeat/index.js
deleted file mode 100644
index a74b99d..0000000
--- a/src/messageHandler/handlers/heartbeat/index.js
+++ /dev/null
@@ -1,4 +0,0 @@
-module.exports = (client) => {
- const nowTime = new Date().getTime();
- client.setLastPing(nowTime);
-};
diff --git a/src/messageHandler/handlers/heartbeat/index.ts b/src/messageHandler/handlers/heartbeat/index.ts
new file mode 100644
index 0000000..43bf35e
--- /dev/null
+++ b/src/messageHandler/handlers/heartbeat/index.ts
@@ -0,0 +1,10 @@
+import { IClient } from "../../../models/client";
+
+export const HeartbeatHandler = (client: IClient | undefined): boolean => {
+ if (client) {
+ const nowTime = new Date().getTime();
+ client.setLastPing(nowTime);
+ }
+
+ return true;
+};
diff --git a/src/messageHandler/handlers/index.ts b/src/messageHandler/handlers/index.ts
new file mode 100644
index 0000000..45095d3
--- /dev/null
+++ b/src/messageHandler/handlers/index.ts
@@ -0,0 +1,2 @@
+export { HeartbeatHandler } from "./heartbeat";
+export { TransmissionHandler } from "./transmission";
diff --git a/src/messageHandler/handlers/transmission/index.js b/src/messageHandler/handlers/transmission/index.js
deleted file mode 100644
index aacdb7f..0000000
--- a/src/messageHandler/handlers/transmission/index.js
+++ /dev/null
@@ -1,49 +0,0 @@
-const { MessageType } = require('../../../enums');
-
-module.exports = ({ realm }) => (client, message) => {
- const type = message.type;
- const srcId = message.src;
- const dstId = message.dst;
-
- const destinationClient = realm.getClientById(dstId);
-
- // User is connected!
- if (destinationClient) {
- try {
- if (destinationClient.socket) {
- const data = JSON.stringify(message);
-
- destinationClient.socket.send(data);
- } else {
- // Neither socket no res available. Peer dead?
- throw new Error('Peer dead');
- }
- } catch (e) {
- // This happens when a peer disconnects without closing connections and
- // the associated WebSocket has not closed.
- // Tell other side to stop trying.
- if (destinationClient.socket) {
- destinationClient.socket.close();
- } else {
- realm.removeClientById(destinationClient.getId());
- }
-
- module.exports({ realm })(client, {
- type: MessageType.LEAVE,
- src: dstId,
- dst: srcId
- });
- }
- } else {
- // Wait for this client to connect/reconnect (XHR) for important
- // messages.
- if (type !== MessageType.LEAVE && type !== MessageType.EXPIRE && dstId) {
- realm.addMessageToQueue(dstId, message);
- } else if (type === MessageType.LEAVE && !dstId) {
- realm.removeClientById(srcId);
- } else {
- // Unavailable destination specified with message LEAVE or EXPIRE
- // Ignore
- }
- }
-};
diff --git a/src/messageHandler/handlers/transmission/index.ts b/src/messageHandler/handlers/transmission/index.ts
new file mode 100644
index 0000000..bd31c70
--- /dev/null
+++ b/src/messageHandler/handlers/transmission/index.ts
@@ -0,0 +1,61 @@
+import { MessageType } from "../../../enums";
+import { IClient } from "../../../models/client";
+import { IMessage } from "../../../models/message";
+import { IRealm } from "../../../models/realm";
+
+export const TransmissionHandler = ({ realm }: { realm: IRealm; }): (client: IClient | undefined, message: IMessage) => boolean => {
+ const handle = (client: IClient | undefined, message: IMessage) => {
+ const type = message.type;
+ const srcId = message.src;
+ const dstId = message.dst;
+
+ const destinationClient = realm.getClientById(dstId);
+
+ // User is connected!
+ if (destinationClient) {
+ const socket = destinationClient.getSocket();
+ try {
+ if (socket) {
+ const data = JSON.stringify(message);
+
+ socket.send(data);
+ } else {
+ // Neither socket no res available. Peer dead?
+ throw new Error("Peer dead");
+ }
+ } catch (e) {
+ // This happens when a peer disconnects without closing connections and
+ // the associated WebSocket has not closed.
+ // Tell other side to stop trying.
+ if (socket) {
+ socket.close();
+ } else {
+ realm.removeClientById(destinationClient.getId());
+ }
+
+ handle(client, {
+ type: MessageType.LEAVE,
+ src: dstId,
+ dst: srcId
+ });
+ }
+ } else {
+ // Wait for this client to connect/reconnect (XHR) for important
+ // messages.
+ const ignoredTypes = [MessageType.LEAVE, MessageType.EXPIRE];
+
+ if (!ignoredTypes.includes(type) && dstId) {
+ realm.addMessageToQueue(dstId, message);
+ } else if (type === MessageType.LEAVE && !dstId) {
+ realm.removeClientById(srcId);
+ } else {
+ // Unavailable destination specified with message LEAVE or EXPIRE
+ // Ignore
+ }
+ }
+
+ return true;
+ };
+
+ return handle;
+};
diff --git a/src/messageHandler/handlersRegistry.ts b/src/messageHandler/handlersRegistry.ts
new file mode 100644
index 0000000..def2ac8
--- /dev/null
+++ b/src/messageHandler/handlersRegistry.ts
@@ -0,0 +1,29 @@
+import { MessageType } from "../enums";
+import { IClient } from "../models/client";
+import { IMessage } from "../models/message";
+import { Handler } from "./handler";
+
+export interface IHandlersRegistry {
+ registerHandler(messageType: MessageType, handler: Handler): void;
+ handle(client: IClient | undefined, message: IMessage): boolean;
+}
+
+export class HandlersRegistry implements IHandlersRegistry {
+ private readonly handlers: Map = new Map();
+
+ public registerHandler(messageType: MessageType, handler: Handler): void {
+ if (this.handlers.has(messageType)) return;
+
+ this.handlers.set(messageType, handler);
+ }
+
+ public handle(client: IClient | undefined, message: IMessage): boolean {
+ const { type } = message;
+
+ const handler = this.handlers.get(type);
+
+ if (!handler) return false;
+
+ return handler(client, message);
+ }
+}
diff --git a/src/messageHandler/index.js b/src/messageHandler/index.js
deleted file mode 100644
index 447e949..0000000
--- a/src/messageHandler/index.js
+++ /dev/null
@@ -1,49 +0,0 @@
-const { MessageType } = require('../enums');
-
-class MessageHandlers {
- constructor() {
- this.handlers = {};
- }
-
- registerHandler(messageType, handler) {
- this.handlers[messageType] = handler;
- }
-
- handle(client, message) {
- const { type } = message;
-
- const handler = this.handlers[type];
-
- if (!handler) {
- return;
- }
-
- handler(client, message);
- }
-}
-module.exports = ({ realm }) => {
- const transmissionHandler = require('./handlers/transmission')({ realm });
- const heartbeatHandler = require('./handlers/heartbeat');
-
- const messageHandlers = new MessageHandlers();
-
- const handleTransmission = (client, message) => {
- transmissionHandler(client, {
- type: message.type,
- src: message.src,
- dst: message.dst,
- payload: message.payload
- });
- };
-
- const handleHeartbeat = (client) => heartbeatHandler(client);
-
- messageHandlers.registerHandler(MessageType.HEARTBEAT, handleHeartbeat);
- messageHandlers.registerHandler(MessageType.OFFER, handleTransmission);
- messageHandlers.registerHandler(MessageType.ANSWER, handleTransmission);
- messageHandlers.registerHandler(MessageType.CANDIDATE, handleTransmission);
- messageHandlers.registerHandler(MessageType.LEAVE, handleTransmission);
- messageHandlers.registerHandler(MessageType.EXPIRE, handleTransmission);
-
- return (client, message) => messageHandlers.handle(client, message);
-};
diff --git a/src/messageHandler/index.ts b/src/messageHandler/index.ts
new file mode 100644
index 0000000..7f6c67a
--- /dev/null
+++ b/src/messageHandler/index.ts
@@ -0,0 +1,40 @@
+import { MessageType } from "../enums";
+import { IClient } from "../models/client";
+import { IMessage } from "../models/message";
+import { IRealm } from "../models/realm";
+import { Handler } from "./handler";
+import { HeartbeatHandler, TransmissionHandler } from "./handlers";
+import { IHandlersRegistry, HandlersRegistry } from "./handlersRegistry";
+
+export interface IMessageHandler {
+ handle(client: IClient | undefined, message: IMessage): boolean;
+}
+
+export class MessageHandler implements IMessageHandler {
+ constructor(realm: IRealm, private readonly handlersRegistry: IHandlersRegistry = new HandlersRegistry()) {
+ const transmissionHandler: Handler = TransmissionHandler({ realm });
+ const heartbeatHandler: Handler = HeartbeatHandler;
+
+ const handleTransmission: Handler = (client: IClient | undefined, { type, src, dst, payload }: IMessage): boolean => {
+ return transmissionHandler(client, {
+ type,
+ src,
+ dst,
+ payload,
+ });
+ };
+
+ const handleHeartbeat = (client: IClient | undefined, message: IMessage) => heartbeatHandler(client, message);
+
+ this.handlersRegistry.registerHandler(MessageType.HEARTBEAT, handleHeartbeat);
+ this.handlersRegistry.registerHandler(MessageType.OFFER, handleTransmission);
+ this.handlersRegistry.registerHandler(MessageType.ANSWER, handleTransmission);
+ this.handlersRegistry.registerHandler(MessageType.CANDIDATE, handleTransmission);
+ this.handlersRegistry.registerHandler(MessageType.LEAVE, handleTransmission);
+ this.handlersRegistry.registerHandler(MessageType.EXPIRE, handleTransmission);
+ }
+
+ public handle(client: IClient | undefined, message: IMessage): boolean {
+ return this.handlersRegistry.handle(client, message);
+ }
+}
diff --git a/src/models/client.js b/src/models/client.js
deleted file mode 100644
index 50cc5ef..0000000
--- a/src/models/client.js
+++ /dev/null
@@ -1,38 +0,0 @@
-class Client {
- constructor({ id, token }) {
- this.id = id;
- this.token = token;
- this.socket = null;
- this.lastPing = new Date().getTime();
- }
-
- getId() {
- return this.id;
- }
-
- getToken() {
- return this.token;
- }
-
- getSocket() {
- return this.socket;
- }
-
- setSocket(socket) {
- this.socket = socket;
- }
-
- getLastPing() {
- return this.lastPing;
- }
-
- setLastPing(lastPing) {
- this.lastPing = lastPing;
- }
-
- send(data) {
- this.socket.send(JSON.stringify(data));
- }
-}
-
-module.exports = Client;
diff --git a/src/models/client.ts b/src/models/client.ts
new file mode 100644
index 0000000..4dee3ca
--- /dev/null
+++ b/src/models/client.ts
@@ -0,0 +1,57 @@
+import { MyWebSocket } from "../services/webSocketServer/webSocket";
+
+export interface IClient {
+ getId(): string;
+
+ getToken(): string;
+
+ getSocket(): MyWebSocket | null;
+
+ setSocket(socket: MyWebSocket | null): void;
+
+ getLastPing(): number;
+
+ setLastPing(lastPing: number): void;
+
+ send(data: any): void;
+}
+
+export class Client implements IClient {
+ private readonly id: string;
+ private readonly token: string;
+ private socket: MyWebSocket | null = null;
+ private lastPing: number = new Date().getTime();
+
+ constructor({ id, token }: { id: string, token: string; }) {
+ this.id = id;
+ this.token = token;
+ }
+
+ public getId(): string {
+ return this.id;
+ }
+
+ public getToken(): string {
+ return this.token;
+ }
+
+ public getSocket(): MyWebSocket | null {
+ return this.socket;
+ }
+
+ public setSocket(socket: MyWebSocket | null): void {
+ this.socket = socket;
+ }
+
+ public getLastPing(): number {
+ return this.lastPing;
+ }
+
+ public setLastPing(lastPing: number): void {
+ this.lastPing = lastPing;
+ }
+
+ public send(data: any): void {
+ this.socket?.send(JSON.stringify(data));
+ }
+}
diff --git a/src/models/message.ts b/src/models/message.ts
new file mode 100644
index 0000000..06c9156
--- /dev/null
+++ b/src/models/message.ts
@@ -0,0 +1,8 @@
+import { MessageType } from "../enums";
+
+export interface IMessage {
+ readonly type: MessageType;
+ readonly src: string;
+ readonly dst: string;
+ readonly payload?: any;
+}
diff --git a/src/models/messageQueue.js b/src/models/messageQueue.js
deleted file mode 100644
index ec5fdd1..0000000
--- a/src/models/messageQueue.js
+++ /dev/null
@@ -1,30 +0,0 @@
-class MessageQueue {
- constructor (id) {
- this._id = id;
- this._lastReadAt = new Date().getTime();
- this._messages = [];
- }
-
- getLastReadAt () {
- return this._lastReadAt;
- }
-
- addMessage (message) {
- this._messages.push(message);
- }
-
- readMessage () {
- if (this._messages.length > 0) {
- this._lastReadAt = new Date().getTime();
- return this._messages.shift();
- }
-
- return null;
- }
-
- getMessages () {
- return this._messages;
- }
-}
-
-module.exports = MessageQueue;
diff --git a/src/models/messageQueue.ts b/src/models/messageQueue.ts
new file mode 100644
index 0000000..da716bb
--- /dev/null
+++ b/src/models/messageQueue.ts
@@ -0,0 +1,37 @@
+import { IMessage } from "./message";
+
+export interface IMessageQueue {
+ getLastReadAt(): number;
+
+ addMessage(message: IMessage): void;
+
+ readMessage(): IMessage | undefined;
+
+ getMessages(): IMessage[];
+}
+
+export class MessageQueue implements IMessageQueue {
+ private lastReadAt: number = new Date().getTime();
+ private readonly messages: IMessage[] = [];
+
+ public getLastReadAt(): number {
+ return this.lastReadAt;
+ }
+
+ public addMessage(message: IMessage): void {
+ this.messages.push(message);
+ }
+
+ public readMessage(): IMessage | undefined {
+ if (this.messages.length > 0) {
+ this.lastReadAt = new Date().getTime();
+ return this.messages.shift()!;
+ }
+
+ return undefined;
+ }
+
+ public getMessages(): IMessage[] {
+ return this.messages;
+ }
+}
diff --git a/src/models/realm.js b/src/models/realm.js
deleted file mode 100644
index 73af397..0000000
--- a/src/models/realm.js
+++ /dev/null
@@ -1,64 +0,0 @@
-const MessageQueue = require('./messageQueue');
-
-class Realm {
- constructor () {
- this._clients = new Map();
- this._messageQueues = new Map();
- }
-
- getClientsIds () {
- return [...this._clients.keys()];
- }
-
- getClientById (clientId) {
- return this._clients.get(clientId);
- }
-
- setClient (client, id) {
- this._clients.set(id, client);
- }
-
- removeClientById (id) {
- const client = this.getClientById(id);
-
- if (!client) return false;
-
- this._clients.delete(id);
- }
-
- getMessageQueueById (id) {
- return this._messageQueues.get(id);
- }
-
- addMessageToQueue (id, message) {
- if (!this.getMessageQueueById(id)) {
- this._messageQueues.set(id, new MessageQueue(id));
- }
-
- this.getMessageQueueById(id).addMessage(message);
- }
-
- clearMessageQueue (id) {
- this._messageQueues.delete(id);
- }
-
- generateClientId (_genRandomId) {
- const originalGenRandomId = () => {
- return (Math.random().toString(36) + '0000000000000000000').substr(2, 16);
- }
-
- const genRandomId = _genRandomId && typeof _genRandomId === 'function' ?
- _genRandomId :
- originalGenRandomId;
-
- let clientId = genRandomId();
-
- while (this.getClientById(clientId)) {
- clientId = genRandomId();
- }
-
- return clientId;
- }
-}
-
-module.exports = Realm;
diff --git a/src/models/realm.ts b/src/models/realm.ts
new file mode 100644
index 0000000..f910829
--- /dev/null
+++ b/src/models/realm.ts
@@ -0,0 +1,84 @@
+import uuidv4 from "uuid/v4";
+import { IClient } from "./client";
+import { IMessage } from "./message";
+import { IMessageQueue, MessageQueue } from "./messageQueue";
+
+export interface IRealm {
+ getClientsIds(): string[];
+
+ getClientById(clientId: string): IClient | undefined;
+
+ getClientsIdsWithQueue(): string[];
+
+ setClient(client: IClient, id: string): void;
+
+ removeClientById(id: string): boolean;
+
+ getMessageQueueById(id: string): IMessageQueue | undefined;
+
+ addMessageToQueue(id: string, message: IMessage): void;
+
+ clearMessageQueue(id: string): void;
+
+ generateClientId(genRandomId: () => string): string;
+}
+
+export class Realm implements IRealm {
+ private readonly clients: Map = new Map();
+ private readonly messageQueues: Map = new Map();
+
+ public getClientsIds(): string[] {
+ return [...this.clients.keys()];
+ }
+
+ public getClientById(clientId: string): IClient | undefined {
+ return this.clients.get(clientId);
+ }
+
+ public getClientsIdsWithQueue(): string[] {
+ return [...this.messageQueues.keys()];
+ }
+
+ public setClient(client: IClient, id: string): void {
+ this.clients.set(id, client);
+ }
+
+ public removeClientById(id: string): boolean {
+ const client = this.getClientById(id);
+
+ if (!client) return false;
+
+ this.clients.delete(id);
+
+ return true;
+ }
+
+ public getMessageQueueById(id: string): IMessageQueue | undefined {
+ return this.messageQueues.get(id);
+ }
+
+ public addMessageToQueue(id: string, message: IMessage): void {
+ if (!this.getMessageQueueById(id)) {
+ this.messageQueues.set(id, new MessageQueue());
+ }
+
+ this.getMessageQueueById(id)!.addMessage(message);
+ }
+
+ public clearMessageQueue(id: string): void {
+ this.messageQueues.delete(id);
+ }
+
+ public generateClientId(genRandomId: () => string): string {
+
+ const _genRandomId = genRandomId ? genRandomId : uuidv4;
+
+ let clientId = _genRandomId();
+
+ while (this.getClientById(clientId)) {
+ clientId = _genRandomId();
+ }
+
+ return clientId;
+ }
+}
diff --git a/src/services/checkBrokenConnections/index.js b/src/services/checkBrokenConnections/index.js
deleted file mode 100644
index fe66fef..0000000
--- a/src/services/checkBrokenConnections/index.js
+++ /dev/null
@@ -1,57 +0,0 @@
-const DEFAULT_CHECK_INTERVAL = 300;
-
-module.exports = ({ realm, config, checkInterval = DEFAULT_CHECK_INTERVAL, onClose = () => { } }) => {
- const checkConnections = () => {
- const clientsIds = realm.getClientsIds();
-
- const now = new Date().getTime();
- const aliveTimeout = config.alive_timeout;
-
- for (const clientId of clientsIds) {
- const client = realm.getClientById(clientId);
- const timeSinceLastPing = now - client.getLastPing();
-
- if (timeSinceLastPing < aliveTimeout) continue;
-
- try {
- client.getSocket().close();
- // eslint-disable-next-line no-empty
- } catch (e) { } finally {
- realm.clearMessageQueue(clientId);
- realm.removeClientById(clientId);
- client.setSocket(null);
-
- if (onClose) onClose(client);
- }
- }
- };
-
- let timeoutId;
-
- const start = () => {
- if (timeoutId) {
- clearTimeout(timeoutId);
- }
-
- timeoutId = setTimeout(() => {
- checkConnections();
-
- timeoutId = null;
-
- start();
- }, checkInterval);
- };
-
- const stop = () => {
- if (timeoutId) {
- clearTimeout(timeoutId);
- timeoutId = null;
- }
- };
-
- return {
- start,
- stop,
- CHECK_INTERVAL: checkInterval
- };
-};
diff --git a/src/services/checkBrokenConnections/index.ts b/src/services/checkBrokenConnections/index.ts
new file mode 100644
index 0000000..9ef3c4e
--- /dev/null
+++ b/src/services/checkBrokenConnections/index.ts
@@ -0,0 +1,74 @@
+import { IConfig } from "../../config";
+import { IClient } from "../../models/client";
+import { IRealm } from "../../models/realm";
+
+const DEFAULT_CHECK_INTERVAL = 300;
+
+type CustomConfig = Pick;
+
+export class CheckBrokenConnections {
+
+ public readonly checkInterval: number;
+ private timeoutId: NodeJS.Timeout | null = null;
+ private readonly realm: IRealm;
+ private readonly config: CustomConfig;
+ private readonly onClose?: (client: IClient) => void;
+
+ constructor({ realm, config, checkInterval = DEFAULT_CHECK_INTERVAL, onClose }: {
+ realm: IRealm,
+ config: CustomConfig,
+ checkInterval?: number,
+ onClose?: (client: IClient) => void;
+ }) {
+ this.realm = realm;
+ this.config = config;
+ this.onClose = onClose;
+ this.checkInterval = checkInterval;
+ }
+
+ public start(): void {
+ if (this.timeoutId) {
+ clearTimeout(this.timeoutId);
+ }
+
+ this.timeoutId = setTimeout(() => {
+ this.checkConnections();
+
+ this.timeoutId = null;
+
+ this.start();
+ }, this.checkInterval);
+ }
+
+ public stop(): void {
+ if (this.timeoutId) {
+ clearTimeout(this.timeoutId);
+ this.timeoutId = null;
+ }
+ }
+
+ private checkConnections(): void {
+ const clientsIds = this.realm.getClientsIds();
+
+ const now = new Date().getTime();
+ const { alive_timeout: aliveTimeout } = this.config;
+
+ for (const clientId of clientsIds) {
+ const client = this.realm.getClientById(clientId)!;
+ const timeSinceLastPing = now - client.getLastPing();
+
+ if (timeSinceLastPing < aliveTimeout) continue;
+
+ try {
+ client.getSocket()?.close();
+ } finally {
+ this.realm.clearMessageQueue(clientId);
+ this.realm.removeClientById(clientId);
+
+ client.setSocket(null);
+
+ this.onClose?.(client);
+ }
+ }
+ }
+}
diff --git a/src/services/messagesExpire/index.js b/src/services/messagesExpire/index.js
deleted file mode 100644
index b4d2b8c..0000000
--- a/src/services/messagesExpire/index.js
+++ /dev/null
@@ -1,63 +0,0 @@
-const { MessageType } = require('../../enums');
-
-module.exports = ({ realm, config, messageHandler }) => {
- const pruneOutstanding = () => {
- const destinationClientsIds = realm._messageQueues.keys();
-
- const now = new Date().getTime();
- const maxDiff = config.expire_timeout;
-
- const seen = {};
-
- for (const destinationClientId of destinationClientsIds) {
- const messageQueue = realm.getMessageQueueById(destinationClientId);
- const lastReadDiff = now - messageQueue.getLastReadAt();
-
- if (lastReadDiff < maxDiff) continue;
-
- const messages = messageQueue.getMessages();
-
- for (const message of messages) {
- if (!seen[message.src]) {
- messageHandler(null, {
- type: MessageType.EXPIRE,
- src: message.dst,
- dst: message.src
- });
- seen[message.src] = true;
- }
- }
-
- realm.clearMessageQueue(destinationClientId);
- }
- };
-
- let timeoutId;
-
- const startMessagesExpiration = () => {
- if (timeoutId) {
- clearTimeout(timeoutId);
- }
-
- // Clean up outstanding messages
- timeoutId = setTimeout(() => {
- pruneOutstanding();
-
- timeoutId = null;
-
- startMessagesExpiration();
- }, config.cleanup_out_msgs);
- };
-
- const stopMessagesExpiration = () => {
- if (timeoutId) {
- clearTimeout(timeoutId);
- timeoutId = null;
- }
- };
-
- return {
- startMessagesExpiration,
- stopMessagesExpiration
- };
-};
diff --git a/src/services/messagesExpire/index.ts b/src/services/messagesExpire/index.ts
new file mode 100644
index 0000000..cf94a38
--- /dev/null
+++ b/src/services/messagesExpire/index.ts
@@ -0,0 +1,83 @@
+import { IConfig } from "../../config";
+import { MessageType } from "../../enums";
+import { IMessageHandler } from "../../messageHandler";
+import { IRealm } from "../../models/realm";
+
+export interface IMessagesExpire {
+ startMessagesExpiration(): void;
+ stopMessagesExpiration(): void;
+}
+
+type CustomConfig = Pick;
+
+export class MessagesExpire implements IMessagesExpire {
+ private readonly realm: IRealm;
+ private readonly config: CustomConfig;
+ private readonly messageHandler: IMessageHandler;
+
+ private timeoutId: NodeJS.Timeout | null = null;
+
+ constructor({ realm, config, messageHandler }: {
+ realm: IRealm;
+ config: CustomConfig;
+ messageHandler: IMessageHandler;
+ }) {
+ this.realm = realm;
+ this.config = config;
+ this.messageHandler = messageHandler;
+ }
+
+ public startMessagesExpiration(): void {
+ if (this.timeoutId) {
+ clearTimeout(this.timeoutId);
+ }
+
+ // Clean up outstanding messages
+ this.timeoutId = setTimeout(() => {
+ this.pruneOutstanding();
+
+ this.timeoutId = null;
+
+ this.startMessagesExpiration();
+ }, this.config.cleanup_out_msgs);
+ }
+
+ public stopMessagesExpiration(): void {
+ if (this.timeoutId) {
+ clearTimeout(this.timeoutId);
+ this.timeoutId = null;
+ }
+ }
+
+ private pruneOutstanding(): void {
+ const destinationClientsIds = this.realm.getClientsIdsWithQueue();
+
+ const now = new Date().getTime();
+ const maxDiff = this.config.expire_timeout;
+
+ const seen: Record = {};
+
+ for (const destinationClientId of destinationClientsIds) {
+ const messageQueue = this.realm.getMessageQueueById(destinationClientId)!;
+ const lastReadDiff = now - messageQueue.getLastReadAt();
+
+ if (lastReadDiff < maxDiff) continue;
+
+ const messages = messageQueue.getMessages();
+
+ for (const message of messages) {
+ if (!seen[message.src]) {
+ this.messageHandler.handle(undefined, {
+ type: MessageType.EXPIRE,
+ src: message.dst,
+ dst: message.src
+ });
+
+ seen[message.src] = true;
+ }
+ }
+
+ this.realm.clearMessageQueue(destinationClientId);
+ }
+ }
+}
diff --git a/src/services/webSocketServer/index.js b/src/services/webSocketServer/index.js
deleted file mode 100644
index bfe1b6c..0000000
--- a/src/services/webSocketServer/index.js
+++ /dev/null
@@ -1,114 +0,0 @@
-const WSS = require('ws').Server;
-const url = require('url');
-const EventEmitter = require('events');
-const { MessageType, Errors } = require('../../enums');
-const Client = require('../../models/client');
-
-class WebSocketServer extends EventEmitter {
- constructor({ server, realm, config }) {
- super();
- this.setMaxListeners(0);
- this.realm = realm;
- this.config = config;
-
- let path = this.config.path;
- path = path + (path[path.length - 1] !== '/' ? '/' : '') + 'peerjs';
-
- this._wss = new WSS({ path, server });
-
- this._wss.on('connection', (socket, req) => this._onSocketConnection(socket, req));
- this._wss.on('error', (error) => this._onSocketError(error));
- }
-
- _onSocketConnection(socket, req) {
- const { query = {} } = url.parse(req.url, true);
-
- const { id, token, key } = query;
-
- if (!id || !token || !key) {
- return this._sendErrorAndClose(socket, Errors.INVALID_WS_PARAMETERS);
- }
-
- if (key !== this.config.key) {
- return this._sendErrorAndClose(socket, Errors.INVALID_KEY);
- }
-
- const client = this.realm.getClientById(id);
-
- if (client) {
- if (token !== client.getToken()) {
- // ID-taken, invalid token
- socket.send(JSON.stringify({
- type: MessageType.ID_TAKEN,
- payload: { msg: 'ID is taken' }
- }));
-
- return socket.close();
- }
-
- return this._configureWS(socket, client);
- }
-
- this._registerClient({ socket, id, token });
- }
-
- _onSocketError(error) {
- // handle error
- this.emit('error', error);
- }
-
- _registerClient({ socket, id, token }) {
- // Check concurrent limit
- const clientsCount = this.realm.getClientsIds().length;
-
- if (clientsCount >= this.config.concurrent_limit) {
- return this._sendErrorAndClose(socket, Errors.CONNECTION_LIMIT_EXCEED);
- }
-
- const newClient = new Client({ id, token });
- this.realm.setClient(newClient, id);
- socket.send(JSON.stringify({ type: MessageType.OPEN }));
-
- this._configureWS(socket, newClient);
- }
-
- _configureWS(socket, client) {
- client.setSocket(socket);
-
- // Cleanup after a socket closes.
- socket.on('close', () => {
- if (client.socket === socket) {
- this.realm.removeClientById(client.getId());
- this.emit('close', client);
- }
- });
-
- // Handle messages from peers.
- socket.on('message', (data) => {
- try {
- const message = JSON.parse(data);
-
- message.src = client.getId();
-
- this.emit('message', client, message);
- } catch (e) {
- this.emit('error', e);
- }
- });
-
- this.emit('connection', client);
- }
-
- _sendErrorAndClose(socket, msg) {
- socket.send(
- JSON.stringify({
- type: MessageType.ERROR,
- payload: { msg }
- })
- );
-
- socket.close();
- }
-}
-
-module.exports = WebSocketServer;
diff --git a/src/services/webSocketServer/index.ts b/src/services/webSocketServer/index.ts
new file mode 100644
index 0000000..3b237a1
--- /dev/null
+++ b/src/services/webSocketServer/index.ts
@@ -0,0 +1,143 @@
+import EventEmitter from "events";
+import { IncomingMessage } from "http";
+import url from "url";
+import WebSocketLib from "ws";
+import { IConfig } from "../../config";
+import { Errors, MessageType } from "../../enums";
+import { Client, IClient } from "../../models/client";
+import { IRealm } from "../../models/realm";
+import { MyWebSocket } from "./webSocket";
+
+export interface IWebSocketServer extends EventEmitter {
+ readonly path: string;
+}
+
+interface IAuthParams {
+ id?: string;
+ token?: string;
+ key?: string;
+}
+
+type CustomConfig = Pick;
+
+const WS_PATH = 'peerjs';
+
+export class WebSocketServer extends EventEmitter implements IWebSocketServer {
+
+ public readonly path: string;
+ private readonly realm: IRealm;
+ private readonly config: CustomConfig;
+ public readonly socketServer: WebSocketLib.Server;
+
+ constructor({ server, realm, config }: { server: any, realm: IRealm, config: CustomConfig; }) {
+ super();
+
+ this.setMaxListeners(0);
+
+ this.realm = realm;
+ this.config = config;
+
+ const path = this.config.path;
+ this.path = `${path}${path.endsWith('/') ? "" : "/"}${WS_PATH}`;
+
+ this.socketServer = new WebSocketLib.Server({ path: this.path, server });
+
+ this.socketServer.on("connection", (socket: MyWebSocket, req) => this._onSocketConnection(socket, req));
+ this.socketServer.on("error", (error: Error) => this._onSocketError(error));
+ }
+
+ private _onSocketConnection(socket: MyWebSocket, req: IncomingMessage): void {
+ const { query = {} } = url.parse(req.url!, true);
+
+ const { id, token, key }: IAuthParams = query;
+
+ if (!id || !token || !key) {
+ return this._sendErrorAndClose(socket, Errors.INVALID_WS_PARAMETERS);
+ }
+
+ if (key !== this.config.key) {
+ return this._sendErrorAndClose(socket, Errors.INVALID_KEY);
+ }
+
+ const client = this.realm.getClientById(id);
+
+ if (client) {
+ if (token !== client.getToken()) {
+ // ID-taken, invalid token
+ socket.send(JSON.stringify({
+ type: MessageType.ID_TAKEN,
+ payload: { msg: "ID is taken" }
+ }));
+
+ return socket.close();
+ }
+
+ return this._configureWS(socket, client);
+ }
+
+ this._registerClient({ socket, id, token });
+ }
+
+ private _onSocketError(error: Error): void {
+ // handle error
+ this.emit("error", error);
+ }
+
+ private _registerClient({ socket, id, token }:
+ {
+ socket: MyWebSocket;
+ id: string;
+ token: string;
+ }): void {
+ // Check concurrent limit
+ const clientsCount = this.realm.getClientsIds().length;
+
+ if (clientsCount >= this.config.concurrent_limit) {
+ return this._sendErrorAndClose(socket, Errors.CONNECTION_LIMIT_EXCEED);
+ }
+
+ const newClient: IClient = new Client({ id, token });
+ this.realm.setClient(newClient, id);
+ socket.send(JSON.stringify({ type: MessageType.OPEN }));
+
+ this._configureWS(socket, newClient);
+ }
+
+ private _configureWS(socket: MyWebSocket, client: IClient): void {
+ client.setSocket(socket);
+
+ // Cleanup after a socket closes.
+ socket.on("close", () => {
+ if (client.getSocket() === socket) {
+ this.realm.removeClientById(client.getId());
+ this.emit("close", client);
+ }
+ });
+
+ // Handle messages from peers.
+ socket.on("message", (data: WebSocketLib.Data) => {
+ try {
+ const message = JSON.parse(data as string);
+
+ message.src = client.getId();
+
+ this.emit("message", client, message);
+ } catch (e) {
+ this.emit("error", e);
+ }
+ });
+
+ this.emit("connection", client);
+ }
+
+ private _sendErrorAndClose(socket: MyWebSocket, msg: Errors): void {
+ socket.send(
+ JSON.stringify({
+ type: MessageType.ERROR,
+ payload: { msg }
+ })
+ );
+
+ socket.close();
+ }
+}
diff --git a/src/services/webSocketServer/webSocket.ts b/src/services/webSocketServer/webSocket.ts
new file mode 100644
index 0000000..1e04565
--- /dev/null
+++ b/src/services/webSocketServer/webSocket.ts
@@ -0,0 +1,4 @@
+import EventEmitter from "events";
+import WebSocketLib from "ws";
+
+export type MyWebSocket = WebSocketLib & EventEmitter;
diff --git a/test/messageHandler/handlers/heartbeat/index.js b/test/messageHandler/handlers/heartbeat/index.ts
similarity index 58%
rename from test/messageHandler/handlers/heartbeat/index.js
rename to test/messageHandler/handlers/heartbeat/index.ts
index de76b79..c13d7c0 100644
--- a/test/messageHandler/handlers/heartbeat/index.js
+++ b/test/messageHandler/handlers/heartbeat/index.ts
@@ -1,6 +1,6 @@
-const { expect } = require('chai');
-const Client = require('../../../../src/models/client');
-const heartbeatHandler = require('../../../../src/messageHandler/handlers/heartbeat');
+import { expect } from 'chai';
+import { Client } from '../../../../src/models/client';
+import { HeartbeatHandler } from '../../../../src/messageHandler/handlers';
describe('Heartbeat handler', () => {
it('should update last ping time', () => {
@@ -9,7 +9,7 @@ describe('Heartbeat handler', () => {
const nowTime = new Date().getTime();
- heartbeatHandler(client);
+ HeartbeatHandler(client);
expect(client.getLastPing()).to.be.closeTo(nowTime, 2);
});
diff --git a/test/messageHandler/handlers/transmission/index.ts b/test/messageHandler/handlers/transmission/index.ts
new file mode 100644
index 0000000..83b1ff6
--- /dev/null
+++ b/test/messageHandler/handlers/transmission/index.ts
@@ -0,0 +1,96 @@
+import { expect } from 'chai';
+import { Client } from '../../../../src/models/client';
+import { TransmissionHandler } from '../../../../src/messageHandler/handlers';
+import { Realm } from '../../../../src/models/realm';
+import { MessageType } from '../../../../src/enums';
+import { MyWebSocket } from '../../../../src/services/webSocketServer/webSocket';
+
+const createFakeSocket = (): MyWebSocket => {
+ /* eslint-disable @typescript-eslint/no-empty-function */
+ const sock = {
+ send: (): void => { },
+ close: (): void => { },
+ on: (): void => { },
+ };
+ /* eslint-enable @typescript-eslint/no-empty-function */
+
+ return (sock as unknown as MyWebSocket);
+};
+
+describe('Transmission handler', () => {
+ it('should save message in queue when destination client not connected', () => {
+ const realm = new Realm();
+ const handleTransmission = TransmissionHandler({ realm });
+
+ const clientFrom = new Client({ id: 'id1', token: '' });
+ const idTo = 'id2';
+ realm.setClient(clientFrom, clientFrom.getId());
+
+ handleTransmission(clientFrom, { type: MessageType.OFFER, src: clientFrom.getId(), dst: idTo });
+
+ expect(realm.getMessageQueueById(idTo)?.getMessages().length).to.be.eq(1);
+ });
+
+ it('should not save LEAVE and EXPIRE messages in queue when destination client not connected', () => {
+ const realm = new Realm();
+ const handleTransmission = TransmissionHandler({ realm });
+
+ const clientFrom = new Client({ id: 'id1', token: '' });
+ const idTo = 'id2';
+ realm.setClient(clientFrom, clientFrom.getId());
+
+ handleTransmission(clientFrom, { type: MessageType.LEAVE, src: clientFrom.getId(), dst: idTo });
+ handleTransmission(clientFrom, { type: MessageType.EXPIRE, src: clientFrom.getId(), dst: idTo });
+
+ expect(realm.getMessageQueueById(idTo)).to.be.undefined;
+ });
+
+ it('should send message to destination client when destination client connected', () => {
+ const realm = new Realm();
+ const handleTransmission = TransmissionHandler({ realm });
+
+ const clientFrom = new Client({ id: 'id1', token: '' });
+ const clientTo = new Client({ id: 'id2', token: '' });
+ const socketTo = createFakeSocket();
+ clientTo.setSocket(socketTo);
+ realm.setClient(clientTo, clientTo.getId());
+
+ let sent = false;
+ socketTo.send = (): void => {
+ sent = true;
+ };
+
+ handleTransmission(clientFrom, { type: MessageType.OFFER, src: clientFrom.getId(), dst: clientTo.getId() });
+
+ expect(sent).to.be.true;
+ });
+
+ it('should send LEAVE message to source client when sending to destination client failed', () => {
+ const realm = new Realm();
+ const handleTransmission = TransmissionHandler({ realm });
+
+ const clientFrom = new Client({ id: 'id1', token: '' });
+ const clientTo = new Client({ id: 'id2', token: '' });
+ const socketFrom = createFakeSocket();
+ const socketTo = createFakeSocket();
+ clientFrom.setSocket(socketFrom);
+ clientTo.setSocket(socketTo);
+ realm.setClient(clientFrom, clientFrom.getId());
+ realm.setClient(clientTo, clientTo.getId());
+
+ let sent = false;
+ socketFrom.send = (data: string): void => {
+ if (JSON.parse(data)?.type === MessageType.LEAVE) {
+ sent = true;
+ }
+ };
+
+ socketTo.send = (): void => {
+ throw Error();
+ };
+
+ handleTransmission(clientFrom, { type: MessageType.OFFER, src: clientFrom.getId(), dst: clientTo.getId() });
+
+ expect(sent).to.be.true;
+ });
+});
diff --git a/test/messageHandler/handlersRegistry.ts b/test/messageHandler/handlersRegistry.ts
new file mode 100644
index 0000000..6791056
--- /dev/null
+++ b/test/messageHandler/handlersRegistry.ts
@@ -0,0 +1,23 @@
+import { expect } from 'chai';
+import { HandlersRegistry } from '../../src/messageHandler/handlersRegistry';
+import { Handler } from '../../src/messageHandler/handler';
+import { MessageType } from '../../src/enums';
+
+describe('HandlersRegistry', () => {
+ it('should execute handler for message type', () => {
+ const handlersRegistry = new HandlersRegistry();
+
+ let handled = false;
+
+ const handler: Handler = (): boolean => {
+ handled = true;
+ return true;
+ };
+
+ handlersRegistry.registerHandler(MessageType.OPEN, handler);
+
+ handlersRegistry.handle(undefined, { type: MessageType.OPEN, src: 'src', dst: 'dst' });
+
+ expect(handled).to.be.true;
+ });
+});
diff --git a/test/models/messageQueue.ts b/test/models/messageQueue.ts
new file mode 100644
index 0000000..41118f2
--- /dev/null
+++ b/test/models/messageQueue.ts
@@ -0,0 +1,62 @@
+import { expect } from 'chai';
+import { MessageQueue } from '../../src/models/messageQueue';
+import { MessageType } from '../../src/enums';
+import { IMessage } from '../../src/models/message';
+import { wait } from '../utils';
+
+describe('MessageQueue', () => {
+ const createTestMessage = (): IMessage => {
+ return {
+ type: MessageType.OPEN,
+ src: 'src',
+ dst: 'dst'
+ };
+ };
+
+ describe('#addMessage', () => {
+ it('should add message to queue', () => {
+ const queue = new MessageQueue();
+ queue.addMessage(createTestMessage());
+ expect(queue.getMessages().length).to.eq(1);
+ });
+ });
+
+ describe('#readMessage', () => {
+ it('should return undefined for empty queue', () => {
+ const queue = new MessageQueue();
+ expect(queue.readMessage()).to.be.undefined;
+ });
+
+ it('should return message if any exists in queue', () => {
+ const queue = new MessageQueue();
+ const message = createTestMessage();
+ queue.addMessage(message);
+
+ expect(queue.readMessage()).to.deep.eq(message);
+ expect(queue.readMessage()).to.be.undefined;
+ });
+ });
+
+ describe('#getLastReadAt', () => {
+ it('should not be changed if no messages when read', () => {
+ const queue = new MessageQueue();
+ const lastReadAt = queue.getLastReadAt();
+ queue.readMessage();
+ expect(queue.getLastReadAt()).to.be.eq(lastReadAt);
+ });
+
+ it('should be changed when read message', async () => {
+ const queue = new MessageQueue();
+ const lastReadAt = queue.getLastReadAt();
+ queue.addMessage(createTestMessage());
+
+ await wait(10);
+
+ expect(queue.getLastReadAt()).to.be.eq(lastReadAt);
+
+ queue.readMessage();
+
+ expect(queue.getLastReadAt()).to.be.greaterThan(lastReadAt + 10);
+ });
+ });
+});
diff --git a/test/models/realm.js b/test/models/realm.ts
similarity index 83%
rename from test/models/realm.js
rename to test/models/realm.ts
index 2c8ee39..6daf9c2 100644
--- a/test/models/realm.js
+++ b/test/models/realm.ts
@@ -1,12 +1,12 @@
-const { expect } = require('chai');
-const Realm = require('../../src/models/realm');
-const Client = require('../../src/models/client');
+import { expect } from 'chai';
+import { Realm } from '../../src/models/realm';
+import { Client } from '../../src/models/client';
describe('Realm', () => {
describe('#generateClientId', () => {
- it('should generate a 16-character ID', () => {
+ it('should generate a 36-character UUID', () => {
const realm = new Realm();
- expect(realm.generateClientId().length).to.eq(16);
+ expect(realm.generateClientId().length).to.eq(36);
expect(realm.generateClientId(() => 'abcd')).to.eq('abcd');
});
});
diff --git a/test/services/checkBrokenConnections/index.js b/test/services/checkBrokenConnections/index.js
deleted file mode 100644
index 1d77ad5..0000000
--- a/test/services/checkBrokenConnections/index.js
+++ /dev/null
@@ -1,43 +0,0 @@
-const { expect } = require('chai');
-const Client = require('../../../src/models/client');
-const Realm = require('../../../src/models/realm');
-const checkBrokenConnectionsBuilder = require('../../../src/services/checkBrokenConnections');
-
-describe('checkBrokenConnections service', () => {
- it('should remove client after 2 checks', (done) => {
- const realm = new Realm();
- const doubleCheckTime = 55;//~ equals to checkBrokenConnections.CHECK_INTERVAL * 2
- const checkBrokenConnections = checkBrokenConnectionsBuilder({ realm, config: { alive_timeout: doubleCheckTime }, checkInterval: 30 });
- const client = new Client({ id: 'id', token: '' });
- realm.setClient(client, 'id');
-
- checkBrokenConnections.start();
-
- setTimeout(() => {
- expect(realm.getClientById('id')).to.be.undefined;
- checkBrokenConnections.stop();
- done();
- }, checkBrokenConnections.CHECK_INTERVAL * 2 + 3);
- });
-
- it('should remove client after 1 ping', (done) => {
- const realm = new Realm();
- const doubleCheckTime = 55;//~ equals to checkBrokenConnections.CHECK_INTERVAL * 2
- const checkBrokenConnections = checkBrokenConnectionsBuilder({ realm, config: { alive_timeout: doubleCheckTime }, checkInterval: 30 });
- const client = new Client({ id: 'id', token: '' });
- realm.setClient(client, 'id');
-
- checkBrokenConnections.start();
-
- //set ping after first check
- setTimeout(() => {
- client.setLastPing(new Date().getTime());
-
- setTimeout(() => {
- expect(realm.getClientById('id')).to.be.undefined;
- checkBrokenConnections.stop();
- done();
- }, checkBrokenConnections.CHECK_INTERVAL * 2 + 10);
- }, checkBrokenConnections.CHECK_INTERVAL);
- });
-});
diff --git a/test/services/checkBrokenConnections/index.ts b/test/services/checkBrokenConnections/index.ts
new file mode 100644
index 0000000..437f054
--- /dev/null
+++ b/test/services/checkBrokenConnections/index.ts
@@ -0,0 +1,44 @@
+import { expect } from 'chai';
+import { Client } from '../../../src/models/client';
+import { Realm } from '../../../src/models/realm';
+import { CheckBrokenConnections } from '../../../src/services/checkBrokenConnections';
+import { wait } from '../../utils';
+
+describe('CheckBrokenConnections', () => {
+ it('should remove client after 2 checks', async () => {
+ const realm = new Realm();
+ const doubleCheckTime = 55;//~ equals to checkBrokenConnections.checkInterval * 2
+ const checkBrokenConnections = new CheckBrokenConnections({ realm, config: { alive_timeout: doubleCheckTime }, checkInterval: 30 });
+ const client = new Client({ id: 'id', token: '' });
+ realm.setClient(client, 'id');
+
+ checkBrokenConnections.start();
+
+ await wait(checkBrokenConnections.checkInterval * 2 + 30);
+
+ expect(realm.getClientById('id')).to.be.undefined;
+
+ checkBrokenConnections.stop();
+ });
+
+ it('should remove client after 1 ping', async () => {
+ const realm = new Realm();
+ const doubleCheckTime = 55;//~ equals to checkBrokenConnections.checkInterval * 2
+ const checkBrokenConnections = new CheckBrokenConnections({ realm, config: { alive_timeout: doubleCheckTime }, checkInterval: 30 });
+ const client = new Client({ id: 'id', token: '' });
+ realm.setClient(client, 'id');
+
+ checkBrokenConnections.start();
+
+ //set ping after first check
+ await wait(checkBrokenConnections.checkInterval);
+
+ client.setLastPing(new Date().getTime());
+
+ await wait(checkBrokenConnections.checkInterval * 2 + 10);
+
+ expect(realm.getClientById('id')).to.be.undefined;
+
+ checkBrokenConnections.stop();
+ });
+});
diff --git a/test/services/messagesExpire/index.ts b/test/services/messagesExpire/index.ts
new file mode 100644
index 0000000..eac362b
--- /dev/null
+++ b/test/services/messagesExpire/index.ts
@@ -0,0 +1,78 @@
+import { expect } from 'chai';
+import { Client } from '../../../src/models/client';
+import { Realm } from '../../../src/models/realm';
+import { IMessage } from '../../../src/models/message';
+import { MessagesExpire } from '../../../src/services/messagesExpire';
+import { MessageHandler } from '../../../src/messageHandler';
+import { MessageType } from '../../../src/enums';
+import { wait } from '../../utils';
+
+describe('MessagesExpire', () => {
+ const createTestMessage = (): IMessage => {
+ return {
+ type: MessageType.OPEN,
+ src: 'src',
+ dst: 'dst'
+ };
+ };
+
+ it('should remove client if no read from queue', async () => {
+ const realm = new Realm();
+ const messageHandler = new MessageHandler(realm);
+ const checkInterval = 10;
+ const expireTimeout = 50;
+ const config = { cleanup_out_msgs: checkInterval, expire_timeout: expireTimeout };
+
+ const messagesExpire = new MessagesExpire({ realm, config, messageHandler });
+
+ const client = new Client({ id: 'id', token: '' });
+ realm.setClient(client, 'id');
+ realm.addMessageToQueue(client.getId(), createTestMessage());
+
+ messagesExpire.startMessagesExpiration();
+
+ await wait(checkInterval * 2);
+
+ expect(realm.getMessageQueueById(client.getId())?.getMessages().length).to.be.eq(1);
+
+ await wait(expireTimeout);
+
+ expect(realm.getMessageQueueById(client.getId())).to.be.undefined;
+
+ messagesExpire.stopMessagesExpiration();
+ });
+
+ it('should fire EXPIRE message', async () => {
+ const realm = new Realm();
+ const messageHandler = new MessageHandler(realm);
+ const checkInterval = 10;
+ const expireTimeout = 50;
+ const config = { cleanup_out_msgs: checkInterval, expire_timeout: expireTimeout };
+
+ const messagesExpire = new MessagesExpire({ realm, config, messageHandler });
+
+ const client = new Client({ id: 'id', token: '' });
+ realm.setClient(client, 'id');
+ realm.addMessageToQueue(client.getId(), createTestMessage());
+
+ let handled = false;
+
+ messageHandler.handle = (client, message): boolean => {
+ expect(client).to.be.undefined;
+ expect(message.type).to.be.eq(MessageType.EXPIRE);
+
+ handled = true;
+
+ return true;
+ };
+
+ messagesExpire.startMessagesExpiration();
+
+ await wait(checkInterval * 2);
+ await wait(expireTimeout);
+
+ expect(handled).to.be.true;
+
+ messagesExpire.stopMessagesExpiration();
+ });
+});
diff --git a/test/services/webSocketServer/index.ts b/test/services/webSocketServer/index.ts
new file mode 100644
index 0000000..705b2a6
--- /dev/null
+++ b/test/services/webSocketServer/index.ts
@@ -0,0 +1,195 @@
+import { expect } from 'chai';
+import { Server, WebSocket } from 'mock-socket';
+import { Realm } from '../../../src/models/realm';
+import { WebSocketServer } from '../../../src/services/webSocketServer';
+import { Errors, MessageType } from '../../../src/enums';
+import { wait } from '../../utils';
+
+type Destroyable = T & { destroy?: () => Promise; };
+
+const checkOpen = async (c: WebSocket): Promise => {
+ return new Promise(resolve => {
+ c.onmessage = (event: object & { data?: string; }): void => {
+ c.onmessage = null;
+ const message = JSON.parse(event.data as string);
+ resolve(message.type === MessageType.OPEN);
+ };
+ });
+};
+
+const checkSequence = async (c: WebSocket, msgs: { type: MessageType; error?: Errors; }[]): Promise => {
+ return new Promise(resolve => {
+ const restMessages = [...msgs];
+
+ const finish = (success = false): void => {
+ c.onmessage = null;
+ resolve(success);
+ };
+
+ c.onmessage = (event: object & { data?: string; }): void => {
+ const [mes] = restMessages;
+
+ if (!mes) {
+ return finish();
+ }
+
+ restMessages.shift();
+
+ const message = JSON.parse(event.data as string);
+ if (message.type !== mes.type) {
+ return finish();
+ }
+
+ const isOk = !mes.error || message.payload?.msg === mes.error;
+
+ if (!isOk) {
+ return finish();
+ }
+
+ if (restMessages.length === 0) {
+ finish(true);
+ }
+ };
+ });
+};
+
+const createTestServer = ({ realm, config, url }: { realm: Realm; config: { path: string; key: string; concurrent_limit: number; }; url: string; }): Destroyable => {
+ const server = new Server(url);
+ const webSocketServer: Destroyable = new WebSocketServer({ server, realm, config });
+
+ server.on('connection', (socket: WebSocket & { on?: (eventName: string, callback: () => void) => void; }) => {
+ const s = webSocketServer.socketServer;
+ s.emit('connection', socket, { url: socket.url });
+
+ socket.onclose = (): void => {
+ const userId = socket.url.split('?')[1]?.split('&').find(p => p.startsWith('id'))?.split('=')[1];
+
+ if (!userId) return;
+
+ const client = realm.getClientById(userId);
+
+ const clientSocket = client?.getSocket();
+
+ if (!clientSocket) return;
+
+ (clientSocket as unknown as WebSocket).listeners['server::close']?.forEach((s: () => void) => s());
+ };
+
+ socket.onmessage = (event: object & { data?: string; }): void => {
+ const userId = socket.url.split('?')[1]?.split('&').find(p => p.startsWith('id'))?.split('=')[1];
+
+ if (!userId) return;
+
+ const client = realm.getClientById(userId);
+
+ const clientSocket = client?.getSocket();
+
+ if (!clientSocket) return;
+
+ (clientSocket as unknown as WebSocket).listeners['server::message']?.forEach((s: (data: object) => void) => s(event));
+ };
+ });
+
+ webSocketServer.destroy = async (): Promise => {
+ server.close();
+ };
+
+ return webSocketServer;
+};
+
+describe('WebSocketServer', () => {
+
+ it('should return valid path', () => {
+ const realm = new Realm();
+ const config = { path: '/', key: 'testKey', concurrent_limit: 1 };
+ const config2 = { ...config, path: 'path' };
+ const server = new Server('path1');
+ const server2 = new Server('path2');
+
+ const webSocketServer = new WebSocketServer({ server, realm, config });
+
+ expect(webSocketServer.path).to.be.eq('/peerjs');
+
+ const webSocketServer2 = new WebSocketServer({ server: server2, realm, config: config2 });
+
+ expect(webSocketServer2.path).to.be.eq('path/peerjs');
+
+ server.stop();
+ server2.stop();
+ });
+
+ it(`should check client's params`, async () => {
+ const realm = new Realm();
+ const config = { path: '/', key: 'testKey', concurrent_limit: 1 };
+ const fakeURL = 'ws://localhost:8080/peerjs';
+
+ const getError = async (url: string, validError: Errors = Errors.INVALID_WS_PARAMETERS): Promise => {
+ const webSocketServer = createTestServer({ url, realm, config });
+
+ const ws = new WebSocket(url);
+
+ const errorSent = await checkSequence(ws, [{ type: MessageType.ERROR, error: validError }]);
+
+ ws.close();
+
+ await webSocketServer.destroy?.();
+
+ return errorSent;
+ };
+
+ expect(await getError(fakeURL)).to.be.true;
+ expect(await getError(`${fakeURL}?key=${config.key}`)).to.be.true;
+ expect(await getError(`${fakeURL}?key=${config.key}&id=1`)).to.be.true;
+ expect(await getError(`${fakeURL}?key=notValidKey&id=userId&token=userToken`, Errors.INVALID_KEY)).to.be.true;
+ });
+
+ it(`should check concurrent limit`, async () => {
+ const realm = new Realm();
+ const config = { path: '/', key: 'testKey', concurrent_limit: 1 };
+ const fakeURL = 'ws://localhost:8080/peerjs';
+
+ const createClient = (id: string): Destroyable => {
+ const url = `${fakeURL}?key=${config.key}&id=${id}&token=${id}`;
+ const webSocketServer = createTestServer({ url, realm, config });
+ const ws: Destroyable = new WebSocket(url);
+
+ ws.destroy = async (): Promise => {
+ ws.close();
+
+ wait(10);
+
+ webSocketServer.destroy?.();
+
+ wait(10);
+
+ ws.destroy = undefined;
+ };
+
+ return ws;
+ };
+
+
+ const c1 = createClient('1');
+
+ expect(await checkOpen(c1)).to.be.true;
+
+ const c2 = createClient('2');
+
+ expect(await checkSequence(c2, [
+ { type: MessageType.ERROR, error: Errors.CONNECTION_LIMIT_EXCEED }
+ ])).to.be.true;
+
+ await c1.destroy?.();
+ await c2.destroy?.();
+
+ await wait(10);
+
+ expect(realm.getClientsIds().length).to.be.eq(0);
+
+ const c3 = createClient('3');
+
+ expect(await checkOpen(c3)).to.be.true;
+
+ await c3.destroy?.();
+ });
+});
diff --git a/test/utils.ts b/test/utils.ts
new file mode 100644
index 0000000..cbbd648
--- /dev/null
+++ b/test/utils.ts
@@ -0,0 +1 @@
+export const wait = (ms: number): Promise => new Promise(resolve => setTimeout(resolve, ms));
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..3c7af7a
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "lib": [
+ "esnext"
+ ],
+ "target": "es2016",
+ "module": "commonjs",
+ "strict": true,
+ "esModuleInterop": true,
+ "downlevelIteration": true,
+ "moduleResolution": "node",
+ "noImplicitAny": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": false,
+ "outDir": "dist"
+ },
+ "include": [
+ "./src/**/*",
+ ],
+ "exclude": [
+ "test",
+ "bin",
+ ]
+}
\ No newline at end of file