From 629241611bb70bd9a1bd56cf086f8d5f6814f668 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 25 Sep 2014 17:33:27 +0100 Subject: [PATCH 01/79] v1 of the redis driver wrapper --- libraries/redis-wrapper/.gitignore | 11 ++++ libraries/redis-wrapper/Gruntfile.coffee | 35 +++++++++++++ libraries/redis-wrapper/index.coffee | 10 ++++ libraries/redis-wrapper/package.json | 23 +++++++++ libraries/redis-wrapper/test.coffee | 65 ++++++++++++++++++++++++ 5 files changed, 144 insertions(+) create mode 100644 libraries/redis-wrapper/.gitignore create mode 100644 libraries/redis-wrapper/Gruntfile.coffee create mode 100644 libraries/redis-wrapper/index.coffee create mode 100644 libraries/redis-wrapper/package.json create mode 100644 libraries/redis-wrapper/test.coffee diff --git a/libraries/redis-wrapper/.gitignore b/libraries/redis-wrapper/.gitignore new file mode 100644 index 0000000000..cb03337081 --- /dev/null +++ b/libraries/redis-wrapper/.gitignore @@ -0,0 +1,11 @@ +**.swp + +app.js +app/js/ +test/unit/js/ +public/build/ + +node_modules/ + +/public/js/chat.js +plato/ diff --git a/libraries/redis-wrapper/Gruntfile.coffee b/libraries/redis-wrapper/Gruntfile.coffee new file mode 100644 index 0000000000..59bb3d34b6 --- /dev/null +++ b/libraries/redis-wrapper/Gruntfile.coffee @@ -0,0 +1,35 @@ +module.exports = (grunt) -> + + # Project configuration. + grunt.initConfig + coffee: + server: + expand: true, + flatten: false, + cwd: 'app/coffee', + src: ['**/*.coffee'], + dest: 'app/js/', + ext: '.js' + + server_tests: + expand: true, + flatten: false, + cwd: 'test/unit/coffee', + src: ['**/*.coffee'], + dest: 'test/unit/js/', + ext: '.js' + + mochaTest: + unit: + options: + reporter: process.env.MOCHA_RUNNER || "spec" + grep: grunt.option("grep") + require: 'coffee-script/register' + src: ['test.coffee'] + + + grunt.loadNpmTasks 'grunt-contrib-coffee' + grunt.loadNpmTasks 'grunt-mocha-test' + + grunt.registerTask 'test:unit', ['mochaTest:unit'] + diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee new file mode 100644 index 0000000000..a1154ce9c7 --- /dev/null +++ b/libraries/redis-wrapper/index.coffee @@ -0,0 +1,10 @@ +module.exports = + + createClient: ()-> + if arguments[0] instanceof Array + client = require("redis-sentinel").createClient.apply null, arguments + else + client = require("redis").createClient.apply null, arguments + return client + + diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json new file mode 100644 index 0000000000..7209fde4ba --- /dev/null +++ b/libraries/redis-wrapper/package.json @@ -0,0 +1,23 @@ +{ + "name": "redis-sharelatex", + "version": "0.0.0", + "description": "", + "main": "index.coffee", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "chai": "^1.9.1", + "coffee-script": "^1.8.0", + "grunt": "^0.4.5", + "grunt-contrib-coffee": "^0.11.1", + "grunt-mocha-test": "^0.12.0", + "mocha": "^1.21.4", + "redis": "^0.12.1", + "redis-sentinel": "^0.1.1", + "sandboxed-module": "^1.0.1", + "sinon": "^1.10.3" + } +} diff --git a/libraries/redis-wrapper/test.coffee b/libraries/redis-wrapper/test.coffee new file mode 100644 index 0000000000..8fdaa5331e --- /dev/null +++ b/libraries/redis-wrapper/test.coffee @@ -0,0 +1,65 @@ +should = require('chai').should() +SandboxedModule = require('sandboxed-module') +assert = require('assert') +path = require('path') +sinon = require('sinon') +modulePath = path.join __dirname, "./index.coffee" +expect = require("chai").expect + +describe "index", -> + + beforeEach -> + + @settings = {} + @sentinelClient = set:-> + @normalRedisClient = get: -> + + @sentinel = + createClient: sinon.stub().returns(@sentinelClient) + @normalRedis = + createClient: sinon.stub().returns(@normalRedisClient) + @redis = SandboxedModule.require modulePath, requires: + "redis-sentinel":@sentinel + "redis":@normalRedis + @standardOpts = + auth_pass: "my password" + + describe "sentinel", -> + + beforeEach -> + @endpoints = [ + {host: '127.0.0.1', port: 26379}, + {host: '127.0.0.1', port: 26380} + ] + @masterName = "my master" + + it "should use sentinal if the first argument in an array", -> + + client = @redis.createClient @endpoints, @masterName, @standardOpts + @sentinel.createClient.called.should.equal true + @normalRedis.createClient.called.should.equal false + client.should.equal @sentinelClient + + it "should pass the options correctly though", -> + client = @redis.createClient @endpoints, @masterName, @standardOpts + @sentinel.createClient.calledWith(@endpoints, @masterName, @standardOpts).should.equal true + client.should.equal @sentinelClient + + describe "normal redis", -> + + beforeEach -> + @port = 1234 + @host = "redis.mysite.env" + + it "should use the normal redis driver if a non array is passed", -> + + client = @redis.createClient @port, @host, @standardOpts + @sentinel.createClient.called.should.equal false + @normalRedis.createClient.called.should.equal true + client.should.equal @normalRedisClient + + + it "should use the normal redis driver if a non array is passed", -> + + client = @redis.createClient @port, @host, @standardOpts + @normalRedis.createClient.calledWith(@port, @host, @standardOpts).should.equal true From a0c861cf5de91bb169d4425482b9c2ae8abf62c4 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Fri, 26 Sep 2014 14:46:23 +0100 Subject: [PATCH 02/79] pass entire redis object though with all opts in one go --- libraries/redis-wrapper/index.coffee | 17 +++++++++++---- libraries/redis-wrapper/package.json | 30 ++++++++++++-------------- libraries/redis-wrapper/test.coffee | 32 +++++++++++++++++----------- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index a1154ce9c7..4c8a028d8e 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -1,10 +1,19 @@ +_ = require("underscore") + module.exports = - createClient: ()-> - if arguments[0] instanceof Array - client = require("redis-sentinel").createClient.apply null, arguments + createClient: (opts)-> + + if opts.endpoints? + standardOpts = _.clone(opts) + delete standardOpts.endpoints + delete standardOpts.masterName + client = require("redis-sentinel").createClient opts.endpoints, opts.masterName, standardOpts else - client = require("redis").createClient.apply null, arguments + standardOpts = _.clone(opts) + delete standardOpts.port + delete standardOpts.host + client = require("redis").createClient opts.port, opts.host, standardOpts return client diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 7209fde4ba..e317117b5f 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,23 +1,21 @@ { "name": "redis-sharelatex", - "version": "0.0.0", - "description": "", + "version": "0.0.1", + "description": "redis wrapper for node which will either use sentinal or normal redis", "main": "index.coffee", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", + "author": "henry oswald @ sharelatex", "license": "ISC", "dependencies": { - "chai": "^1.9.1", - "coffee-script": "^1.8.0", - "grunt": "^0.4.5", - "grunt-contrib-coffee": "^0.11.1", - "grunt-mocha-test": "^0.12.0", - "mocha": "^1.21.4", - "redis": "^0.12.1", - "redis-sentinel": "^0.1.1", - "sandboxed-module": "^1.0.1", - "sinon": "^1.10.3" + "chai": "1.9.1", + "coffee-script": "1.8.0", + "grunt": "0.4.5", + "grunt-contrib-coffee": "0.11.1", + "grunt-mocha-test": "0.12.0", + "mocha": "1.21.4", + "redis": "0.12.1", + "redis-sentinel": "0.1.1", + "sandboxed-module": "1.0.1", + "sinon": "1.10.3", + "underscore": "^1.7.0" } } diff --git a/libraries/redis-wrapper/test.coffee b/libraries/redis-wrapper/test.coffee index 8fdaa5331e..50f551331c 100644 --- a/libraries/redis-wrapper/test.coffee +++ b/libraries/redis-wrapper/test.coffee @@ -21,8 +21,7 @@ describe "index", -> @redis = SandboxedModule.require modulePath, requires: "redis-sentinel":@sentinel "redis":@normalRedis - @standardOpts = - auth_pass: "my password" + @auth_pass = "1234 pass" describe "sentinel", -> @@ -32,34 +31,41 @@ describe "index", -> {host: '127.0.0.1', port: 26380} ] @masterName = "my master" + @sentinelOptions = + endpoints:@endpoints + masterName:@masterName + auth_pass:@auth_pass it "should use sentinal if the first argument in an array", -> - - client = @redis.createClient @endpoints, @masterName, @standardOpts + client = @redis.createClient @sentinelOptions @sentinel.createClient.called.should.equal true @normalRedis.createClient.called.should.equal false client.should.equal @sentinelClient it "should pass the options correctly though", -> - client = @redis.createClient @endpoints, @masterName, @standardOpts - @sentinel.createClient.calledWith(@endpoints, @masterName, @standardOpts).should.equal true + client = @redis.createClient @sentinelOptions + @sentinel.createClient.calledWith(@endpoints, @masterName, auth_pass:@auth_pass).should.equal true client.should.equal @sentinelClient describe "normal redis", -> beforeEach -> - @port = 1234 - @host = "redis.mysite.env" + @standardOpts = + auth_pass: @auth_pass + port: 1234 + host: "redis.mysite.env" it "should use the normal redis driver if a non array is passed", -> - - client = @redis.createClient @port, @host, @standardOpts + client = @redis.createClient @standardOpts @sentinel.createClient.called.should.equal false @normalRedis.createClient.called.should.equal true client.should.equal @normalRedisClient - it "should use the normal redis driver if a non array is passed", -> + client = @redis.createClient @standardOpts + @normalRedis.createClient.calledWith(@standardOpts.port, @standardOpts.host, auth_pass:@auth_pass).should.equal true + + + + - client = @redis.createClient @port, @host, @standardOpts - @normalRedis.createClient.calledWith(@port, @host, @standardOpts).should.equal true From f554ea8bd5fc5dd390884fa20e17e887687088db Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Sep 2014 20:33:29 +0100 Subject: [PATCH 03/79] change underscore dep --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index e317117b5f..52bc04d6ad 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -16,6 +16,6 @@ "redis-sentinel": "0.1.1", "sandboxed-module": "1.0.1", "sinon": "1.10.3", - "underscore": "^1.7.0" + "underscore": "1.7.0" } } From a33f537cb1e51a004e489ce15b7f5c1e5b5d5f3c Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Sun, 28 Sep 2014 20:34:20 +0100 Subject: [PATCH 04/79] increment package --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 52bc04d6ad..e221b1c537 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "0.0.1", + "version": "0.0.2", "description": "redis wrapper for node which will either use sentinal or normal redis", "main": "index.coffee", "author": "henry oswald @ sharelatex", From 8f31ac60caa23e1e1f5c144577b8bd2ddb4e36c2 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Mon, 29 Sep 2014 11:40:40 +0100 Subject: [PATCH 05/79] if password is passed rename it to auth_pass --- libraries/redis-wrapper/index.coffee | 4 +++- libraries/redis-wrapper/package.json | 2 +- libraries/redis-wrapper/test.coffee | 29 +++++++++++++++++++++++----- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 4c8a028d8e..1135d90c36 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -3,7 +3,9 @@ _ = require("underscore") module.exports = createClient: (opts)-> - + if opts.password? + opts.auth_pass = opts.password + delete opts.password if opts.endpoints? standardOpts = _.clone(opts) delete standardOpts.endpoints diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index e221b1c537..43026b0085 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "0.0.2", + "version": "0.0.3", "description": "redis wrapper for node which will either use sentinal or normal redis", "main": "index.coffee", "author": "henry oswald @ sharelatex", diff --git a/libraries/redis-wrapper/test.coffee b/libraries/redis-wrapper/test.coffee index 50f551331c..f166c34ba8 100644 --- a/libraries/redis-wrapper/test.coffee +++ b/libraries/redis-wrapper/test.coffee @@ -22,14 +22,14 @@ describe "index", -> "redis-sentinel":@sentinel "redis":@normalRedis @auth_pass = "1234 pass" - - describe "sentinel", -> - - beforeEach -> - @endpoints = [ + @endpoints = [ {host: '127.0.0.1', port: 26379}, {host: '127.0.0.1', port: 26380} ] + describe "sentinel", -> + + beforeEach -> + @masterName = "my master" @sentinelOptions = endpoints:@endpoints @@ -67,5 +67,24 @@ describe "index", -> + describe "setting the password", -> + beforeEach -> + @standardOpts = + password: @auth_pass + port: 1234 + host: "redis.mysite.env" + + @sentinelOptions = + endpoints:@endpoints + masterName:@masterName + password: @auth_pass + + it "should set the auth_pass from password if password exists for normal redis", -> + client = @redis.createClient @standardOpts + @normalRedis.createClient.calledWith(@standardOpts.port, @standardOpts.host, auth_pass:@auth_pass).should.equal true + + it "should set the auth_pass from password if password exists for sentinal", -> + client = @redis.createClient @sentinelOptions + @sentinel.createClient.calledWith(@endpoints, @masterName, auth_pass:@auth_pass).should.equal true From c63f3c9da910900ad231fb63ea25550b607b79be Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Mon, 29 Sep 2014 12:00:03 +0100 Subject: [PATCH 06/79] added readme --- libraries/redis-wrapper/Readme.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 libraries/redis-wrapper/Readme.md diff --git a/libraries/redis-wrapper/Readme.md b/libraries/redis-wrapper/Readme.md new file mode 100644 index 0000000000..e69de29bb2 From 4fd5191528e945c4aadc2d9566e769c8ee4c046b Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Mon, 29 Sep 2014 12:02:38 +0100 Subject: [PATCH 07/79] bump package --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 43026b0085..5e068cfd99 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "0.0.3", + "version": "0.0.4", "description": "redis wrapper for node which will either use sentinal or normal redis", "main": "index.coffee", "author": "henry oswald @ sharelatex", From 8808097f2cdf2acc2957901795ae85643b247973 Mon Sep 17 00:00:00 2001 From: James Allen Date: Fri, 7 Nov 2014 15:02:45 +0000 Subject: [PATCH 08/79] Add javascript wrapper so it can be loaded directly --- libraries/redis-wrapper/index.js | 2 ++ libraries/redis-wrapper/package.json | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 libraries/redis-wrapper/index.js diff --git a/libraries/redis-wrapper/index.js b/libraries/redis-wrapper/index.js new file mode 100644 index 0000000000..d812c63570 --- /dev/null +++ b/libraries/redis-wrapper/index.js @@ -0,0 +1,2 @@ +require("coffee-script").register(); +module.exports = require("./index.coffee"); diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 5e068cfd99..73385e3024 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,8 +1,8 @@ { "name": "redis-sharelatex", - "version": "0.0.4", + "version": "0.0.5", "description": "redis wrapper for node which will either use sentinal or normal redis", - "main": "index.coffee", + "main": "index.js", "author": "henry oswald @ sharelatex", "license": "ISC", "dependencies": { From 79afad5409a596988f4db33ce3f46bc0df86ff95 Mon Sep 17 00:00:00 2001 From: James Allen Date: Tue, 18 Nov 2014 15:49:27 +0000 Subject: [PATCH 09/79] Use own fork of node-redis-sentinel --- libraries/redis-wrapper/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 73385e3024..d2174eacfa 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "0.0.5", + "version": "0.0.6", "description": "redis wrapper for node which will either use sentinal or normal redis", "main": "index.js", "author": "henry oswald @ sharelatex", @@ -13,7 +13,7 @@ "grunt-mocha-test": "0.12.0", "mocha": "1.21.4", "redis": "0.12.1", - "redis-sentinel": "0.1.1", + "redis-sentinel": "git+https://github.com/sharelatex/node-redis-sentinel.git#master", "sandboxed-module": "1.0.1", "sinon": "1.10.3", "underscore": "1.7.0" From 230203eadf09a444f2120bc6c1ff51b693010381 Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 19 Nov 2014 11:01:02 +0000 Subject: [PATCH 10/79] Add in robust heartbeat driven subscription model --- libraries/redis-wrapper/index.coffee | 38 +++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 1135d90c36..a72613a0b6 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -1,8 +1,7 @@ _ = require("underscore") -module.exports = - - createClient: (opts)-> +module.exports = RedisSharelatex = + createClient: (opts = {port: 6379, host: "localhost"})-> if opts.password? opts.auth_pass = opts.password delete opts.password @@ -17,5 +16,38 @@ module.exports = delete standardOpts.host client = require("redis").createClient opts.port, opts.host, standardOpts return client + + createRobustSubscriptionClient: (opts, heartbeatOpts = {}) -> + sub = RedisSharelatex.createClient(opts) + pub = RedisSharelatex.createClient(opts) + + heartbeatInterval = heartbeatOpts.heartbeat_interval or 1000 #ms + reconnectAfter = heartbeatOpts.reconnect_after or 5000 #ms + + id = require("crypto").createHash("md5").update(Math.random().toString()).digest("hex") + heartbeatChannel = "heartbeat-#{id}" + lastHeartbeat = Date.now() + + sub.subscribe heartbeatChannel, (error) -> + if error? + console.error "ERROR: failed to subscribe to #{heartbeatChannel} channel", error + sub.on "message", (channel, message) -> + if channel == heartbeatChannel + lastHeartbeat = Date.now() + + reconnectIfInactive = () -> + timeSinceLastHeartBeat = Date.now() - lastHeartbeat + if timeSinceLastHeartBeat > reconnectAfter + console.warn "No heartbeat for #{timeSinceLastHeartBeat}ms, reconnecting" + sub.connection_gone("no heartbeat for #{timeSinceLastHeartBeat}ms") + + setInterval () -> + pub.publish heartbeatChannel, "PING" + reconnectIfInactive() + , heartbeatInterval + + return sub + + From c90cc61570986502a9b2288f3781df750fbbb6be Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 19 Nov 2014 11:02:27 +0000 Subject: [PATCH 11/79] Set retry_max_delay to 5 seconds so that reconnects don't slow down exponentially --- libraries/redis-wrapper/index.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index a72613a0b6..ebf953fa06 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -2,6 +2,9 @@ _ = require("underscore") module.exports = RedisSharelatex = createClient: (opts = {port: 6379, host: "localhost"})-> + if !opts.retry_max_delay? + opts.retry_max_delay = 5000 # ms + if opts.password? opts.auth_pass = opts.password delete opts.password From 68c428545dfa01d42e9f665bd6e9dcb647f31e4d Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 19 Nov 2014 11:16:43 +0000 Subject: [PATCH 12/79] Don't hash because Henry is hashist! --- libraries/redis-wrapper/index.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index ebf953fa06..07c43e4af4 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -27,7 +27,7 @@ module.exports = RedisSharelatex = heartbeatInterval = heartbeatOpts.heartbeat_interval or 1000 #ms reconnectAfter = heartbeatOpts.reconnect_after or 5000 #ms - id = require("crypto").createHash("md5").update(Math.random().toString()).digest("hex") + id = require("crypto").randomBytes(16).toString("hex") heartbeatChannel = "heartbeat-#{id}" lastHeartbeat = Date.now() From e988dc8586ebad423a3c99b471a46a42c8f2c2e9 Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 19 Nov 2014 11:18:31 +0000 Subject: [PATCH 13/79] Don't need secure random bytes which can error if not enough entropy --- libraries/redis-wrapper/index.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 07c43e4af4..be15ac89ff 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -27,7 +27,7 @@ module.exports = RedisSharelatex = heartbeatInterval = heartbeatOpts.heartbeat_interval or 1000 #ms reconnectAfter = heartbeatOpts.reconnect_after or 5000 #ms - id = require("crypto").randomBytes(16).toString("hex") + id = require("crypto").pseudoRandomBytes(16).toString("hex") heartbeatChannel = "heartbeat-#{id}" lastHeartbeat = Date.now() From b67b49564de2cad8bd937d01ceb6f0f31a129514 Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 19 Nov 2014 11:21:36 +0000 Subject: [PATCH 14/79] Revert "Use own fork of node-redis-sentinel" This reverts commit a351534a5f0e50656430ff37d2f6c42f701096d0. --- libraries/redis-wrapper/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index d2174eacfa..73385e3024 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "0.0.6", + "version": "0.0.5", "description": "redis wrapper for node which will either use sentinal or normal redis", "main": "index.js", "author": "henry oswald @ sharelatex", @@ -13,7 +13,7 @@ "grunt-mocha-test": "0.12.0", "mocha": "1.21.4", "redis": "0.12.1", - "redis-sentinel": "git+https://github.com/sharelatex/node-redis-sentinel.git#master", + "redis-sentinel": "0.1.1", "sandboxed-module": "1.0.1", "sinon": "1.10.3", "underscore": "1.7.0" From db3537a8ebabaa0eb5b6d61160b720708ddc8ecd Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 19 Nov 2014 11:25:09 +0000 Subject: [PATCH 15/79] Reset heartbeat timer after triggering a reconnect --- libraries/redis-wrapper/index.coffee | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index be15ac89ff..04eca38450 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -39,10 +39,12 @@ module.exports = RedisSharelatex = lastHeartbeat = Date.now() reconnectIfInactive = () -> - timeSinceLastHeartBeat = Date.now() - lastHeartbeat - if timeSinceLastHeartBeat > reconnectAfter - console.warn "No heartbeat for #{timeSinceLastHeartBeat}ms, reconnecting" - sub.connection_gone("no heartbeat for #{timeSinceLastHeartBeat}ms") + timeSinceLastHeartbeat = Date.now() - lastHeartbeat + if timeSinceLastHeartbeat > reconnectAfter + console.warn "No heartbeat for #{timeSinceLastHeartbeat}ms, reconnecting" + sub.connection_gone("no heartbeat for #{timeSinceLastHeartbeat}ms") + # Reset timer after triggering a reconnect to avoid potential cascading failure. + lastHeartbeat = Date.now() setInterval () -> pub.publish heartbeatChannel, "PING" From 861eafd88da3a74e72c23e1bcf86fa596de38e5a Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 19 Nov 2014 11:52:40 +0000 Subject: [PATCH 16/79] Handle reconnect logic better to (hopefully) avoid duplicate connections --- libraries/redis-wrapper/index.coffee | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 04eca38450..581c419469 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -41,8 +41,17 @@ module.exports = RedisSharelatex = reconnectIfInactive = () -> timeSinceLastHeartbeat = Date.now() - lastHeartbeat if timeSinceLastHeartbeat > reconnectAfter - console.warn "No heartbeat for #{timeSinceLastHeartbeat}ms, reconnecting" - sub.connection_gone("no heartbeat for #{timeSinceLastHeartbeat}ms") + console.warn "[#{new Date()}] No heartbeat for #{timeSinceLastHeartbeat}ms on #{heartbeatChannel}, reconnecting" + # If the client realises it isn't connected then will be trying to + # restablish the connection, so there's nothing for us to do. If + # it still thinks it's connected, then disconnect it and start to reconnect. + if sub.connected + sub.end() + # We ended the connection, but want to start it up again, so set + # the internal closing variable: + sub.closing = false + # Trigger the reconnect: + sub.connection_gone("no heartbeat for #{timeSinceLastHeartbeat}ms") # Reset timer after triggering a reconnect to avoid potential cascading failure. lastHeartbeat = Date.now() From 42cbaecbe00c9e51f1ffbc5973b43b125123566b Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 19 Nov 2014 12:30:10 +0000 Subject: [PATCH 17/79] Let the client take care of reconnecting only when the stream is actually ended --- libraries/redis-wrapper/index.coffee | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 581c419469..8378e47e5d 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -41,17 +41,20 @@ module.exports = RedisSharelatex = reconnectIfInactive = () -> timeSinceLastHeartbeat = Date.now() - lastHeartbeat if timeSinceLastHeartbeat > reconnectAfter - console.warn "[#{new Date()}] No heartbeat for #{timeSinceLastHeartbeat}ms on #{heartbeatChannel}, reconnecting" # If the client realises it isn't connected then will be trying to # restablish the connection, so there's nothing for us to do. If # it still thinks it's connected, then disconnect it and start to reconnect. if sub.connected + console.warn "[#{new Date()}] No heartbeat for #{timeSinceLastHeartbeat}ms on #{heartbeatChannel}, reconnecting" sub.end() # We ended the connection, but want to start it up again, so set # the internal closing variable: sub.closing = false - # Trigger the reconnect: - sub.connection_gone("no heartbeat for #{timeSinceLastHeartbeat}ms") + # Trigger the reconnect (automatically triggered by sub.end() with closing = false): + # sub.connection_gone("no heartbeat for #{timeSinceLastHeartbeat}ms") + else + console.warn "[#{new Date()}] No heartbeat for #{timeSinceLastHeartbeat}ms on #{heartbeatChannel}, but not reconnecting (already reconnecting)" + # Reset timer after triggering a reconnect to avoid potential cascading failure. lastHeartbeat = Date.now() From 1ee287ed98467ea53aabfd0f3203c5c779d6889a Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 19 Nov 2014 14:05:16 +0000 Subject: [PATCH 18/79] add createMonitoredSubscriptionClient method --- libraries/redis-wrapper/index.coffee | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 8378e47e5d..3b745bd9fa 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -20,6 +20,7 @@ module.exports = RedisSharelatex = client = require("redis").createClient opts.port, opts.host, standardOpts return client + # DO NOT USE. Not robust at all (ends up getting subscribed twice, etc)! createRobustSubscriptionClient: (opts, heartbeatOpts = {}) -> sub = RedisSharelatex.createClient(opts) pub = RedisSharelatex.createClient(opts) @@ -64,6 +65,36 @@ module.exports = RedisSharelatex = , heartbeatInterval return sub + + # Attaches an isAlive() method to the subsciption client which returns true + # so long as we have had a heartbeat recently. + createMonitoredSubscriptionClient: (opts, heartbeatOpts = {}) -> + sub = RedisSharelatex.createClient(opts) + pub = RedisSharelatex.createClient(opts) + + heartbeatInterval = heartbeatOpts.heartbeat_interval or 2000 #ms + isAliveTimeout = heartbeatOpts.is_alive_timeout or 10000 #ms + + id = require("crypto").pseudoRandomBytes(16).toString("hex") + heartbeatChannel = "heartbeat-#{id}" + lastHeartbeat = Date.now() + + sub.subscribe heartbeatChannel, (error) -> + if error? + console.error "ERROR: failed to subscribe to #{heartbeatChannel} channel", error + sub.on "message", (channel, message) -> + if channel == heartbeatChannel + lastHeartbeat = Date.now() + + sub.isAlive = () -> + timeSinceLastHeartbeat = Date.now() - lastHeartbeat + return (timeSinceLastHeartbeat < isAliveTimeout) + + setInterval () -> + pub.publish heartbeatChannel, "PING" + , heartbeatInterval + + return sub From 4cd3c249ecbd24eb29ff5745d893c379a9fa047c Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Wed, 19 Nov 2014 16:39:06 +0000 Subject: [PATCH 19/79] removed reconnect stuff --- libraries/redis-wrapper/index.coffee | 82 +--------------------------- 1 file changed, 1 insertion(+), 81 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 3b745bd9fa..fd71b221a3 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -18,84 +18,4 @@ module.exports = RedisSharelatex = delete standardOpts.port delete standardOpts.host client = require("redis").createClient opts.port, opts.host, standardOpts - return client - - # DO NOT USE. Not robust at all (ends up getting subscribed twice, etc)! - createRobustSubscriptionClient: (opts, heartbeatOpts = {}) -> - sub = RedisSharelatex.createClient(opts) - pub = RedisSharelatex.createClient(opts) - - heartbeatInterval = heartbeatOpts.heartbeat_interval or 1000 #ms - reconnectAfter = heartbeatOpts.reconnect_after or 5000 #ms - - id = require("crypto").pseudoRandomBytes(16).toString("hex") - heartbeatChannel = "heartbeat-#{id}" - lastHeartbeat = Date.now() - - sub.subscribe heartbeatChannel, (error) -> - if error? - console.error "ERROR: failed to subscribe to #{heartbeatChannel} channel", error - sub.on "message", (channel, message) -> - if channel == heartbeatChannel - lastHeartbeat = Date.now() - - reconnectIfInactive = () -> - timeSinceLastHeartbeat = Date.now() - lastHeartbeat - if timeSinceLastHeartbeat > reconnectAfter - # If the client realises it isn't connected then will be trying to - # restablish the connection, so there's nothing for us to do. If - # it still thinks it's connected, then disconnect it and start to reconnect. - if sub.connected - console.warn "[#{new Date()}] No heartbeat for #{timeSinceLastHeartbeat}ms on #{heartbeatChannel}, reconnecting" - sub.end() - # We ended the connection, but want to start it up again, so set - # the internal closing variable: - sub.closing = false - # Trigger the reconnect (automatically triggered by sub.end() with closing = false): - # sub.connection_gone("no heartbeat for #{timeSinceLastHeartbeat}ms") - else - console.warn "[#{new Date()}] No heartbeat for #{timeSinceLastHeartbeat}ms on #{heartbeatChannel}, but not reconnecting (already reconnecting)" - - # Reset timer after triggering a reconnect to avoid potential cascading failure. - lastHeartbeat = Date.now() - - setInterval () -> - pub.publish heartbeatChannel, "PING" - reconnectIfInactive() - , heartbeatInterval - - return sub - - # Attaches an isAlive() method to the subsciption client which returns true - # so long as we have had a heartbeat recently. - createMonitoredSubscriptionClient: (opts, heartbeatOpts = {}) -> - sub = RedisSharelatex.createClient(opts) - pub = RedisSharelatex.createClient(opts) - - heartbeatInterval = heartbeatOpts.heartbeat_interval or 2000 #ms - isAliveTimeout = heartbeatOpts.is_alive_timeout or 10000 #ms - - id = require("crypto").pseudoRandomBytes(16).toString("hex") - heartbeatChannel = "heartbeat-#{id}" - lastHeartbeat = Date.now() - - sub.subscribe heartbeatChannel, (error) -> - if error? - console.error "ERROR: failed to subscribe to #{heartbeatChannel} channel", error - sub.on "message", (channel, message) -> - if channel == heartbeatChannel - lastHeartbeat = Date.now() - - sub.isAlive = () -> - timeSinceLastHeartbeat = Date.now() - lastHeartbeat - return (timeSinceLastHeartbeat < isAliveTimeout) - - setInterval () -> - pub.publish heartbeatChannel, "PING" - , heartbeatInterval - - return sub - - - - + return client \ No newline at end of file From 6da4f3eef5b72d63c2bb9fa221b2ef54a6fee889 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Wed, 19 Nov 2014 16:41:28 +0000 Subject: [PATCH 20/79] bump package --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 73385e3024..3569f57082 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "0.0.5", + "version": "0.0.6", "description": "redis wrapper for node which will either use sentinal or normal redis", "main": "index.js", "author": "henry oswald @ sharelatex", From e133c7101e4b9e5d1f904c9732dfc2261dd2ec7f Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Wed, 19 Nov 2014 23:18:56 +0000 Subject: [PATCH 21/79] incremented version and added basic health check function in --- libraries/redis-wrapper/index.coffee | 37 +++++++++++++++++++++++++++- libraries/redis-wrapper/package.json | 2 +- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index fd71b221a3..fa85c9f457 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -18,4 +18,39 @@ module.exports = RedisSharelatex = delete standardOpts.port delete standardOpts.host client = require("redis").createClient opts.port, opts.host, standardOpts - return client \ No newline at end of file + return client + + + activeHealthCheckRedis: (connectionInfo)-> + sub = RedisSharelatex.createClient(connectionInfo) + pub = RedisSharelatex.createClient(connectionInfo) + + heartbeatInterval = 2000 #ms + isAliveTimeout = 10000 #ms + + id = require("crypto").pseudoRandomBytes(16).toString("hex") + heartbeatChannel = "heartbeat-#{id}" + lastHeartbeat = Date.now() + + sub.subscribe heartbeatChannel, (error) -> + if error? + console.error "ERROR: failed to subscribe to #{heartbeatChannel} channel", error + sub.on "message", (channel, message) -> + if channel == heartbeatChannel + lastHeartbeat = Date.now() + + setInterval -> + pub.publish heartbeatChannel, "PING" + , heartbeatInterval + + isAlive = -> + timeSinceLastHeartbeat = Date.now() - lastHeartbeat + if timeSinceLastHeartbeat > isAliveTimeout + console.error "heartbeat from redis timed out" + return false + else + return true + + return { + isAlive:isAlive + } diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 3569f57082..d23cd89692 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "0.0.6", + "version": "0.0.7", "description": "redis wrapper for node which will either use sentinal or normal redis", "main": "index.js", "author": "henry oswald @ sharelatex", From ef0ea2ace26f328c9738bed60b7600c21877e933 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 20 Nov 2014 11:09:44 +0000 Subject: [PATCH 22/79] if redis fails once mark it to always fail --- libraries/redis-wrapper/index.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index fa85c9f457..386765af38 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -25,6 +25,7 @@ module.exports = RedisSharelatex = sub = RedisSharelatex.createClient(connectionInfo) pub = RedisSharelatex.createClient(connectionInfo) + redisIsOk = true heartbeatInterval = 2000 #ms isAliveTimeout = 10000 #ms @@ -45,8 +46,11 @@ module.exports = RedisSharelatex = isAlive = -> timeSinceLastHeartbeat = Date.now() - lastHeartbeat - if timeSinceLastHeartbeat > isAliveTimeout + if !redisIsOk + return false + else if timeSinceLastHeartbeat > isAliveTimeout console.error "heartbeat from redis timed out" + redisIsOk = false return false else return true From 119ae80853b501d99e63a040404d1e2897d2822f Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 20 Nov 2014 11:09:57 +0000 Subject: [PATCH 23/79] bump package.json --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index d23cd89692..784412b4e7 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "0.0.7", + "version": "0.0.8", "description": "redis wrapper for node which will either use sentinal or normal redis", "main": "index.js", "author": "henry oswald @ sharelatex", From 917ce27a2c51cd05d19ad9c96cc2ed14bc98a8fe Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 20 Nov 2014 12:50:19 +0000 Subject: [PATCH 24/79] add a double message check --- libraries/redis-wrapper/index.coffee | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 386765af38..770a5030d0 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -26,6 +26,7 @@ module.exports = RedisSharelatex = pub = RedisSharelatex.createClient(connectionInfo) redisIsOk = true + lastPingMessage = "" heartbeatInterval = 2000 #ms isAliveTimeout = 10000 #ms @@ -37,11 +38,15 @@ module.exports = RedisSharelatex = if error? console.error "ERROR: failed to subscribe to #{heartbeatChannel} channel", error sub.on "message", (channel, message) -> + if lastPingMessage == message #we got the same message twice + redisIsOk = false + lastPingMessage = message if channel == heartbeatChannel lastHeartbeat = Date.now() setInterval -> - pub.publish heartbeatChannel, "PING" + message = "ping:#{Date.now()}" + pub.publish heartbeatChannel, message , heartbeatInterval isAlive = -> From 3334a55944a8692cc2644b2cf52800abcea1fafa Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 20 Nov 2014 12:50:31 +0000 Subject: [PATCH 25/79] bump package --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 784412b4e7..d81f72cce4 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "0.0.8", + "version": "0.0.9", "description": "redis wrapper for node which will either use sentinal or normal redis", "main": "index.js", "author": "henry oswald @ sharelatex", From 3b58e390fdd77c2c815394a47484c4b83f7c4ab4 Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 12 Apr 2017 14:53:34 +0100 Subject: [PATCH 26/79] Include ioredis as a driver to be able to handle cluster configs --- libraries/redis-wrapper/index.coffee | 98 ++++++++++++++++------------ libraries/redis-wrapper/package.json | 7 +- 2 files changed, 62 insertions(+), 43 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 770a5030d0..8eda79ce13 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -13,53 +13,71 @@ module.exports = RedisSharelatex = delete standardOpts.endpoints delete standardOpts.masterName client = require("redis-sentinel").createClient opts.endpoints, opts.masterName, standardOpts + client.healthCheck = RedisSharelatex.singleInstanceHealthCheckBuilder(client) + else if opts.cluster? + Redis = require("ioredis") + client = new Redis.Cluster(opts.cluster) + client.healthCheck = RedisSharelatex.clusterHealthCheckBuilder(client) + RedisSharelatex._monkeyPatchIoredisExec(client) else standardOpts = _.clone(opts) delete standardOpts.port delete standardOpts.host client = require("redis").createClient opts.port, opts.host, standardOpts + client.healthCheck = RedisSharelatex.singleInstanceHealthCheckBuilder(client) return client - - - activeHealthCheckRedis: (connectionInfo)-> - sub = RedisSharelatex.createClient(connectionInfo) - pub = RedisSharelatex.createClient(connectionInfo) + + HEARTBEAT_TIMEOUT: 2000 + singleInstanceHealthCheckBuilder: (client) -> + healthCheck = (callback) -> + RedisSharelatex._checkClient(client, callback) + return healthCheck + + clusterHealthCheckBuilder: (client) -> + healthCheck = (callback) -> + jobs = client.rclient.nodes("all").map (node) => + (cb) => RedisSharelatex._checkClient(node, cb) + async.parallel jobs, callback - redisIsOk = true - lastPingMessage = "" - heartbeatInterval = 2000 #ms - isAliveTimeout = 10000 #ms + return healthCheck + + _checkClient: (client, callback) -> + callback = _.once(callback) + timer = setTimeout () -> + error = new Error("redis client ping check timed out") + console.error { + err: error, + key: client.options?.key # only present for cluster + }, "client timed out" + callback(error) + , RedisSharelatex.HEARTBEAT_TIMEOUT + client.ping (err) -> + clearTimeout timer + callback(err) - id = require("crypto").pseudoRandomBytes(16).toString("hex") - heartbeatChannel = "heartbeat-#{id}" - lastHeartbeat = Date.now() + _monkeyPatchIoredisExec: (client) -> + _multi = client.multi + client.multi = (args...) -> + multi = _multi.call(client, args...) + _exec = multi.exec + multi.exec = (args..., callback) -> + _exec.call multi, args..., (error, result) -> + # ioredis exec returns an results like: + # [ [null, 42], [null, "foo"] ] + # where the first entries in each 2-tuple are + # presumably errors for each individual command, + # and the second entry is the result. We need to transform + # this into the same result as the old redis driver: + # [ 42, "foo" ] + filtered_result = [] + for entry in result or [] + if entry[0]? + return callback(entry[0]) + else + filtered_result.push entry[1] + callback error, filtered_result + return multi + - sub.subscribe heartbeatChannel, (error) -> - if error? - console.error "ERROR: failed to subscribe to #{heartbeatChannel} channel", error - sub.on "message", (channel, message) -> - if lastPingMessage == message #we got the same message twice - redisIsOk = false - lastPingMessage = message - if channel == heartbeatChannel - lastHeartbeat = Date.now() - - setInterval -> - message = "ping:#{Date.now()}" - pub.publish heartbeatChannel, message - , heartbeatInterval + - isAlive = -> - timeSinceLastHeartbeat = Date.now() - lastHeartbeat - if !redisIsOk - return false - else if timeSinceLastHeartbeat > isAliveTimeout - console.error "heartbeat from redis timed out" - redisIsOk = false - return false - else - return true - - return { - isAlive:isAlive - } diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index d81f72cce4..2ea0fb66de 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,9 +1,9 @@ { "name": "redis-sharelatex", - "version": "0.0.9", - "description": "redis wrapper for node which will either use sentinal or normal redis", + "version": "1.0.0", + "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", - "author": "henry oswald @ sharelatex", + "author": "ShareLaTeX", "license": "ISC", "dependencies": { "chai": "1.9.1", @@ -11,6 +11,7 @@ "grunt": "0.4.5", "grunt-contrib-coffee": "0.11.1", "grunt-mocha-test": "0.12.0", + "ioredis": "^2.5.0", "mocha": "1.21.4", "redis": "0.12.1", "redis-sentinel": "0.1.1", From 89397e4c50c508390387ee1c6a447e50f72e9bf7 Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 12 Apr 2017 16:58:59 +0100 Subject: [PATCH 27/79] Get unit tests running and add one for ioredis --- libraries/redis-wrapper/test.coffee | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/libraries/redis-wrapper/test.coffee b/libraries/redis-wrapper/test.coffee index f166c34ba8..883ddfa346 100644 --- a/libraries/redis-wrapper/test.coffee +++ b/libraries/redis-wrapper/test.coffee @@ -21,15 +21,17 @@ describe "index", -> @redis = SandboxedModule.require modulePath, requires: "redis-sentinel":@sentinel "redis":@normalRedis + "ioredis": @ioredis = + Cluster: class Cluster + constructor: (@config) -> @auth_pass = "1234 pass" @endpoints = [ {host: '127.0.0.1', port: 26379}, {host: '127.0.0.1', port: 26380} ] - describe "sentinel", -> + describe "sentinel", -> beforeEach -> - @masterName = "my master" @sentinelOptions = endpoints:@endpoints @@ -44,11 +46,10 @@ describe "index", -> it "should pass the options correctly though", -> client = @redis.createClient @sentinelOptions - @sentinel.createClient.calledWith(@endpoints, @masterName, auth_pass:@auth_pass).should.equal true + @sentinel.createClient.calledWith(@endpoints, @masterName, {auth_pass:@auth_pass, retry_max_delay: 5000}).should.equal true client.should.equal @sentinelClient describe "normal redis", -> - beforeEach -> @standardOpts = auth_pass: @auth_pass @@ -63,9 +64,16 @@ describe "index", -> it "should use the normal redis driver if a non array is passed", -> client = @redis.createClient @standardOpts - @normalRedis.createClient.calledWith(@standardOpts.port, @standardOpts.host, auth_pass:@auth_pass).should.equal true + @normalRedis.createClient.calledWith(@standardOpts.port, @standardOpts.host, {auth_pass:@auth_pass, retry_max_delay: 5000}).should.equal true + describe "cluster", -> + beforeEach -> + @cluster = [{"mock": "cluster"}, { "mock": "cluster2"}] + it "should pass the options correctly though", -> + client = @redis.createClient cluster: @cluster + assert(client instanceof @ioredis.Cluster) + client.config.should.deep.equal @cluster describe "setting the password", -> beforeEach -> @@ -81,10 +89,10 @@ describe "index", -> it "should set the auth_pass from password if password exists for normal redis", -> client = @redis.createClient @standardOpts - @normalRedis.createClient.calledWith(@standardOpts.port, @standardOpts.host, auth_pass:@auth_pass).should.equal true + @normalRedis.createClient.calledWith(@standardOpts.port, @standardOpts.host, {auth_pass:@auth_pass, retry_max_delay: 5000}).should.equal true it "should set the auth_pass from password if password exists for sentinal", -> client = @redis.createClient @sentinelOptions - @sentinel.createClient.calledWith(@endpoints, @masterName, auth_pass:@auth_pass).should.equal true + @sentinel.createClient.calledWith(@endpoints, @masterName, {auth_pass:@auth_pass, retry_max_delay: 5000}).should.equal true From 6923ca0d5fad7a9bedfc1142334d625ba16b0c46 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 25 Apr 2017 15:34:32 +0100 Subject: [PATCH 28/79] add test for ioredis monkey patching --- libraries/redis-wrapper/test.coffee | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libraries/redis-wrapper/test.coffee b/libraries/redis-wrapper/test.coffee index 883ddfa346..0dc5c8ad74 100644 --- a/libraries/redis-wrapper/test.coffee +++ b/libraries/redis-wrapper/test.coffee @@ -75,6 +75,27 @@ describe "index", -> assert(client instanceof @ioredis.Cluster) client.config.should.deep.equal @cluster + describe "monkey patch ioredis exec", -> + beforeEach -> + @callback = sinon.stub() + @results = [] + @multiOrig = { exec: sinon.stub().yields(null, @results)} + @client = { multi: sinon.stub().returns(@multiOrig) } + @redis._monkeyPatchIoredisExec(@client) + @multi = @client.multi() + + it "should return the old redis format for an array", -> + @results[0] = [null, 42] + @results[1] = [null, "foo"] + @multi.exec @callback + @callback.calledWith(null, [42, "foo"]).should.equal true + + it "should return the old redis format when there is an error", -> + @results[0] = [null, 42] + @results[1] = ["error", "foo"] + @multi.exec @callback + @callback.calledWith("error").should.equal true + describe "setting the password", -> beforeEach -> @standardOpts = From 92f22bc1a121274aa17a81ce099a74223fd3c9f0 Mon Sep 17 00:00:00 2001 From: James Allen Date: Thu, 4 May 2017 15:38:07 +0100 Subject: [PATCH 29/79] Fix redis cluster health check --- libraries/redis-wrapper/index.coffee | 3 ++- libraries/redis-wrapper/package.json | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 8eda79ce13..5487bd52b2 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -1,4 +1,5 @@ _ = require("underscore") +async = require "async" module.exports = RedisSharelatex = createClient: (opts = {port: 6379, host: "localhost"})-> @@ -35,7 +36,7 @@ module.exports = RedisSharelatex = clusterHealthCheckBuilder: (client) -> healthCheck = (callback) -> - jobs = client.rclient.nodes("all").map (node) => + jobs = client.nodes("all").map (node) => (cb) => RedisSharelatex._checkClient(node, cb) async.parallel jobs, callback diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 2ea0fb66de..654a9502b3 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -6,6 +6,7 @@ "author": "ShareLaTeX", "license": "ISC", "dependencies": { + "async": "^2.4.0", "chai": "1.9.1", "coffee-script": "1.8.0", "grunt": "0.4.5", From da85837e6f50f63967246575e9997b2aae6a45e8 Mon Sep 17 00:00:00 2001 From: James Allen Date: Thu, 4 May 2017 15:41:43 +0100 Subject: [PATCH 30/79] Update package.json --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 654a9502b3..915ac0fcb3 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.0", + "version": "1.0.1", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", From 90e0b4b273d12a8af3b04b13fa69cb47558f28cf Mon Sep 17 00:00:00 2001 From: James Allen Date: Fri, 5 May 2017 13:36:39 +0100 Subject: [PATCH 31/79] Gracefully handle missing callback to exec in ioredis --- libraries/redis-wrapper/index.coffee | 4 ++-- libraries/redis-wrapper/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 5487bd52b2..aa6e43cb1f 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -61,8 +61,8 @@ module.exports = RedisSharelatex = client.multi = (args...) -> multi = _multi.call(client, args...) _exec = multi.exec - multi.exec = (args..., callback) -> - _exec.call multi, args..., (error, result) -> + multi.exec = (callback = () ->) -> + _exec.call multi, (error, result) -> # ioredis exec returns an results like: # [ [null, 42], [null, "foo"] ] # where the first entries in each 2-tuple are diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 915ac0fcb3..2f47b8cd92 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.1", + "version": "1.0.2", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", From bce937f56227383a6bfa65f1b674dfa779b4e8e3 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Fri, 16 Jun 2017 15:28:55 +0100 Subject: [PATCH 32/79] add support for passing options to cluster --- libraries/redis-wrapper/index.coffee | 4 +++- libraries/redis-wrapper/package.json | 2 +- libraries/redis-wrapper/test.coffee | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index aa6e43cb1f..ba9a659a98 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -17,7 +17,9 @@ module.exports = RedisSharelatex = client.healthCheck = RedisSharelatex.singleInstanceHealthCheckBuilder(client) else if opts.cluster? Redis = require("ioredis") - client = new Redis.Cluster(opts.cluster) + standardOpts = _.clone(opts) + delete standardOpts.cluster + client = new Redis.Cluster(opts.cluster, standardOpts) client.healthCheck = RedisSharelatex.clusterHealthCheckBuilder(client) RedisSharelatex._monkeyPatchIoredisExec(client) else diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 2f47b8cd92..cc8e847b39 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.2", + "version": "1.0.3", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", diff --git a/libraries/redis-wrapper/test.coffee b/libraries/redis-wrapper/test.coffee index 0dc5c8ad74..e2bfa926b8 100644 --- a/libraries/redis-wrapper/test.coffee +++ b/libraries/redis-wrapper/test.coffee @@ -23,7 +23,7 @@ describe "index", -> "redis":@normalRedis "ioredis": @ioredis = Cluster: class Cluster - constructor: (@config) -> + constructor: (@config, @options) -> @auth_pass = "1234 pass" @endpoints = [ {host: '127.0.0.1', port: 26379}, @@ -69,12 +69,23 @@ describe "index", -> describe "cluster", -> beforeEach -> @cluster = [{"mock": "cluster"}, { "mock": "cluster2"}] + @extraOptions = {keepAlive:100} + @settings = + cluster: @cluster + redisOptions: @extraOptions - it "should pass the options correctly though", -> + it "should pass the options correctly though with no options", -> client = @redis.createClient cluster: @cluster assert(client instanceof @ioredis.Cluster) client.config.should.deep.equal @cluster + it "should pass the options correctly though with additional options", -> + client = @redis.createClient @settings + assert(client instanceof @ioredis.Cluster) + client.config.should.deep.equal @cluster + # need to use expect here because of _.clone in sandbox + expect(client.options).to.deep.equal {redisOptions: @extraOptions, retry_max_delay: 5000} + describe "monkey patch ioredis exec", -> beforeEach -> @callback = sinon.stub() From bda88c035649fc6d5df61d52435959e623072232 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 19 Jun 2017 15:46:21 +0100 Subject: [PATCH 33/79] remove the key_schema from options passed to redis --- libraries/redis-wrapper/index.coffee | 1 + libraries/redis-wrapper/test.coffee | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index ba9a659a98..2dd8d23fe3 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -19,6 +19,7 @@ module.exports = RedisSharelatex = Redis = require("ioredis") standardOpts = _.clone(opts) delete standardOpts.cluster + delete standardOpts.key_schema client = new Redis.Cluster(opts.cluster, standardOpts) client.healthCheck = RedisSharelatex.clusterHealthCheckBuilder(client) RedisSharelatex._monkeyPatchIoredisExec(client) diff --git a/libraries/redis-wrapper/test.coffee b/libraries/redis-wrapper/test.coffee index e2bfa926b8..84e84f0894 100644 --- a/libraries/redis-wrapper/test.coffee +++ b/libraries/redis-wrapper/test.coffee @@ -73,12 +73,19 @@ describe "index", -> @settings = cluster: @cluster redisOptions: @extraOptions + key_schema: {foo: (x) -> "#{x}"} it "should pass the options correctly though with no options", -> client = @redis.createClient cluster: @cluster assert(client instanceof @ioredis.Cluster) client.config.should.deep.equal @cluster + it "should not pass the key_schema through to the driver", -> + client = @redis.createClient cluster: @cluster, key_schema: "foobar" + assert(client instanceof @ioredis.Cluster) + client.config.should.deep.equal @cluster + expect(client.options).to.deep.equal {retry_max_delay: 5000} + it "should pass the options correctly though with additional options", -> client = @redis.createClient @settings assert(client instanceof @ioredis.Cluster) From 66c09a770eb01839b6a54b520d1c2923eb9e8b89 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 24 Oct 2017 10:46:38 +0100 Subject: [PATCH 34/79] separate out devDependencies --- libraries/redis-wrapper/package.json | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index cc8e847b39..175d476629 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -6,18 +6,20 @@ "author": "ShareLaTeX", "license": "ISC", "dependencies": { - "async": "^2.4.0", - "chai": "1.9.1", + "async": "^2.5.0", "coffee-script": "1.8.0", + "ioredis": "^2.5.0", + "redis": "0.12.1", + "redis-sentinel": "0.1.1", + "underscore": "1.7.0" + }, + "devDependencies": { + "chai": "1.9.1", "grunt": "0.4.5", "grunt-contrib-coffee": "0.11.1", "grunt-mocha-test": "0.12.0", - "ioredis": "^2.5.0", "mocha": "1.21.4", - "redis": "0.12.1", - "redis-sentinel": "0.1.1", "sandboxed-module": "1.0.1", - "sinon": "1.10.3", - "underscore": "1.7.0" + "sinon": "1.10.3" } } From 1737ddbf29ccd3393b9077e200f011b62901ea01 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 24 Oct 2017 10:48:57 +0100 Subject: [PATCH 35/79] update ioredis to 3.2.1 --- libraries/redis-wrapper/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 175d476629..6fec265c09 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.3", + "version": "1.0.4", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", @@ -8,7 +8,7 @@ "dependencies": { "async": "^2.5.0", "coffee-script": "1.8.0", - "ioredis": "^2.5.0", + "ioredis": "^3.2.1", "redis": "0.12.1", "redis-sentinel": "0.1.1", "underscore": "1.7.0" From dd3b8eae45451647bfd4d2bed73b10a1e8d34489 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 22 Jan 2019 15:45:41 +0000 Subject: [PATCH 36/79] bump ioredis to 4.6.0 which lets us use natMap, package goes to 1.0.5 --- libraries/redis-wrapper/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 6fec265c09..e72e1c8727 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.4", + "version": "1.0.5", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", @@ -8,7 +8,7 @@ "dependencies": { "async": "^2.5.0", "coffee-script": "1.8.0", - "ioredis": "^3.2.1", + "ioredis": "4.6.0", "redis": "0.12.1", "redis-sentinel": "0.1.1", "underscore": "1.7.0" From f4b2f7742e39c14d5d716d798348705d61f16d47 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Thu, 11 Apr 2019 15:24:27 +0100 Subject: [PATCH 37/79] allow patch updates to ioredis 4.6.0 --- libraries/redis-wrapper/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index e72e1c8727..ed629e33b6 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.5", + "version": "1.0.6", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", @@ -8,7 +8,7 @@ "dependencies": { "async": "^2.5.0", "coffee-script": "1.8.0", - "ioredis": "4.6.0", + "ioredis": "~4.6.0", "redis": "0.12.1", "redis-sentinel": "0.1.1", "underscore": "1.7.0" From db590651ee833e1bf1ab9865854094d0535088e0 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Fri, 3 May 2019 11:33:24 +0100 Subject: [PATCH 38/79] make ioredis the driver for standard connections --- libraries/redis-wrapper/index.coffee | 9 +++------ libraries/redis-wrapper/package.json | 1 - 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 2dd8d23fe3..971e438033 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -6,9 +6,6 @@ module.exports = RedisSharelatex = if !opts.retry_max_delay? opts.retry_max_delay = 5000 # ms - if opts.password? - opts.auth_pass = opts.password - delete opts.password if opts.endpoints? standardOpts = _.clone(opts) delete standardOpts.endpoints @@ -25,9 +22,9 @@ module.exports = RedisSharelatex = RedisSharelatex._monkeyPatchIoredisExec(client) else standardOpts = _.clone(opts) - delete standardOpts.port - delete standardOpts.host - client = require("redis").createClient opts.port, opts.host, standardOpts + ioredis = require("ioredis") + client = new ioredis(standardOpts) + RedisSharelatex._monkeyPatchIoredisExec(client) client.healthCheck = RedisSharelatex.singleInstanceHealthCheckBuilder(client) return client diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index ed629e33b6..8a9b871358 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -9,7 +9,6 @@ "async": "^2.5.0", "coffee-script": "1.8.0", "ioredis": "~4.6.0", - "redis": "0.12.1", "redis-sentinel": "0.1.1", "underscore": "1.7.0" }, From d1dc6b8ce782b78343df82c6e89237f637fe73cc Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Fri, 3 May 2019 11:37:32 +0100 Subject: [PATCH 39/79] bump ioredis --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 8a9b871358..3a0a2d6e79 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -8,7 +8,7 @@ "dependencies": { "async": "^2.5.0", "coffee-script": "1.8.0", - "ioredis": "~4.6.0", + "ioredis": "~4.9.1", "redis-sentinel": "0.1.1", "underscore": "1.7.0" }, From a4bc5ba5b61c230b8cc05c95f2e232cb32b9ac25 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 20 May 2019 16:15:54 +0100 Subject: [PATCH 40/79] fix tests for ioredis as default --- libraries/redis-wrapper/test.coffee | 52 +++++++++++------------------ 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/libraries/redis-wrapper/test.coffee b/libraries/redis-wrapper/test.coffee index 84e84f0894..ae74ee7aa9 100644 --- a/libraries/redis-wrapper/test.coffee +++ b/libraries/redis-wrapper/test.coffee @@ -11,19 +11,28 @@ describe "index", -> beforeEach -> @settings = {} - @sentinelClient = set:-> - @normalRedisClient = get: -> + @sentinelClient = + set: -> + on: -> + @normalRedisClient = + get: -> + on: -> + @ioredisConstructor = ioredisConstructor = sinon.stub() @sentinel = createClient: sinon.stub().returns(@sentinelClient) @normalRedis = createClient: sinon.stub().returns(@normalRedisClient) + @ioredis = class IoRedis + constructor: ioredisConstructor + on: sinon.stub() + @ioredis.Cluster = class Cluster + constructor: (@config, @options) -> + on: sinon.stub() @redis = SandboxedModule.require modulePath, requires: "redis-sentinel":@sentinel "redis":@normalRedis - "ioredis": @ioredis = - Cluster: class Cluster - constructor: (@config, @options) -> + "ioredis": @ioredis @auth_pass = "1234 pass" @endpoints = [ {host: '127.0.0.1', port: 26379}, @@ -49,22 +58,22 @@ describe "index", -> @sentinel.createClient.calledWith(@endpoints, @masterName, {auth_pass:@auth_pass, retry_max_delay: 5000}).should.equal true client.should.equal @sentinelClient - describe "normal redis", -> + describe "single node redis", -> beforeEach -> @standardOpts = auth_pass: @auth_pass port: 1234 host: "redis.mysite.env" - it "should use the normal redis driver if a non array is passed", -> + it "should use the ioredis driver in single-instance mode if a non array is passed", -> client = @redis.createClient @standardOpts @sentinel.createClient.called.should.equal false - @normalRedis.createClient.called.should.equal true - client.should.equal @normalRedisClient + @normalRedis.createClient.called.should.equal false + assert.equal(client.constructor, @ioredis) - it "should use the normal redis driver if a non array is passed", -> + it "should call createClient for the ioredis driver in single-instance mode if a non array is passed", -> client = @redis.createClient @standardOpts - @normalRedis.createClient.calledWith(@standardOpts.port, @standardOpts.host, {auth_pass:@auth_pass, retry_max_delay: 5000}).should.equal true + @ioredisConstructor.calledWith(@standardOpts).should.equal true describe "cluster", -> beforeEach -> @@ -114,24 +123,3 @@ describe "index", -> @multi.exec @callback @callback.calledWith("error").should.equal true - describe "setting the password", -> - beforeEach -> - @standardOpts = - password: @auth_pass - port: 1234 - host: "redis.mysite.env" - - @sentinelOptions = - endpoints:@endpoints - masterName:@masterName - password: @auth_pass - - it "should set the auth_pass from password if password exists for normal redis", -> - client = @redis.createClient @standardOpts - @normalRedis.createClient.calledWith(@standardOpts.port, @standardOpts.host, {auth_pass:@auth_pass, retry_max_delay: 5000}).should.equal true - - it "should set the auth_pass from password if password exists for sentinal", -> - client = @redis.createClient @sentinelOptions - @sentinel.createClient.calledWith(@endpoints, @masterName, {auth_pass:@auth_pass, retry_max_delay: 5000}).should.equal true - - From b2d6fb77db5a628314a1df3a59e1825eaeb3fa8c Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 30 May 2019 10:12:40 +0100 Subject: [PATCH 41/79] bump to 1.0.7 --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 3a0a2d6e79..2baadb480b 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.6", + "version": "1.0.7", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", From 6600c2e050b38ced171731942b55e6f81665f290 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 30 May 2019 10:13:05 +0100 Subject: [PATCH 42/79] add redis options inc host ip to error message --- libraries/redis-wrapper/index.coffee | 1 + libraries/redis-wrapper/package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 971e438033..91d2d5ad92 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -49,6 +49,7 @@ module.exports = RedisSharelatex = console.error { err: error, key: client.options?.key # only present for cluster + clientOptions: client.options }, "client timed out" callback(error) , RedisSharelatex.HEARTBEAT_TIMEOUT diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 2baadb480b..fed232067c 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.7", + "version": "1.0.8", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", From d694674b786d1ea62bbf897731d10afd1d932a51 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Thu, 30 May 2019 14:36:54 +0100 Subject: [PATCH 43/79] put host in error message --- libraries/redis-wrapper/index.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 91d2d5ad92..18aa47c65f 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -45,7 +45,7 @@ module.exports = RedisSharelatex = _checkClient: (client, callback) -> callback = _.once(callback) timer = setTimeout () -> - error = new Error("redis client ping check timed out") + error = new Error("redis client ping check timed out #{client?.options?.host}") console.error { err: error, key: client.options?.key # only present for cluster From 630a957d7b5ad8f8e60779867252c20df456a165 Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 2 Jul 2019 11:56:21 +0100 Subject: [PATCH 44/79] bump ioredis to have naptmap for sentinal --- libraries/redis-wrapper/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index fed232067c..ced273277c 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.8", + "version": "1.0.9", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", @@ -8,7 +8,7 @@ "dependencies": { "async": "^2.5.0", "coffee-script": "1.8.0", - "ioredis": "~4.9.1", + "ioredis": "~4.11.1", "redis-sentinel": "0.1.1", "underscore": "1.7.0" }, From 2435099766bb78d81f4d85e8be7b704fd8789164 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Thu, 19 Sep 2019 15:05:32 +0100 Subject: [PATCH 45/79] make health check more robust --- libraries/redis-wrapper/health.coffee | 13 ++++++++++ libraries/redis-wrapper/index.coffee | 36 +++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 libraries/redis-wrapper/health.coffee diff --git a/libraries/redis-wrapper/health.coffee b/libraries/redis-wrapper/health.coffee new file mode 100644 index 0000000000..feb02a7f88 --- /dev/null +++ b/libraries/redis-wrapper/health.coffee @@ -0,0 +1,13 @@ +# execute this script with a redis container running to test the health check +# starting and stopping redis with this script running is a good test + +redis = require "./index.coffee" + +rclient = redis.createClient({host:"localhost",port:"6379"}) +setInterval () -> + rclient.healthCheck (err) -> + if err? + console.log "HEALTH CHECK FAILED", err + else + console.log "HEALTH CHECK OK" +, 1000 \ No newline at end of file diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 18aa47c65f..674dae5594 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -1,5 +1,13 @@ _ = require("underscore") async = require "async" +os = require('os') +crypto = require('crypto') + +# generate unique values for health check +HOST = os.hostname() +PID = process.pid +RND = crypto.randomBytes(4).toString('hex') +COUNT = 0 module.exports = RedisSharelatex = createClient: (opts = {port: 6379, host: "localhost"})-> @@ -44,19 +52,37 @@ module.exports = RedisSharelatex = _checkClient: (client, callback) -> callback = _.once(callback) + # check the redis connection by storing and retrieving a unique key/value pair + uniqueToken = "host=#{HOST}:pid=#{PID}:random=#{RND}:time=#{Date.now()}:count=#{COUNT++}" timer = setTimeout () -> - error = new Error("redis client ping check timed out #{client?.options?.host}") + error = new Error("redis client health check timed out #{client?.options?.host}") console.error { err: error, key: client.options?.key # only present for cluster clientOptions: client.options + uniqueToken: uniqueToken }, "client timed out" callback(error) , RedisSharelatex.HEARTBEAT_TIMEOUT - client.ping (err) -> - clearTimeout timer - callback(err) - + healthCheckKey = "_redis-wrapper:healthCheckKey:{#{uniqueToken}}" + healthCheckValue = "_redis-wrapper:healthCheckValue:{#{uniqueToken}}" + # set the unique key/value pair + multi = client.multi() + multi.set healthCheckKey, healthCheckValue, "EX", 60 + multi.exec (err, reply) -> + if err? + clearTimeout timer + return callback(err) + # check that we can retrieve the unique key/value pair + multi = client.multi() + multi.get healthCheckKey + multi.del healthCheckKey + multi.exec (err, reply) -> + clearTimeout timer + return callback(err) if err? + return callback(new Error("bad response from redis health check")) if reply?[0] isnt healthCheckValue + return callback() + _monkeyPatchIoredisExec: (client) -> _multi = client.multi client.multi = (args...) -> From d9214b6eebe00c6964c51370e2ca3251bf0513e5 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Thu, 19 Sep 2019 15:41:43 +0100 Subject: [PATCH 46/79] check full reply in health check --- libraries/redis-wrapper/index.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 674dae5594..05f5fa9fbb 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -80,7 +80,7 @@ module.exports = RedisSharelatex = multi.exec (err, reply) -> clearTimeout timer return callback(err) if err? - return callback(new Error("bad response from redis health check")) if reply?[0] isnt healthCheckValue + return callback(new Error("bad response from redis health check")) if reply?[0] isnt healthCheckValue or reply?[1] isnt 1 return callback() _monkeyPatchIoredisExec: (client) -> From 626511fa732e56003090f6cc847cf9347197eeac Mon Sep 17 00:00:00 2001 From: John Lees-Miller Date: Thu, 19 Sep 2019 16:11:59 +0100 Subject: [PATCH 47/79] Bump version number --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index ced273277c..b6ff6ef757 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.9", + "version": "1.0.10", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", From c8d50d0ee999c1fc6b7783f7f6d1abf8d85441ef Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Tue, 1 Oct 2019 16:43:44 +0100 Subject: [PATCH 48/79] upgrade ioredis to v4.14.1 --- libraries/redis-wrapper/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index b6ff6ef757..e7c5e9d830 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.10", + "version": "1.0.11", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", @@ -8,7 +8,7 @@ "dependencies": { "async": "^2.5.0", "coffee-script": "1.8.0", - "ioredis": "~4.11.1", + "ioredis": "~4.14.1", "redis-sentinel": "0.1.1", "underscore": "1.7.0" }, @@ -21,4 +21,4 @@ "sandboxed-module": "1.0.1", "sinon": "1.10.3" } -} +} \ No newline at end of file From 264e549fc56aadc61d23660d35531bcb7760b78d Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Tue, 31 Mar 2020 09:39:10 +0100 Subject: [PATCH 49/79] bump io redis to 4.16.1 --- libraries/redis-wrapper/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index e7c5e9d830..652563527f 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.11", + "version": "1.0.12", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", @@ -8,7 +8,7 @@ "dependencies": { "async": "^2.5.0", "coffee-script": "1.8.0", - "ioredis": "~4.14.1", + "ioredis": "~4.16.1", "redis-sentinel": "0.1.1", "underscore": "1.7.0" }, From cd6e36d7dcd7a56992df51898e2567aebe21a40a Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Mon, 1 Jun 2020 09:11:57 +0100 Subject: [PATCH 50/79] upgrade ioredis to 4.17.3 --- libraries/redis-wrapper/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 652563527f..7af287fad8 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "redis-sharelatex", - "version": "1.0.12", + "version": "1.0.13", "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", "main": "index.js", "author": "ShareLaTeX", @@ -8,7 +8,7 @@ "dependencies": { "async": "^2.5.0", "coffee-script": "1.8.0", - "ioredis": "~4.16.1", + "ioredis": "~4.17.3", "redis-sentinel": "0.1.1", "underscore": "1.7.0" }, @@ -21,4 +21,4 @@ "sandboxed-module": "1.0.1", "sinon": "1.10.3" } -} \ No newline at end of file +} From 90ad28c51ccf451b39e09ba3618f9c1c7d808735 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 12:37:33 +0000 Subject: [PATCH 51/79] [misc] drop support for redis-sentinel --- libraries/redis-wrapper/index.coffee | 8 +------- libraries/redis-wrapper/package.json | 1 - libraries/redis-wrapper/test.coffee | 30 ---------------------------- 3 files changed, 1 insertion(+), 38 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 05f5fa9fbb..bcb97d4657 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -14,13 +14,7 @@ module.exports = RedisSharelatex = if !opts.retry_max_delay? opts.retry_max_delay = 5000 # ms - if opts.endpoints? - standardOpts = _.clone(opts) - delete standardOpts.endpoints - delete standardOpts.masterName - client = require("redis-sentinel").createClient opts.endpoints, opts.masterName, standardOpts - client.healthCheck = RedisSharelatex.singleInstanceHealthCheckBuilder(client) - else if opts.cluster? + if opts.cluster? Redis = require("ioredis") standardOpts = _.clone(opts) delete standardOpts.cluster diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 7af287fad8..2ae31da636 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -9,7 +9,6 @@ "async": "^2.5.0", "coffee-script": "1.8.0", "ioredis": "~4.17.3", - "redis-sentinel": "0.1.1", "underscore": "1.7.0" }, "devDependencies": { diff --git a/libraries/redis-wrapper/test.coffee b/libraries/redis-wrapper/test.coffee index ae74ee7aa9..83ccdb2703 100644 --- a/libraries/redis-wrapper/test.coffee +++ b/libraries/redis-wrapper/test.coffee @@ -11,16 +11,11 @@ describe "index", -> beforeEach -> @settings = {} - @sentinelClient = - set: -> - on: -> @normalRedisClient = get: -> on: -> @ioredisConstructor = ioredisConstructor = sinon.stub() - @sentinel = - createClient: sinon.stub().returns(@sentinelClient) @normalRedis = createClient: sinon.stub().returns(@normalRedisClient) @ioredis = class IoRedis @@ -30,33 +25,9 @@ describe "index", -> constructor: (@config, @options) -> on: sinon.stub() @redis = SandboxedModule.require modulePath, requires: - "redis-sentinel":@sentinel "redis":@normalRedis "ioredis": @ioredis @auth_pass = "1234 pass" - @endpoints = [ - {host: '127.0.0.1', port: 26379}, - {host: '127.0.0.1', port: 26380} - ] - - describe "sentinel", -> - beforeEach -> - @masterName = "my master" - @sentinelOptions = - endpoints:@endpoints - masterName:@masterName - auth_pass:@auth_pass - - it "should use sentinal if the first argument in an array", -> - client = @redis.createClient @sentinelOptions - @sentinel.createClient.called.should.equal true - @normalRedis.createClient.called.should.equal false - client.should.equal @sentinelClient - - it "should pass the options correctly though", -> - client = @redis.createClient @sentinelOptions - @sentinel.createClient.calledWith(@endpoints, @masterName, {auth_pass:@auth_pass, retry_max_delay: 5000}).should.equal true - client.should.equal @sentinelClient describe "single node redis", -> beforeEach -> @@ -67,7 +38,6 @@ describe "index", -> it "should use the ioredis driver in single-instance mode if a non array is passed", -> client = @redis.createClient @standardOpts - @sentinel.createClient.called.should.equal false @normalRedis.createClient.called.should.equal false assert.equal(client.constructor, @ioredis) From 18fa1842305616b102aaef550446dc924f1dcfce Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 15:59:53 +0000 Subject: [PATCH 52/79] [misc] drop references for 'redis' package from unit tests --- libraries/redis-wrapper/test.coffee | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libraries/redis-wrapper/test.coffee b/libraries/redis-wrapper/test.coffee index 83ccdb2703..e3586ee735 100644 --- a/libraries/redis-wrapper/test.coffee +++ b/libraries/redis-wrapper/test.coffee @@ -11,13 +11,8 @@ describe "index", -> beforeEach -> @settings = {} - @normalRedisClient = - get: -> - on: -> @ioredisConstructor = ioredisConstructor = sinon.stub() - @normalRedis = - createClient: sinon.stub().returns(@normalRedisClient) @ioredis = class IoRedis constructor: ioredisConstructor on: sinon.stub() @@ -25,7 +20,6 @@ describe "index", -> constructor: (@config, @options) -> on: sinon.stub() @redis = SandboxedModule.require modulePath, requires: - "redis":@normalRedis "ioredis": @ioredis @auth_pass = "1234 pass" @@ -38,7 +32,6 @@ describe "index", -> it "should use the ioredis driver in single-instance mode if a non array is passed", -> client = @redis.createClient @standardOpts - @normalRedis.createClient.called.should.equal false assert.equal(client.constructor, @ioredis) it "should call createClient for the ioredis driver in single-instance mode if a non array is passed", -> From a53eef5e3d1b617e35bc8ad5a64e6ed2c62a225c Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 23 Sep 2019 12:41:53 +0200 Subject: [PATCH 53/79] [healthCheck] bring back support for redis cluster Assume `cluster-require-full-coverage=yes` is set for the redis cluster, which is the default value. We are writing into a single hash slot, resulting in a partial health check only. The 'cluster-require-full-coverage=yes' blocks writes as soon as any hash slot is not covered by an active primary. We are leveraging the health check build into the redis cluster topology to bring the scope of the single read/write/delete to the full cluster. REF: 1b3566d6c830289dc826da1d13b75d68205d8dec Signed-off-by: Jakob Ackermann --- libraries/redis-wrapper/index.coffee | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index bcb97d4657..88e97c9dac 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -37,12 +37,7 @@ module.exports = RedisSharelatex = return healthCheck clusterHealthCheckBuilder: (client) -> - healthCheck = (callback) -> - jobs = client.nodes("all").map (node) => - (cb) => RedisSharelatex._checkClient(node, cb) - async.parallel jobs, callback - - return healthCheck + return RedisSharelatex.singleInstanceHealthCheckBuilder(client) _checkClient: (client, callback) -> callback = _.once(callback) From dddb431034715accbd6516d977a68142f08b916c Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Sun, 5 Apr 2020 13:39:58 +0200 Subject: [PATCH 54/79] [misc] drop unused async Signed-off-by: Jakob Ackermann --- libraries/redis-wrapper/index.coffee | 1 - libraries/redis-wrapper/package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 88e97c9dac..da606655be 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -1,5 +1,4 @@ _ = require("underscore") -async = require "async" os = require('os') crypto = require('crypto') diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 2ae31da636..209d385d57 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -6,7 +6,6 @@ "author": "ShareLaTeX", "license": "ISC", "dependencies": { - "async": "^2.5.0", "coffee-script": "1.8.0", "ioredis": "~4.17.3", "underscore": "1.7.0" From 39809562fdaf659e242f99cd3c80b321f193a28a Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 16:03:33 +0000 Subject: [PATCH 55/79] [misc] use plain mocha for testing and bump devDependencies --- libraries/redis-wrapper/Gruntfile.coffee | 35 - libraries/redis-wrapper/package-lock.json | 1125 +++++++++++++++++++++ libraries/redis-wrapper/package.json | 14 +- 3 files changed, 1132 insertions(+), 42 deletions(-) delete mode 100644 libraries/redis-wrapper/Gruntfile.coffee create mode 100644 libraries/redis-wrapper/package-lock.json diff --git a/libraries/redis-wrapper/Gruntfile.coffee b/libraries/redis-wrapper/Gruntfile.coffee deleted file mode 100644 index 59bb3d34b6..0000000000 --- a/libraries/redis-wrapper/Gruntfile.coffee +++ /dev/null @@ -1,35 +0,0 @@ -module.exports = (grunt) -> - - # Project configuration. - grunt.initConfig - coffee: - server: - expand: true, - flatten: false, - cwd: 'app/coffee', - src: ['**/*.coffee'], - dest: 'app/js/', - ext: '.js' - - server_tests: - expand: true, - flatten: false, - cwd: 'test/unit/coffee', - src: ['**/*.coffee'], - dest: 'test/unit/js/', - ext: '.js' - - mochaTest: - unit: - options: - reporter: process.env.MOCHA_RUNNER || "spec" - grep: grunt.option("grep") - require: 'coffee-script/register' - src: ['test.coffee'] - - - grunt.loadNpmTasks 'grunt-contrib-coffee' - grunt.loadNpmTasks 'grunt-mocha-test' - - grunt.registerTask 'test:unit', ['mochaTest:unit'] - diff --git a/libraries/redis-wrapper/package-lock.json b/libraries/redis-wrapper/package-lock.json new file mode 100644 index 0000000000..499cab1181 --- /dev/null +++ b/libraries/redis-wrapper/package-lock.json @@ -0,0 +1,1125 @@ +{ + "name": "redis-sharelatex", + "version": "1.0.13", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@sinonjs/commons": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", + "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sinonjs/formatio": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", + "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^5.0.2" + } + }, + "@sinonjs/samsam": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.2.0.tgz", + "integrity": "sha512-CaIcyX5cDsjcW/ab7HposFWzV1kC++4HNsfnEdFJa7cP1QIuILAKV+BgfeqRXhcnSAc76r/Rh/O5C+300BwUIw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "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 + }, + "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" + } + } + } + }, + "cluster-key-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", + "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" + }, + "coffee-script": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.8.0.tgz", + "integrity": "sha1-nJ8dK0pSoADe0Vtll5FwNkgmPB0=", + "requires": { + "mkdirp": "~0.3.5" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "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 + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "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 + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ioredis": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.17.3.tgz", + "integrity": "sha512-iRvq4BOYzNFkDnSyhx7cmJNOi1x/HWYe+A4VXHBu4qpwJaGT1Mp+D2bVGJntH9K/Z/GeOM/Nprb8gB3bmitz1Q==", + "requires": { + "cluster-key-slot": "^1.1.0", + "debug": "^4.1.1", + "denque": "^1.1.0", + "lodash.defaults": "^4.2.0", + "lodash.flatten": "^4.4.0", + "redis-commands": "1.5.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "just-extend": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", + "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" + }, + "mocha": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", + "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", + "dev": true, + "requires": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.4.3", + "debug": "4.2.0", + "diff": "4.0.2", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.14.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.2", + "nanoid": "3.1.12", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "7.2.0", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.0.2", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "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" + } + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.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==" + }, + "nanoid": { + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", + "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", + "dev": true + }, + "nise": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", + "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "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 + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-to-regexp": { + "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" + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "redis-commands": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", + "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==" + }, + "redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" + }, + "redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", + "requires": { + "redis-errors": "^1.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-like": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "sandboxed-module": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-2.0.4.tgz", + "integrity": "sha512-AwEPOdO8mg/wJjr876yCHP2DHqVN0MaggEXhp6IIf3bcI5cYoQl9QrrCHSrvToHjvdEiS5x4TVZRgjD2bEmNTA==", + "dev": true, + "requires": { + "require-like": "0.1.2", + "stack-trace": "0.0.9" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "sinon": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.1.tgz", + "integrity": "sha512-naPfsamB5KEE1aiioaoqJ6MEhdUs/2vtI5w1hPAXX/UwvoPjXcwh1m5HiKx0HGgKR8lQSoFIgY5jM6KK8VrS9w==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/formatio": "^5.0.1", + "@sinonjs/samsam": "^5.2.0", + "diff": "^4.0.2", + "nise": "^4.0.4", + "supports-color": "^7.1.0" + }, + "dependencies": { + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.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 + }, + "stack-trace": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", + "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=", + "dev": true + }, + "standard-as-callback": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.0.1.tgz", + "integrity": "sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "workerpool": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", + "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", + "dev": true + }, + "wrap-ansi": { + "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": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.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 + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "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" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "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 + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "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" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "dependencies": { + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + } + } + } + } +} diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 209d385d57..2bd45e3d3c 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -5,18 +5,18 @@ "main": "index.js", "author": "ShareLaTeX", "license": "ISC", + "scripts": { + "test": "mocha --require coffee-script/register test.coffee" + }, "dependencies": { "coffee-script": "1.8.0", "ioredis": "~4.17.3", "underscore": "1.7.0" }, "devDependencies": { - "chai": "1.9.1", - "grunt": "0.4.5", - "grunt-contrib-coffee": "0.11.1", - "grunt-mocha-test": "0.12.0", - "mocha": "1.21.4", - "sandboxed-module": "1.0.1", - "sinon": "1.10.3" + "chai": "^4.2.0", + "mocha": "^8.2.1", + "sandboxed-module": "^2.0.4", + "sinon": "^9.2.1" } } From 69df7f5bb3e8cc1c7a7d028da4c745835854c25f Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 16:06:11 +0000 Subject: [PATCH 56/79] [misc] move test scripts into test/ tree --- libraries/redis-wrapper/package.json | 2 +- .../{health.coffee => test/scripts/standalone.coffee} | 2 +- libraries/redis-wrapper/{ => test/unit/src}/test.coffee | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename libraries/redis-wrapper/{health.coffee => test/scripts/standalone.coffee} (89%) rename libraries/redis-wrapper/{ => test/unit/src}/test.coffee (97%) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 2bd45e3d3c..b16bc442f2 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -6,7 +6,7 @@ "author": "ShareLaTeX", "license": "ISC", "scripts": { - "test": "mocha --require coffee-script/register test.coffee" + "test": "mocha --require coffee-script/register test/unit/src/*.coffee" }, "dependencies": { "coffee-script": "1.8.0", diff --git a/libraries/redis-wrapper/health.coffee b/libraries/redis-wrapper/test/scripts/standalone.coffee similarity index 89% rename from libraries/redis-wrapper/health.coffee rename to libraries/redis-wrapper/test/scripts/standalone.coffee index feb02a7f88..1702e06d1a 100644 --- a/libraries/redis-wrapper/health.coffee +++ b/libraries/redis-wrapper/test/scripts/standalone.coffee @@ -1,7 +1,7 @@ # execute this script with a redis container running to test the health check # starting and stopping redis with this script running is a good test -redis = require "./index.coffee" +redis = require "../../index.coffee" rclient = redis.createClient({host:"localhost",port:"6379"}) setInterval () -> diff --git a/libraries/redis-wrapper/test.coffee b/libraries/redis-wrapper/test/unit/src/test.coffee similarity index 97% rename from libraries/redis-wrapper/test.coffee rename to libraries/redis-wrapper/test/unit/src/test.coffee index e3586ee735..98af6cf255 100644 --- a/libraries/redis-wrapper/test.coffee +++ b/libraries/redis-wrapper/test/unit/src/test.coffee @@ -3,7 +3,7 @@ SandboxedModule = require('sandboxed-module') assert = require('assert') path = require('path') sinon = require('sinon') -modulePath = path.join __dirname, "./index.coffee" +modulePath = path.join __dirname, "./../../../index.coffee" expect = require("chai").expect describe "index", -> From 7eccce2ed07b7aa3f0e9b950e725a6e055f8c95d Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 16:16:11 +0000 Subject: [PATCH 57/79] [misc] reference module via js/loose file extension --- libraries/redis-wrapper/test/scripts/standalone.coffee | 2 +- libraries/redis-wrapper/test/unit/src/test.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/redis-wrapper/test/scripts/standalone.coffee b/libraries/redis-wrapper/test/scripts/standalone.coffee index 1702e06d1a..1ee02165e7 100644 --- a/libraries/redis-wrapper/test/scripts/standalone.coffee +++ b/libraries/redis-wrapper/test/scripts/standalone.coffee @@ -1,7 +1,7 @@ # execute this script with a redis container running to test the health check # starting and stopping redis with this script running is a good test -redis = require "../../index.coffee" +redis = require "../.." rclient = redis.createClient({host:"localhost",port:"6379"}) setInterval () -> diff --git a/libraries/redis-wrapper/test/unit/src/test.coffee b/libraries/redis-wrapper/test/unit/src/test.coffee index 98af6cf255..465f526a6c 100644 --- a/libraries/redis-wrapper/test/unit/src/test.coffee +++ b/libraries/redis-wrapper/test/unit/src/test.coffee @@ -3,7 +3,7 @@ SandboxedModule = require('sandboxed-module') assert = require('assert') path = require('path') sinon = require('sinon') -modulePath = path.join __dirname, "./../../../index.coffee" +modulePath = path.join __dirname, "./../../../index.js" expect = require("chai").expect describe "index", -> From 1a090b7b46b295f66e05b4adf4f8c260e3abbea7 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 16:19:05 +0000 Subject: [PATCH 58/79] [misc] add editor config, eslint, prettier boiler plate versions taken from o-error (prettier-eslint-cli from real-time) --- libraries/redis-wrapper/.editorconfig | 11 + libraries/redis-wrapper/.eslintrc.json | 23 + libraries/redis-wrapper/.prettierrc.json | 4 + libraries/redis-wrapper/package-lock.json | 2649 +++++++++++++++++++++ libraries/redis-wrapper/package.json | 16 + 5 files changed, 2703 insertions(+) create mode 100644 libraries/redis-wrapper/.editorconfig create mode 100644 libraries/redis-wrapper/.eslintrc.json create mode 100644 libraries/redis-wrapper/.prettierrc.json diff --git a/libraries/redis-wrapper/.editorconfig b/libraries/redis-wrapper/.editorconfig new file mode 100644 index 0000000000..44f520ec1c --- /dev/null +++ b/libraries/redis-wrapper/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +max_line_length = 79 +tab_width = 4 +trim_trailing_whitespace = true diff --git a/libraries/redis-wrapper/.eslintrc.json b/libraries/redis-wrapper/.eslintrc.json new file mode 100644 index 0000000000..1469158283 --- /dev/null +++ b/libraries/redis-wrapper/.eslintrc.json @@ -0,0 +1,23 @@ +{ + "extends": [ + "standard", + "plugin:prettier/recommended", + "plugin:mocha/recommended", + "plugin:chai-expect/recommended", + "plugin:chai-friendly/recommended" + ], + "env": { + "node": true + }, + "parserOptions": { + "ecmaVersion": 2018 + }, + "overrides": [ + { + "files": ["test/**/*.js"], + "env": { + "mocha": true + } + } + ] +} diff --git a/libraries/redis-wrapper/.prettierrc.json b/libraries/redis-wrapper/.prettierrc.json new file mode 100644 index 0000000000..b2095be81e --- /dev/null +++ b/libraries/redis-wrapper/.prettierrc.json @@ -0,0 +1,4 @@ +{ + "semi": false, + "singleQuote": true +} diff --git a/libraries/redis-wrapper/package-lock.json b/libraries/redis-wrapper/package-lock.json index 499cab1181..0c7414b30d 100644 --- a/libraries/redis-wrapper/package-lock.json +++ b/libraries/redis-wrapper/package-lock.json @@ -4,6 +4,32 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, "@sinonjs/commons": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", @@ -49,18 +75,162 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@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/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "@typescript-eslint/experimental-utils": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", + "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "1.13.0", + "eslint-scope": "^4.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.13.0.tgz", + "integrity": "sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "1.13.0", + "@typescript-eslint/typescript-estree": "1.13.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz", + "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==", + "dev": true, + "requires": { + "lodash.unescape": "4.0.1", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + }, + "dependencies": { + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + } + } + }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -71,12 +241,54 @@ "picomatch": "^2.0.4" } }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, + "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 + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -89,6 +301,12 @@ "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, + "boolify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/boolify/-/boolify-1.0.1.tgz", + "integrity": "sha1-tcCeF8rNET0Rt7s+04TMASmU2Gs=", + "dev": true + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -114,12 +332,39 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "call-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", + "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + } + }, "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", @@ -134,6 +379,23 @@ "type-detect": "^4.0.5" } }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -156,6 +418,21 @@ "readdirp": "~3.5.0" } }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -223,12 +500,51 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "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 + }, + "core-js": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.7.0.tgz", + "integrity": "sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA==", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -252,6 +568,21 @@ "type-detect": "^4.0.0" } }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, "denque": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", @@ -263,12 +594,504 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "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" + } + }, "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 }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "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" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "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.4.3", + "eslint-visitor-keys": "^1.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": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "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.3", + "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" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "eslint-config-prettier": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz", + "integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + }, + "eslint-config-standard": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz", + "integrity": "sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg==", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-chai-expect": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-chai-expect/-/eslint-plugin-chai-expect-2.2.0.tgz", + "integrity": "sha512-ExTJKhgeYMfY8wDj3UiZmgpMKJOUHGNHmWMlxT49JUDB1vTnw0sSNfXJSxnX+LcebyBD/gudXzjzD136WqPJrQ==", + "dev": true + }, + "eslint-plugin-chai-friendly": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-chai-friendly/-/eslint-plugin-chai-friendly-0.5.0.tgz", + "integrity": "sha512-Pxe6z8C9fP0pn2X2nGFU/b3GBOCM/5FVus1hsMwJsXP3R7RiXFl7g0ksJbsc0GxiLyidTW4mEFk77qsNn7Tk7g==", + "dev": true + }, + "eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "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" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-mocha": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-6.3.0.tgz", + "integrity": "sha512-Cd2roo8caAyG21oKaaNTj7cqeYRWW1I2B5SfpKRp0Ip1gkfwoR1Ow0IGlPWnNjzywdF4n+kHL8/9vM6zCJUxdg==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "ramda": "^0.27.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + } + } + }, + "eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "requires": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + } + } + }, + "eslint-plugin-prettier": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", + "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "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-standard": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.2.tgz", + "integrity": "sha512-nKptN8l7jksXkwFk++PhJB3cCDTcXOEyhISIN86Ue2feJ1LFyY3PrY3/xT2keXlJSY5bpmbiTG0f885/YKAvTA==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "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.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -294,6 +1117,23 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -307,6 +1147,18 @@ "dev": true, "optional": true }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -319,6 +1171,37 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-intrinsic": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", + "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, + "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" + } + }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -328,24 +1211,114 @@ "is-glob": "^4.0.1" } }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.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=", + "dev": true + } + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "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 + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "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 + }, + "import-fresh": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", + "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -362,6 +1335,89 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "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": "^6.0.0" + } + }, + "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" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "ioredis": { "version": "4.17.3", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.17.3.tgz", @@ -378,6 +1434,12 @@ "standard-as-callback": "^2.0.1" } }, + "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": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -387,6 +1449,27 @@ "binary-extensions": "^2.0.0" } }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-core-module": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", + "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -408,6 +1491,12 @@ "is-extglob": "^2.1.1" } }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -420,6 +1509,30 @@ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -432,12 +1545,71 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "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 + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, "just-extend": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", "dev": true }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "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=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -447,6 +1619,12 @@ "p-locate": "^5.0.0" } }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, "lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", @@ -463,6 +1641,24 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.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": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -502,6 +1698,108 @@ } } }, + "loglevel": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", + "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==", + "dev": true + }, + "loglevel-colored-level-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz", + "integrity": "sha1-akAhj9x64V/HbD0PPmdsRlOIYD4=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "loglevel": "^1.4.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "make-plural": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-4.3.0.tgz", + "integrity": "sha512-xTYd4JVHpSCW+aqDof6w/MebaMVNTVYBZhbB/vi513xXdiPT92JMVCo0Jq8W2UZnzYRFeVbQiQ+I25l13JuKvA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "map-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", + "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", + "dev": true + }, + "messageformat": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/messageformat/-/messageformat-2.3.0.tgz", + "integrity": "sha512-uTzvsv0lTeQxYI2y1NPa1lItL5VRI8Gb93Y2K2ue5gBPyrbJxfDi/EYWxh2PKv5yO42AJeeqblS9MJSh/IEk4w==", + "dev": true, + "requires": { + "make-plural": "^4.3.0", + "messageformat-formatters": "^2.0.1", + "messageformat-parser": "^4.1.2" + } + }, + "messageformat-formatters": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/messageformat-formatters/-/messageformat-formatters-2.0.1.tgz", + "integrity": "sha512-E/lQRXhtHwGuiQjI7qxkLp8AHbMD5r2217XNe/SREbBlSawe0lOqsFb7rflZJmlQFSULNLIqlcjjsCPlB3m3Mg==", + "dev": true + }, + "messageformat-parser": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-4.1.3.tgz", + "integrity": "sha512-2fU3XDCanRqeOCkn7R5zW5VQHWf+T3hH65SzuqRvjatBK7r4uyFa5mEX+k6F9Bd04LVM5G4/BHBTUJsOdW7uyg==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -511,6 +1809,12 @@ "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, "mkdirp": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", @@ -628,12 +1932,30 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, "nanoid": { "version": "3.1.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "nise": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", @@ -647,12 +1969,68 @@ "path-to-regexp": "^1.7.0" } }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "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 }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "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.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -662,6 +2040,35 @@ "wrappy": "1" } }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optionator": { + "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.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, "p-limit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", @@ -686,6 +2093,24 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -698,6 +2123,24 @@ "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", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, "path-to-regexp": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", @@ -707,6 +2150,15 @@ "isarray": "0.0.1" } }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", @@ -719,6 +2171,676 @@ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "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 + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prettier": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", + "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", + "dev": true + }, + "prettier-eslint": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/prettier-eslint/-/prettier-eslint-9.0.2.tgz", + "integrity": "sha512-u6EQqxUhaGfra9gy9shcR7MT7r/2twwEfRGy1tfzyaJvLQwSg34M9IU5HuF7FsLW2QUgr5VIUc56EPWibw1pdw==", + "dev": true, + "requires": { + "@typescript-eslint/parser": "^1.10.2", + "common-tags": "^1.4.0", + "core-js": "^3.1.4", + "dlv": "^1.1.0", + "eslint": "^5.0.0", + "indent-string": "^4.0.0", + "lodash.merge": "^4.6.0", + "loglevel-colored-level-prefix": "^1.0.0", + "prettier": "^1.7.0", + "pretty-format": "^23.0.1", + "require-relative": "^0.8.7", + "typescript": "^3.2.1", + "vue-eslint-parser": "^2.0.2" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "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 + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "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 + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "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" + } + } + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + } + } + }, + "prettier-eslint-cli": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/prettier-eslint-cli/-/prettier-eslint-cli-5.0.0.tgz", + "integrity": "sha512-cei9UbN1aTrz3sQs88CWpvY/10PYTevzd76zoG1tdJ164OhmNTFRKPTOZrutVvscoQWzbnLKkviS3gu5JXwvZg==", + "dev": true, + "requires": { + "arrify": "^2.0.1", + "boolify": "^1.0.0", + "camelcase-keys": "^6.0.0", + "chalk": "^2.4.2", + "common-tags": "^1.8.0", + "core-js": "^3.1.4", + "eslint": "^5.0.0", + "find-up": "^4.1.0", + "get-stdin": "^7.0.0", + "glob": "^7.1.4", + "ignore": "^5.1.2", + "lodash.memoize": "^4.1.2", + "loglevel-colored-level-prefix": "^1.0.0", + "messageformat": "^2.2.1", + "prettier-eslint": "^9.0.0", + "rxjs": "^6.5.2", + "yargs": "^13.2.4" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "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 + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "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 + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "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 + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "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" + } + } + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + } + } + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-format": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", + "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "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 + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true + }, + "ramda": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz", + "integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -728,6 +2850,78 @@ "safe-buffer": "^5.1.0" } }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "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 + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, "readdirp": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", @@ -755,6 +2949,12 @@ "redis-errors": "^1.0.0" } }, + "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 + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -773,12 +2973,74 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "require-relative": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", + "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", + "dev": true + }, + "resolve": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", + "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", + "dev": true, + "requires": { + "is-core-module": "^2.0.0", + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "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" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "sandboxed-module": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-2.0.4.tgz", @@ -789,6 +3051,12 @@ "stack-trace": "0.0.9" } }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, "serialize-javascript": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", @@ -804,6 +3072,27 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, "sinon": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.1.tgz", @@ -830,6 +3119,49 @@ } } }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "dev": true + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -874,12 +3206,162 @@ } } }, + "string.prototype.trimend": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", + "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "string.prototype.trimstart": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", + "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "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" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "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" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + } + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -889,17 +3371,158 @@ "is-number": "^7.0.0" } }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "typescript": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "dev": true + }, "underscore": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vue-eslint-parser": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz", + "integrity": "sha512-ZezcU71Owm84xVF6gfurBQUGg8WQ+WZGxgDEQu1IHFBZNx7BFZg3L1yHxrCBNNwbwFtE1GuvfJKMtb6Xuwc/Bw==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.2", + "esquery": "^1.0.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "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" + } + }, + "eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", @@ -915,6 +3538,12 @@ "string-width": "^1.0.2 || 2" } }, + "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 + }, "workerpool": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", @@ -990,6 +3619,26 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index b16bc442f2..33889a862d 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -6,6 +6,9 @@ "author": "ShareLaTeX", "license": "ISC", "scripts": { + "lint": "eslint --max-warnings 0 .", + "format": "prettier-eslint $PWD'/**/*.js' --list-different", + "format:fix": "prettier-eslint $PWD'/**/*.js' --write", "test": "mocha --require coffee-script/register test/unit/src/*.coffee" }, "dependencies": { @@ -15,7 +18,20 @@ }, "devDependencies": { "chai": "^4.2.0", + "eslint": "^6.8.0", + "eslint-config-prettier": "^6.10.1", + "eslint-config-standard": "^14.1.1", + "eslint-plugin-chai-expect": "^2.1.0", + "eslint-plugin-chai-friendly": "^0.5.0", + "eslint-plugin-import": "^2.20.2", + "eslint-plugin-mocha": "^6.3.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^3.1.3", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-standard": "^4.0.1", "mocha": "^8.2.1", + "prettier": "^2.0.2", + "prettier-eslint-cli": "^5.0.0", "sandboxed-module": "^2.0.4", "sinon": "^9.2.1" } From 0a2171e9f0c3467723197a987768cbdcdd4c742d Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 16:17:18 +0000 Subject: [PATCH 59/79] [misc] decaffeinate tests: rename --- .../test/scripts/{standalone.coffee => standalone.js} | 0 libraries/redis-wrapper/test/unit/src/{test.coffee => test.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename libraries/redis-wrapper/test/scripts/{standalone.coffee => standalone.js} (100%) rename libraries/redis-wrapper/test/unit/src/{test.coffee => test.js} (100%) diff --git a/libraries/redis-wrapper/test/scripts/standalone.coffee b/libraries/redis-wrapper/test/scripts/standalone.js similarity index 100% rename from libraries/redis-wrapper/test/scripts/standalone.coffee rename to libraries/redis-wrapper/test/scripts/standalone.js diff --git a/libraries/redis-wrapper/test/unit/src/test.coffee b/libraries/redis-wrapper/test/unit/src/test.js similarity index 100% rename from libraries/redis-wrapper/test/unit/src/test.coffee rename to libraries/redis-wrapper/test/unit/src/test.js From 7210b3dfedd081f505ff3ae58a098bc23edda45c Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 16:21:05 +0000 Subject: [PATCH 60/79] [misc] decaffeinate tests: decaffeinate standalone script --- .../redis-wrapper/test/scripts/standalone.js | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/libraries/redis-wrapper/test/scripts/standalone.js b/libraries/redis-wrapper/test/scripts/standalone.js index 1ee02165e7..8e85c90888 100644 --- a/libraries/redis-wrapper/test/scripts/standalone.js +++ b/libraries/redis-wrapper/test/scripts/standalone.js @@ -1,13 +1,16 @@ -# execute this script with a redis container running to test the health check -# starting and stopping redis with this script running is a good test +// execute this script with a redis container running to test the health check +// starting and stopping redis with this script running is a good test -redis = require "../.." +const redis = require('../../') -rclient = redis.createClient({host:"localhost",port:"6379"}) -setInterval () -> - rclient.healthCheck (err) -> - if err? - console.log "HEALTH CHECK FAILED", err - else - console.log "HEALTH CHECK OK" -, 1000 \ No newline at end of file +const rclient = redis.createClient({ host: 'localhost', port: '6379' }) + +setInterval(() => { + rclient.healthCheck((err) => { + if (err) { + console.log('HEALTH CHECK FAILED', err) + } else { + console.log('HEALTH CHECK OK') + } + }) +}, 1000) From 7b69cc42c9ccc89e55c41e9a03d6668faec8c049 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 16:42:41 +0000 Subject: [PATCH 61/79] [misc] decaffeinate tests: decaffeinate unit tests --- libraries/redis-wrapper/package.json | 2 +- libraries/redis-wrapper/test/unit/src/test.js | 207 +++++++++++------- 2 files changed, 134 insertions(+), 75 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 33889a862d..e0990a924a 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -9,7 +9,7 @@ "lint": "eslint --max-warnings 0 .", "format": "prettier-eslint $PWD'/**/*.js' --list-different", "format:fix": "prettier-eslint $PWD'/**/*.js' --write", - "test": "mocha --require coffee-script/register test/unit/src/*.coffee" + "test": "mocha --recursive test/unit/src/" }, "dependencies": { "coffee-script": "1.8.0", diff --git a/libraries/redis-wrapper/test/unit/src/test.js b/libraries/redis-wrapper/test/unit/src/test.js index 465f526a6c..23cea9adb5 100644 --- a/libraries/redis-wrapper/test/unit/src/test.js +++ b/libraries/redis-wrapper/test/unit/src/test.js @@ -1,88 +1,147 @@ -should = require('chai').should() -SandboxedModule = require('sandboxed-module') -assert = require('assert') -path = require('path') -sinon = require('sinon') -modulePath = path.join __dirname, "./../../../index.js" -expect = require("chai").expect +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS206: Consider reworking classes to avoid initClass + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const should = require('chai').should() +const SandboxedModule = require('sandboxed-module') +const assert = require('assert') +const path = require('path') +const sinon = require('sinon') +const modulePath = path.join(__dirname, './../../../index.js') +const { expect } = require('chai') -describe "index", -> +describe('index', function () { + beforeEach(function () { + let Cluster, IoRedis, ioredisConstructor + this.settings = {} + this.ioredisConstructor = ioredisConstructor = sinon.stub() - beforeEach -> + this.ioredis = IoRedis = (function () { + let createIoRedis + IoRedis = class IoRedis { + static initClass() { + this.prototype.on = sinon.stub() + createIoRedis = ioredisConstructor + } - @settings = {} - @ioredisConstructor = ioredisConstructor = sinon.stub() + constructor() { + return createIoRedis.apply(this, arguments) + } + } + IoRedis.initClass() + return IoRedis + })() + this.ioredis.Cluster = Cluster = (function () { + Cluster = class Cluster { + static initClass() { + this.prototype.on = sinon.stub() + } - @ioredis = class IoRedis - constructor: ioredisConstructor - on: sinon.stub() - @ioredis.Cluster = class Cluster - constructor: (@config, @options) -> - on: sinon.stub() - @redis = SandboxedModule.require modulePath, requires: - "ioredis": @ioredis - @auth_pass = "1234 pass" + constructor(config, options) { + this.config = config + this.options = options + } + } + Cluster.initClass() + return Cluster + })() + this.redis = SandboxedModule.require(modulePath, { + requires: { + ioredis: this.ioredis, + }, + }) + return (this.auth_pass = '1234 pass') + }) - describe "single node redis", -> - beforeEach -> - @standardOpts = - auth_pass: @auth_pass - port: 1234 - host: "redis.mysite.env" + describe('single node redis', function () { + beforeEach(function () { + return (this.standardOpts = { + auth_pass: this.auth_pass, + port: 1234, + host: 'redis.mysite.env', + }) + }) - it "should use the ioredis driver in single-instance mode if a non array is passed", -> - client = @redis.createClient @standardOpts - assert.equal(client.constructor, @ioredis) + it('should use the ioredis driver in single-instance mode if a non array is passed', function () { + const client = this.redis.createClient(this.standardOpts) + return assert.equal(client.constructor, this.ioredis) + }) - it "should call createClient for the ioredis driver in single-instance mode if a non array is passed", -> - client = @redis.createClient @standardOpts - @ioredisConstructor.calledWith(@standardOpts).should.equal true + return it('should call createClient for the ioredis driver in single-instance mode if a non array is passed', function () { + const client = this.redis.createClient(this.standardOpts) + return this.ioredisConstructor + .calledWith(this.standardOpts) + .should.equal(true) + }) + }) - describe "cluster", -> - beforeEach -> - @cluster = [{"mock": "cluster"}, { "mock": "cluster2"}] - @extraOptions = {keepAlive:100} - @settings = - cluster: @cluster - redisOptions: @extraOptions - key_schema: {foo: (x) -> "#{x}"} + describe('cluster', function () { + beforeEach(function () { + this.cluster = [{ mock: 'cluster' }, { mock: 'cluster2' }] + this.extraOptions = { keepAlive: 100 } + return (this.settings = { + cluster: this.cluster, + redisOptions: this.extraOptions, + key_schema: { + foo(x) { + return `${x}` + }, + }, + }) + }) - it "should pass the options correctly though with no options", -> - client = @redis.createClient cluster: @cluster - assert(client instanceof @ioredis.Cluster) - client.config.should.deep.equal @cluster + it('should pass the options correctly though with no options', function () { + const client = this.redis.createClient({ cluster: this.cluster }) + assert(client instanceof this.ioredis.Cluster) + return client.config.should.deep.equal(this.cluster) + }) - it "should not pass the key_schema through to the driver", -> - client = @redis.createClient cluster: @cluster, key_schema: "foobar" - assert(client instanceof @ioredis.Cluster) - client.config.should.deep.equal @cluster - expect(client.options).to.deep.equal {retry_max_delay: 5000} + it('should not pass the key_schema through to the driver', function () { + const client = this.redis.createClient({ + cluster: this.cluster, + key_schema: 'foobar', + }) + assert(client instanceof this.ioredis.Cluster) + client.config.should.deep.equal(this.cluster) + return expect(client.options).to.deep.equal({ retry_max_delay: 5000 }) + }) - it "should pass the options correctly though with additional options", -> - client = @redis.createClient @settings - assert(client instanceof @ioredis.Cluster) - client.config.should.deep.equal @cluster - # need to use expect here because of _.clone in sandbox - expect(client.options).to.deep.equal {redisOptions: @extraOptions, retry_max_delay: 5000} + return it('should pass the options correctly though with additional options', function () { + const client = this.redis.createClient(this.settings) + assert(client instanceof this.ioredis.Cluster) + client.config.should.deep.equal(this.cluster) + // need to use expect here because of _.clone in sandbox + return expect(client.options).to.deep.equal({ + redisOptions: this.extraOptions, + retry_max_delay: 5000, + }) + }) + }) - describe "monkey patch ioredis exec", -> - beforeEach -> - @callback = sinon.stub() - @results = [] - @multiOrig = { exec: sinon.stub().yields(null, @results)} - @client = { multi: sinon.stub().returns(@multiOrig) } - @redis._monkeyPatchIoredisExec(@client) - @multi = @client.multi() + return describe('monkey patch ioredis exec', function () { + beforeEach(function () { + this.callback = sinon.stub() + this.results = [] + this.multiOrig = { exec: sinon.stub().yields(null, this.results) } + this.client = { multi: sinon.stub().returns(this.multiOrig) } + this.redis._monkeyPatchIoredisExec(this.client) + return (this.multi = this.client.multi()) + }) - it "should return the old redis format for an array", -> - @results[0] = [null, 42] - @results[1] = [null, "foo"] - @multi.exec @callback - @callback.calledWith(null, [42, "foo"]).should.equal true - - it "should return the old redis format when there is an error", -> - @results[0] = [null, 42] - @results[1] = ["error", "foo"] - @multi.exec @callback - @callback.calledWith("error").should.equal true + it('should return the old redis format for an array', function () { + this.results[0] = [null, 42] + this.results[1] = [null, 'foo'] + this.multi.exec(this.callback) + return this.callback.calledWith(null, [42, 'foo']).should.equal(true) + }) + return it('should return the old redis format when there is an error', function () { + this.results[0] = [null, 42] + this.results[1] = ['error', 'foo'] + this.multi.exec(this.callback) + return this.callback.calledWith('error').should.equal(true) + }) + }) +}) From 830d6275b3965a7a5416a0dadac6f1d2e8fa97bc Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 17:04:51 +0000 Subject: [PATCH 62/79] [misc] add scripts for testing redis cluster --- .../test/scripts/cluster/clear-dbs.sh | 4 + .../test/scripts/cluster/cluster.js | 25 +++++++ .../test/scripts/cluster/create-cluster.sh | 73 +++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100755 libraries/redis-wrapper/test/scripts/cluster/clear-dbs.sh create mode 100644 libraries/redis-wrapper/test/scripts/cluster/cluster.js create mode 100755 libraries/redis-wrapper/test/scripts/cluster/create-cluster.sh diff --git a/libraries/redis-wrapper/test/scripts/cluster/clear-dbs.sh b/libraries/redis-wrapper/test/scripts/cluster/clear-dbs.sh new file mode 100755 index 0000000000..650630bb42 --- /dev/null +++ b/libraries/redis-wrapper/test/scripts/cluster/clear-dbs.sh @@ -0,0 +1,4 @@ +while true; do + seq 0 8 \ + | xargs -I% redis-cli -p 700% FLUSHALL > /dev/null +done diff --git a/libraries/redis-wrapper/test/scripts/cluster/cluster.js b/libraries/redis-wrapper/test/scripts/cluster/cluster.js new file mode 100644 index 0000000000..54dedb1385 --- /dev/null +++ b/libraries/redis-wrapper/test/scripts/cluster/cluster.js @@ -0,0 +1,25 @@ +/* + execute this script with a redis cluster running to test the health check. + starting and stopping shards with this script running is a good test. + + to create a new cluster, use $ ./create-redis-cluster.sh + to run a chaos monkey, use $ ./clear-dbs.sh +*/ + +const redis = require('../../../') + +const rclient = redis.createClient({ + cluster: Array.from({ length: 9 }).map((value, index) => { + return { host: '127.0.0.1', port: 7000 + index } + }), +}) + +setInterval(() => { + rclient.healthCheck((err) => { + if (err) { + console.log('HEALTH CHECK FAILED', err) + } else { + console.log('HEALTH CHECK OK') + } + }) +}, 1000) diff --git a/libraries/redis-wrapper/test/scripts/cluster/create-cluster.sh b/libraries/redis-wrapper/test/scripts/cluster/create-cluster.sh new file mode 100755 index 0000000000..dd384a2d92 --- /dev/null +++ b/libraries/redis-wrapper/test/scripts/cluster/create-cluster.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# USAGE: $0 [NUMBER_OF_NODES, default: 9] [DATA_DIR, default: a new temp dir] +# +# ports are assigned from 7000 on +# +# NOTE: the cluster setup requires redis 5+ + +set -ex + +COUNT=${1:-9} +DATA=$2 + +if [[ -z "$DATA" ]]; then + IS_TEMP=1 + TEMP=`mktemp -d` + DATA="$TEMP" +fi + +HAS_DATA= +if [[ -e "$DATA/7000/node.conf" ]]; then + HAS_DATA=1 +fi + +PIDs="" + +cleanup() { + # ensure that we delete the temp dir, no matter how the kill cmd exists + set +e + # invoke kill with at least one PID + echo "$PIDs" | xargs -r kill + if [[ ! -z "$IS_TEMP" ]]; then + rm -rf "$TEMP" + fi +} +trap cleanup exit + +for NUM in `seq "$COUNT"`; do + PORT=`expr 6999 + "$NUM"` + CWD="$DATA/$PORT" + mkdir -p "$CWD" + pushd "$CWD" + redis-server \ + --appendonly no \ + --cluster-enabled yes \ + --cluster-config-file node.conf \ + --port "$PORT" \ + --save "" \ + > /dev/null \ + & + PIDs="$PIDs $!" + popd +done + +# initial nodes +if [[ -z "$HAS_DATA" ]]; then + # confirm the setup + echo yes \ + | redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 +fi + +# scale up as requested +for NUM in `seq 4 "$COUNT"`; do + PORT=`expr 6999 + "$NUM"` + GUARD="$DATA/$PORT/.joined" + if [[ ! -e "$GUARD" ]]; then + redis-cli --cluster add-node "127.0.0.1:$PORT" 127.0.0.1:7000 --cluster-slave + touch "$GUARD" + fi +done + +echo "CLUSTER IS READY" >&2 +wait From 45bf2abb141dc60790b76aeb7f035f66d973c3b0 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 17:06:41 +0000 Subject: [PATCH 63/79] [misc] decaffeinate: rename 1/2 --- libraries/redis-wrapper/index.js | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 libraries/redis-wrapper/index.js diff --git a/libraries/redis-wrapper/index.js b/libraries/redis-wrapper/index.js deleted file mode 100644 index d812c63570..0000000000 --- a/libraries/redis-wrapper/index.js +++ /dev/null @@ -1,2 +0,0 @@ -require("coffee-script").register(); -module.exports = require("./index.coffee"); From c973c5b1889a52b6872bd91bbe34a1a57b8275c4 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 17:07:00 +0000 Subject: [PATCH 64/79] [misc] decaffeinate: rename 2/2 --- libraries/redis-wrapper/{index.coffee => index.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename libraries/redis-wrapper/{index.coffee => index.js} (100%) diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.js similarity index 100% rename from libraries/redis-wrapper/index.coffee rename to libraries/redis-wrapper/index.js From da8bef821ba11791475d01dc9dc1fc97a1edd4f6 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 17:12:51 +0000 Subject: [PATCH 65/79] [misc] decaffeinate: decaffeinate module --- libraries/redis-wrapper/index.js | 241 +++++++++++++++++++------------ 1 file changed, 146 insertions(+), 95 deletions(-) diff --git a/libraries/redis-wrapper/index.js b/libraries/redis-wrapper/index.js index da606655be..8fcb52a978 100644 --- a/libraries/redis-wrapper/index.js +++ b/libraries/redis-wrapper/index.js @@ -1,99 +1,150 @@ -_ = require("underscore") -os = require('os') -crypto = require('crypto') +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS103: Rewrite code to no longer use __guard__, or convert again using --optional-chaining + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +let RedisSharelatex +const _ = require('underscore') +const os = require('os') +const crypto = require('crypto') -# generate unique values for health check -HOST = os.hostname() -PID = process.pid -RND = crypto.randomBytes(4).toString('hex') -COUNT = 0 +// generate unique values for health check +const HOST = os.hostname() +const PID = process.pid +const RND = crypto.randomBytes(4).toString('hex') +let COUNT = 0 -module.exports = RedisSharelatex = - createClient: (opts = {port: 6379, host: "localhost"})-> - if !opts.retry_max_delay? - opts.retry_max_delay = 5000 # ms - - if opts.cluster? - Redis = require("ioredis") - standardOpts = _.clone(opts) - delete standardOpts.cluster - delete standardOpts.key_schema - client = new Redis.Cluster(opts.cluster, standardOpts) - client.healthCheck = RedisSharelatex.clusterHealthCheckBuilder(client) - RedisSharelatex._monkeyPatchIoredisExec(client) - else - standardOpts = _.clone(opts) - ioredis = require("ioredis") - client = new ioredis(standardOpts) - RedisSharelatex._monkeyPatchIoredisExec(client) - client.healthCheck = RedisSharelatex.singleInstanceHealthCheckBuilder(client) - return client - - HEARTBEAT_TIMEOUT: 2000 - singleInstanceHealthCheckBuilder: (client) -> - healthCheck = (callback) -> - RedisSharelatex._checkClient(client, callback) - return healthCheck - - clusterHealthCheckBuilder: (client) -> - return RedisSharelatex.singleInstanceHealthCheckBuilder(client) - - _checkClient: (client, callback) -> - callback = _.once(callback) - # check the redis connection by storing and retrieving a unique key/value pair - uniqueToken = "host=#{HOST}:pid=#{PID}:random=#{RND}:time=#{Date.now()}:count=#{COUNT++}" - timer = setTimeout () -> - error = new Error("redis client health check timed out #{client?.options?.host}") - console.error { - err: error, - key: client.options?.key # only present for cluster - clientOptions: client.options - uniqueToken: uniqueToken - }, "client timed out" - callback(error) - , RedisSharelatex.HEARTBEAT_TIMEOUT - healthCheckKey = "_redis-wrapper:healthCheckKey:{#{uniqueToken}}" - healthCheckValue = "_redis-wrapper:healthCheckValue:{#{uniqueToken}}" - # set the unique key/value pair - multi = client.multi() - multi.set healthCheckKey, healthCheckValue, "EX", 60 - multi.exec (err, reply) -> - if err? - clearTimeout timer - return callback(err) - # check that we can retrieve the unique key/value pair - multi = client.multi() - multi.get healthCheckKey - multi.del healthCheckKey - multi.exec (err, reply) -> - clearTimeout timer - return callback(err) if err? - return callback(new Error("bad response from redis health check")) if reply?[0] isnt healthCheckValue or reply?[1] isnt 1 - return callback() +module.exports = RedisSharelatex = { + createClient(opts) { + let client, standardOpts + if (opts == null) { + opts = { port: 6379, host: 'localhost' } + } + if (opts.retry_max_delay == null) { + opts.retry_max_delay = 5000 // ms + } - _monkeyPatchIoredisExec: (client) -> - _multi = client.multi - client.multi = (args...) -> - multi = _multi.call(client, args...) - _exec = multi.exec - multi.exec = (callback = () ->) -> - _exec.call multi, (error, result) -> - # ioredis exec returns an results like: - # [ [null, 42], [null, "foo"] ] - # where the first entries in each 2-tuple are - # presumably errors for each individual command, - # and the second entry is the result. We need to transform - # this into the same result as the old redis driver: - # [ 42, "foo" ] - filtered_result = [] - for entry in result or [] - if entry[0]? - return callback(entry[0]) - else - filtered_result.push entry[1] - callback error, filtered_result - return multi - - - + if (opts.cluster != null) { + const Redis = require('ioredis') + standardOpts = _.clone(opts) + delete standardOpts.cluster + delete standardOpts.key_schema + client = new Redis.Cluster(opts.cluster, standardOpts) + client.healthCheck = RedisSharelatex.clusterHealthCheckBuilder(client) + RedisSharelatex._monkeyPatchIoredisExec(client) + } else { + standardOpts = _.clone(opts) + const ioredis = require('ioredis') + client = new ioredis(standardOpts) + RedisSharelatex._monkeyPatchIoredisExec(client) + client.healthCheck = RedisSharelatex.singleInstanceHealthCheckBuilder( + client + ) + } + return client + }, + HEARTBEAT_TIMEOUT: 2000, + singleInstanceHealthCheckBuilder(client) { + const healthCheck = (callback) => + RedisSharelatex._checkClient(client, callback) + return healthCheck + }, + + clusterHealthCheckBuilder(client) { + return RedisSharelatex.singleInstanceHealthCheckBuilder(client) + }, + + _checkClient(client, callback) { + callback = _.once(callback) + // check the redis connection by storing and retrieving a unique key/value pair + const uniqueToken = `host=${HOST}:pid=${PID}:random=${RND}:time=${Date.now()}:count=${COUNT++}` + const timer = setTimeout(function () { + const error = new Error( + `redis client health check timed out ${__guard__( + client != null ? client.options : undefined, + (x) => x.host + )}` + ) + console.error( + { + err: error, + key: client.options != null ? client.options.key : undefined, // only present for cluster + clientOptions: client.options, + uniqueToken, + }, + 'client timed out' + ) + return callback(error) + }, RedisSharelatex.HEARTBEAT_TIMEOUT) + const healthCheckKey = `_redis-wrapper:healthCheckKey:{${uniqueToken}}` + const healthCheckValue = `_redis-wrapper:healthCheckValue:{${uniqueToken}}` + // set the unique key/value pair + let multi = client.multi() + multi.set(healthCheckKey, healthCheckValue, 'EX', 60) + return multi.exec(function (err, reply) { + if (err != null) { + clearTimeout(timer) + return callback(err) + } + // check that we can retrieve the unique key/value pair + multi = client.multi() + multi.get(healthCheckKey) + multi.del(healthCheckKey) + return multi.exec(function (err, reply) { + clearTimeout(timer) + if (err != null) { + return callback(err) + } + if ( + (reply != null ? reply[0] : undefined) !== healthCheckValue || + (reply != null ? reply[1] : undefined) !== 1 + ) { + return callback(new Error('bad response from redis health check')) + } + return callback() + }) + }) + }, + + _monkeyPatchIoredisExec(client) { + const _multi = client.multi + return (client.multi = function (...args) { + const multi = _multi.call(client, ...Array.from(args)) + const _exec = multi.exec + multi.exec = function (callback) { + if (callback == null) { + callback = function () {} + } + return _exec.call(multi, function (error, result) { + // ioredis exec returns an results like: + // [ [null, 42], [null, "foo"] ] + // where the first entries in each 2-tuple are + // presumably errors for each individual command, + // and the second entry is the result. We need to transform + // this into the same result as the old redis driver: + // [ 42, "foo" ] + const filtered_result = [] + for (const entry of Array.from(result || [])) { + if (entry[0] != null) { + return callback(entry[0]) + } else { + filtered_result.push(entry[1]) + } + } + return callback(error, filtered_result) + }) + } + return multi + }) + }, +} + +function __guard__(value, transform) { + return typeof value !== 'undefined' && value !== null + ? transform(value) + : undefined +} From 4aebc1b0b6fb6451a863036f9132fa63ba5afaf3 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 17:15:36 +0000 Subject: [PATCH 66/79] [misc] rewrite: free functions --- libraries/redis-wrapper/index.js | 234 +++++++++--------- libraries/redis-wrapper/test/unit/src/test.js | 3 +- 2 files changed, 118 insertions(+), 119 deletions(-) diff --git a/libraries/redis-wrapper/index.js b/libraries/redis-wrapper/index.js index 8fcb52a978..80be830845 100644 --- a/libraries/redis-wrapper/index.js +++ b/libraries/redis-wrapper/index.js @@ -6,7 +6,6 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -let RedisSharelatex const _ = require('underscore') const os = require('os') const crypto = require('crypto') @@ -17,130 +16,125 @@ const PID = process.pid const RND = crypto.randomBytes(4).toString('hex') let COUNT = 0 -module.exports = RedisSharelatex = { - createClient(opts) { - let client, standardOpts - if (opts == null) { - opts = { port: 6379, host: 'localhost' } +function createClient(opts) { + let client, standardOpts + if (opts == null) { + opts = { port: 6379, host: 'localhost' } + } + if (opts.retry_max_delay == null) { + opts.retry_max_delay = 5000 // ms + } + + if (opts.cluster != null) { + const Redis = require('ioredis') + standardOpts = _.clone(opts) + delete standardOpts.cluster + delete standardOpts.key_schema + client = new Redis.Cluster(opts.cluster, standardOpts) + client.healthCheck = clusterHealthCheckBuilder(client) + _monkeyPatchIoredisExec(client) + } else { + standardOpts = _.clone(opts) + const ioredis = require('ioredis') + client = new ioredis(standardOpts) + _monkeyPatchIoredisExec(client) + client.healthCheck = singleInstanceHealthCheckBuilder(client) + } + return client +} + +const HEARTBEAT_TIMEOUT = 2000 +function singleInstanceHealthCheckBuilder(client) { + const healthCheck = (callback) => _checkClient(client, callback) + return healthCheck +} + +function clusterHealthCheckBuilder(client) { + return singleInstanceHealthCheckBuilder(client) +} + +function _checkClient(client, callback) { + callback = _.once(callback) + // check the redis connection by storing and retrieving a unique key/value pair + const uniqueToken = `host=${HOST}:pid=${PID}:random=${RND}:time=${Date.now()}:count=${COUNT++}` + const timer = setTimeout(function () { + const error = new Error( + `redis client health check timed out ${__guard__( + client != null ? client.options : undefined, + (x) => x.host + )}` + ) + console.error( + { + err: error, + key: client.options != null ? client.options.key : undefined, // only present for cluster + clientOptions: client.options, + uniqueToken, + }, + 'client timed out' + ) + return callback(error) + }, HEARTBEAT_TIMEOUT) + const healthCheckKey = `_redis-wrapper:healthCheckKey:{${uniqueToken}}` + const healthCheckValue = `_redis-wrapper:healthCheckValue:{${uniqueToken}}` + // set the unique key/value pair + let multi = client.multi() + multi.set(healthCheckKey, healthCheckValue, 'EX', 60) + return multi.exec(function (err, reply) { + if (err != null) { + clearTimeout(timer) + return callback(err) } - if (opts.retry_max_delay == null) { - opts.retry_max_delay = 5000 // ms - } - - if (opts.cluster != null) { - const Redis = require('ioredis') - standardOpts = _.clone(opts) - delete standardOpts.cluster - delete standardOpts.key_schema - client = new Redis.Cluster(opts.cluster, standardOpts) - client.healthCheck = RedisSharelatex.clusterHealthCheckBuilder(client) - RedisSharelatex._monkeyPatchIoredisExec(client) - } else { - standardOpts = _.clone(opts) - const ioredis = require('ioredis') - client = new ioredis(standardOpts) - RedisSharelatex._monkeyPatchIoredisExec(client) - client.healthCheck = RedisSharelatex.singleInstanceHealthCheckBuilder( - client - ) - } - return client - }, - - HEARTBEAT_TIMEOUT: 2000, - singleInstanceHealthCheckBuilder(client) { - const healthCheck = (callback) => - RedisSharelatex._checkClient(client, callback) - return healthCheck - }, - - clusterHealthCheckBuilder(client) { - return RedisSharelatex.singleInstanceHealthCheckBuilder(client) - }, - - _checkClient(client, callback) { - callback = _.once(callback) - // check the redis connection by storing and retrieving a unique key/value pair - const uniqueToken = `host=${HOST}:pid=${PID}:random=${RND}:time=${Date.now()}:count=${COUNT++}` - const timer = setTimeout(function () { - const error = new Error( - `redis client health check timed out ${__guard__( - client != null ? client.options : undefined, - (x) => x.host - )}` - ) - console.error( - { - err: error, - key: client.options != null ? client.options.key : undefined, // only present for cluster - clientOptions: client.options, - uniqueToken, - }, - 'client timed out' - ) - return callback(error) - }, RedisSharelatex.HEARTBEAT_TIMEOUT) - const healthCheckKey = `_redis-wrapper:healthCheckKey:{${uniqueToken}}` - const healthCheckValue = `_redis-wrapper:healthCheckValue:{${uniqueToken}}` - // set the unique key/value pair - let multi = client.multi() - multi.set(healthCheckKey, healthCheckValue, 'EX', 60) + // check that we can retrieve the unique key/value pair + multi = client.multi() + multi.get(healthCheckKey) + multi.del(healthCheckKey) return multi.exec(function (err, reply) { + clearTimeout(timer) if (err != null) { - clearTimeout(timer) return callback(err) } - // check that we can retrieve the unique key/value pair - multi = client.multi() - multi.get(healthCheckKey) - multi.del(healthCheckKey) - return multi.exec(function (err, reply) { - clearTimeout(timer) - if (err != null) { - return callback(err) - } - if ( - (reply != null ? reply[0] : undefined) !== healthCheckValue || - (reply != null ? reply[1] : undefined) !== 1 - ) { - return callback(new Error('bad response from redis health check')) - } - return callback() - }) - }) - }, - - _monkeyPatchIoredisExec(client) { - const _multi = client.multi - return (client.multi = function (...args) { - const multi = _multi.call(client, ...Array.from(args)) - const _exec = multi.exec - multi.exec = function (callback) { - if (callback == null) { - callback = function () {} - } - return _exec.call(multi, function (error, result) { - // ioredis exec returns an results like: - // [ [null, 42], [null, "foo"] ] - // where the first entries in each 2-tuple are - // presumably errors for each individual command, - // and the second entry is the result. We need to transform - // this into the same result as the old redis driver: - // [ 42, "foo" ] - const filtered_result = [] - for (const entry of Array.from(result || [])) { - if (entry[0] != null) { - return callback(entry[0]) - } else { - filtered_result.push(entry[1]) - } - } - return callback(error, filtered_result) - }) + if ( + (reply != null ? reply[0] : undefined) !== healthCheckValue || + (reply != null ? reply[1] : undefined) !== 1 + ) { + return callback(new Error('bad response from redis health check')) } - return multi + return callback() }) - }, + }) +} + +function _monkeyPatchIoredisExec(client) { + const _multi = client.multi + return (client.multi = function (...args) { + const multi = _multi.call(client, ...Array.from(args)) + const _exec = multi.exec + multi.exec = function (callback) { + if (callback == null) { + callback = function () {} + } + return _exec.call(multi, function (error, result) { + // ioredis exec returns an results like: + // [ [null, 42], [null, "foo"] ] + // where the first entries in each 2-tuple are + // presumably errors for each individual command, + // and the second entry is the result. We need to transform + // this into the same result as the old redis driver: + // [ 42, "foo" ] + const filtered_result = [] + for (const entry of Array.from(result || [])) { + if (entry[0] != null) { + return callback(entry[0]) + } else { + filtered_result.push(entry[1]) + } + } + return callback(error, filtered_result) + }) + } + return multi + }) } function __guard__(value, transform) { @@ -148,3 +142,7 @@ function __guard__(value, transform) { ? transform(value) : undefined } + +module.exports = { + createClient, +} diff --git a/libraries/redis-wrapper/test/unit/src/test.js b/libraries/redis-wrapper/test/unit/src/test.js index 23cea9adb5..fee144c990 100644 --- a/libraries/redis-wrapper/test/unit/src/test.js +++ b/libraries/redis-wrapper/test/unit/src/test.js @@ -126,7 +126,8 @@ describe('index', function () { this.results = [] this.multiOrig = { exec: sinon.stub().yields(null, this.results) } this.client = { multi: sinon.stub().returns(this.multiOrig) } - this.redis._monkeyPatchIoredisExec(this.client) + this.ioredisConstructor.returns(this.client) + this.redis.createClient(this.client) return (this.multi = this.client.multi()) }) From d827b521c6f32388ff7026ab3fa2b2a998203e8c Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 17:40:25 +0000 Subject: [PATCH 67/79] [misc] test/unit: loosely match the passed redis options The rewrite will pass a cloned object through. --- libraries/redis-wrapper/test/unit/src/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/test/unit/src/test.js b/libraries/redis-wrapper/test/unit/src/test.js index fee144c990..af1c3db190 100644 --- a/libraries/redis-wrapper/test/unit/src/test.js +++ b/libraries/redis-wrapper/test/unit/src/test.js @@ -72,7 +72,7 @@ describe('index', function () { return it('should call createClient for the ioredis driver in single-instance mode if a non array is passed', function () { const client = this.redis.createClient(this.standardOpts) return this.ioredisConstructor - .calledWith(this.standardOpts) + .calledWith(sinon.match(this.standardOpts)) .should.equal(true) }) }) From ccf4bb1e0ea083c209fe4f33a3694ab4cc8255d9 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Tue, 10 Nov 2020 09:40:38 +0000 Subject: [PATCH 68/79] [misc] test/scripts: use logger-sharelatex for logging as in production --- libraries/redis-wrapper/package-lock.json | 1116 +++++++++++++++++ libraries/redis-wrapper/package.json | 1 + .../test/scripts/cluster/cluster.js | 5 +- .../redis-wrapper/test/scripts/standalone.js | 5 +- 4 files changed, 1123 insertions(+), 4 deletions(-) diff --git a/libraries/redis-wrapper/package-lock.json b/libraries/redis-wrapper/package-lock.json index 0c7414b30d..f46c613bab 100644 --- a/libraries/redis-wrapper/package-lock.json +++ b/libraries/redis-wrapper/package-lock.json @@ -30,6 +30,358 @@ "js-tokens": "^4.0.0" } }, + "@google-cloud/common": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-3.4.1.tgz", + "integrity": "sha512-e5z0CwsM0RXky+PnyPtQ3QK46ksqm+kE7kX8pm8X+ddBwZJipHchKeazMM5fLlGCS+AALalzXb+uYmH72TRnpQ==", + "dev": true, + "requires": { + "@google-cloud/projectify": "^2.0.0", + "@google-cloud/promisify": "^2.0.0", + "arrify": "^2.0.1", + "duplexify": "^4.1.1", + "ent": "^2.2.0", + "extend": "^3.0.2", + "google-auth-library": "^6.1.1", + "retry-request": "^4.1.1", + "teeny-request": "^7.0.0" + } + }, + "@google-cloud/logging": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-8.1.0.tgz", + "integrity": "sha512-4c+Uhr7/aPSjvJcctAFuamt1O0gZzzca8dvVBJ0bJFsL14evMVbJVmIu9Vtqo2tKj8r3lNnfw+e22XE+2JpDVw==", + "dev": true, + "requires": { + "@google-cloud/common": "^3.4.1", + "@google-cloud/paginator": "^3.0.0", + "@google-cloud/projectify": "^2.0.0", + "@google-cloud/promisify": "^2.0.0", + "@opencensus/propagation-stackdriver": "0.0.22", + "arrify": "^2.0.1", + "dot-prop": "^6.0.0", + "eventid": "^1.0.0", + "extend": "^3.0.2", + "gcp-metadata": "^4.0.0", + "google-auth-library": "^6.0.0", + "google-gax": "^2.9.2", + "is": "^3.3.0", + "on-finished": "^2.3.0", + "pumpify": "^2.0.1", + "snakecase-keys": "^3.1.2", + "stream-events": "^1.0.5", + "through2": "^4.0.0", + "type-fest": "^0.18.0" + }, + "dependencies": { + "type-fest": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.0.tgz", + "integrity": "sha512-fbDukFPnJBdn2eZ3RR+5mK2slHLFd6gYHY7jna1KWWy4Yr4XysHuCdXRzy+RiG/HwG4WJat00vdC2UHky5eKiQ==", + "dev": true + } + } + }, + "@google-cloud/logging-bunyan": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/logging-bunyan/-/logging-bunyan-3.0.1.tgz", + "integrity": "sha512-tp9ltnfl5bmgIjWhK2YLxNcMit6Q9vmtB17/11PWsMCDVZXsCdwTZ58HEysy+xeCjYcsHBmnTohr6Nl+A6puGA==", + "dev": true, + "requires": { + "@google-cloud/logging": "^8.0.0", + "google-auth-library": "^6.0.0" + } + }, + "@google-cloud/paginator": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.5.tgz", + "integrity": "sha512-N4Uk4BT1YuskfRhKXBs0n9Lg2YTROZc6IMpkO/8DIHODtm5s3xY8K5vVBo23v/2XulY3azwITQlYWgT4GdLsUw==", + "dev": true, + "requires": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + } + }, + "@google-cloud/projectify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.0.1.tgz", + "integrity": "sha512-ZDG38U/Yy6Zr21LaR3BTiiLtpJl6RkPS/JwoRT453G+6Q1DhlV0waNf8Lfu+YVYGIIxgKnLayJRfYlFJfiI8iQ==", + "dev": true + }, + "@google-cloud/promisify": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.3.tgz", + "integrity": "sha512-d4VSA86eL/AFTe5xtyZX+ePUjE8dIFu2T8zmdeNBSa5/kNgXPCx/o/wbFNHAGLJdGnk1vddRuMESD9HbOC8irw==", + "dev": true + }, + "@grpc/grpc-js": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.1.8.tgz", + "integrity": "sha512-64hg5rmEm6F/NvlWERhHmmgxbWU8nD2TMWE+9TvG7/WcOrFT3fzg/Uu631pXRFwmJ4aWO/kp9vVSlr8FUjBDLA==", + "dev": true, + "requires": { + "@grpc/proto-loader": "^0.6.0-pre14", + "@types/node": "^12.12.47", + "google-auth-library": "^6.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "@grpc/proto-loader": { + "version": "0.6.0-pre9", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.0-pre9.tgz", + "integrity": "sha512-oM+LjpEjNzW5pNJjt4/hq1HYayNeQT+eGrOPABJnYHv7TyNPDNzkQ76rDYZF86X5swJOa4EujEMzQ9iiTdPgww==", + "dev": true, + "requires": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.9.0", + "yargs": "^15.3.1" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "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==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "string-width": { + "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": "^6.0.0" + } + }, + "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" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "@grpc/proto-loader": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.5.tgz", + "integrity": "sha512-WwN9jVNdHRQoOBo9FDH7qU+mgfjPc8GygPYms3M+y3fbQLfnCe/Kv/E01t7JRgnrsOHH8euvSbed3mIalXhwqQ==", + "dev": true, + "requires": { + "lodash.camelcase": "^4.3.0", + "protobufjs": "^6.8.6" + } + }, + "@opencensus/core": { + "version": "0.0.22", + "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.22.tgz", + "integrity": "sha512-ErazJtivjceNoOZI1bG9giQ6cWS45J4i6iPUtlp7dLNu58OLs/v+CD0FsaPCh47XgPxAI12vbBE8Ec09ViwHNA==", + "dev": true, + "requires": { + "continuation-local-storage": "^3.2.1", + "log-driver": "^1.2.7", + "semver": "^7.0.0", + "shimmer": "^1.2.0", + "uuid": "^8.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "@opencensus/propagation-stackdriver": { + "version": "0.0.22", + "resolved": "https://registry.npmjs.org/@opencensus/propagation-stackdriver/-/propagation-stackdriver-0.0.22.tgz", + "integrity": "sha512-eBvf/ihb1mN8Yz/ASkz8nHzuMKqygu77+VNnUeR0yEh3Nj+ykB8VVR6lK+NAFXo1Rd1cOsTmgvuXAZgDAGleQQ==", + "dev": true, + "requires": { + "@opencensus/core": "^0.0.22", + "hex2dec": "^1.0.1", + "uuid": "^8.0.0" + } + }, + "@overleaf/o-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@overleaf/o-error/-/o-error-3.1.0.tgz", + "integrity": "sha512-TWJ80ozJ1LeugGTJyGQSPEuTkZ9LqZD7/ndLE6azKa03SU/mKV/FINcfk8atpVil8iv1hHQwzYZc35klplpMpQ==", + "dev": true + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=", + "dev": true + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "dev": true + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "dev": true + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=", + "dev": true + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "dev": true, + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=", + "dev": true + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=", + "dev": true + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=", + "dev": true + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=", + "dev": true + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=", + "dev": true + }, "@sinonjs/commons": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", @@ -75,6 +427,12 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -93,6 +451,18 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==", + "dev": true + }, + "@types/node": { + "version": "12.19.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.4.tgz", + "integrity": "sha512-o3oj1bETk8kBwzz1WlO6JWL/AfAA3Vm6J1B3C9CsdxHYp7XgPiH7OEXPUbZTndHlRaIElrANkQfe6ZmfJb3H2w==", + "dev": true + }, "@typescript-eslint/experimental-utils": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", @@ -152,6 +522,15 @@ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "requires": { + "event-target-shim": "^5.0.0" + } + }, "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -164,6 +543,15 @@ "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -289,12 +677,42 @@ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, + "async-listener": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz", + "integrity": "sha512-gpuo6xOyF4D5DE5WvyqZdPA3NGhiT6Qf07l7DCB0wwDEsLvDIbCr6j9S5aj5Ch96dLace5tXVzWBZkxU/c5ohw==", + "dev": true, + "requires": { + "semver": "^5.3.0", + "shimmer": "^1.1.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "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 }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + }, + "bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", + "dev": true + }, "binary-extensions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", @@ -332,6 +750,24 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", + "dev": true + }, + "bunyan": { + "version": "1.8.14", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.14.tgz", + "integrity": "sha512-LlahJUxXzZLuw/hetUQJmRgZ1LF6+cr5TPpRj6jf327AsiIq2jhYEH4oqUUkVKTor+9w2BT3oxVwhzE5lw9tcg==", + "dev": true, + "requires": { + "dtrace-provider": "~0.8", + "moment": "^2.19.3", + "mv": "~2", + "safe-json-stringify": "~1" + } + }, "call-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", @@ -396,6 +832,12 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", + "dev": true + }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -518,6 +960,22 @@ "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, + "continuation-local-storage": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz", + "integrity": "sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA==", + "dev": true, + "requires": { + "async-listener": "^0.6.0", + "emitter-listener": "^1.1.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, "core-js": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.7.0.tgz", @@ -545,6 +1003,18 @@ } } }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", + "dev": true + }, + "d64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d64/-/d64-1.0.0.tgz", + "integrity": "sha1-QAKofoUMv8n52XBrYPymE6MzbpA=", + "dev": true + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -609,12 +1079,82 @@ "esutils": "^2.0.2" } }, + "dot-prop": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.0.tgz", + "integrity": "sha512-xCbB8IN3IT+tdgoEPOnJmYTNJDrygGFOmiQEiVa5eAD+JEB1vTgMNhVGRnN5Eex/6amck7cdcrixb1qN9Go+GQ==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "dtrace-provider": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", + "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.14.0" + } + }, + "duplexify": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz", + "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==", + "dev": true, + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "emitter-listener": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", + "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", + "dev": true, + "requires": { + "shimmer": "^1.2.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 }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -1039,6 +1579,36 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true + }, + "eventid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eventid/-/eventid-1.0.0.tgz", + "integrity": "sha512-4upSDsvpxhWPsmw4fsJCp0zj8S7I0qh1lCDTmZXP8V3TtryQKDI8CgQPN+e5JakbWwzaAX3lrdp2b3KSoMSUpw==", + "dev": true, + "requires": { + "d64": "^1.0.0", + "uuid": "^3.0.1" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -1074,6 +1644,12 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fast-text-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", + "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==", + "dev": true + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -1159,6 +1735,29 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "gaxios": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.0.1.tgz", + "integrity": "sha512-jOin8xRZ/UytQeBpSXFqIzqU7Fi5TqgPNLlUsSB8kjJ76+FiGBfImF8KJu++c6J4jOldfJUtt0YmkRj2ZpSHTQ==", + "dev": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.3.0" + } + }, + "gcp-metadata": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.2.1.tgz", + "integrity": "sha512-tSk+REe5iq/N+K+SK1XjZJUrFPuDqGZVzCy2vocIHIGmPlTGsa8owXMJwGkrXr73NO0AzhPW4MF2DEHz7P2AVw==", + "dev": true, + "requires": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + } + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1220,6 +1819,50 @@ "type-fest": "^0.8.1" } }, + "google-auth-library": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.3.tgz", + "integrity": "sha512-m9mwvY3GWbr7ZYEbl61isWmk+fvTmOt0YNUfPOUY2VH8K5pZlAIWJjxEi0PqR3OjMretyiQLI6GURMrPSwHQ2g==", + "dev": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + } + }, + "google-gax": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.9.2.tgz", + "integrity": "sha512-Pve4osEzNKpBZqFXMfGKBbKCtgnHpUe5IQMh5Ou+Xtg8nLcba94L3gF0xgM5phMdGRRqJn0SMjcuEVmOYu7EBg==", + "dev": true, + "requires": { + "@grpc/grpc-js": "~1.1.1", + "@grpc/proto-loader": "^0.5.1", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "google-auth-library": "^6.1.3", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "protobufjs": "^6.9.0", + "retry-request": "^4.0.0" + } + }, + "google-p12-pem": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz", + "integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==", + "dev": true, + "requires": { + "node-forge": "^0.10.0" + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -1232,6 +1875,18 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "gtoken": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.0.5.tgz", + "integrity": "sha512-wvjkecutFh8kVfbcdBdUWqDRrXb+WrgD79DBDEYf1Om8S1FluhylhtFjrL7Tx69vNhh259qA3Q1P4sPtb+kUYw==", + "dev": true, + "requires": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.0.3", + "jws": "^4.0.0", + "mime": "^2.2.0" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -1276,12 +1931,39 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "hex2dec": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/hex2dec/-/hex2dec-1.1.2.tgz", + "integrity": "sha512-Yu+q/XWr2fFQ11tHxPq4p4EiNkb2y+lAacJNhAdRXVfRIcDH6gi7htWFnnlIzvqHMHoWeIsfXlNAjZInpAOJDA==", + "dev": true + }, "hosted-git-info": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1434,6 +2116,12 @@ "standard-as-callback": "^2.0.1" } }, + "is": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", + "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -1449,6 +2137,12 @@ "binary-extensions": "^2.0.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 + }, "is-callable": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", @@ -1503,6 +2197,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -1518,6 +2218,18 @@ "has-symbols": "^1.0.1" } }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "is-stream-ended": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==", + "dev": true + }, "is-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", @@ -1561,6 +2273,15 @@ "esprima": "^4.0.0" } }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dev": true, + "requires": { + "bignumber.js": "^9.0.0" + } + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1588,6 +2309,27 @@ "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", "dev": true }, + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "dev": true, + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "dev": true, + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -1625,6 +2367,12 @@ "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, "lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", @@ -1659,6 +2407,12 @@ "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", "dev": true }, + "log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true + }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -1698,6 +2452,20 @@ } } }, + "logger-sharelatex": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/logger-sharelatex/-/logger-sharelatex-2.2.0.tgz", + "integrity": "sha512-ko+OmE25XHJJCiz1R9EgwlfM7J/5olpunUfR3WcfuqOQrcUqsdBrDA2sOytngT0ViwjCR0Fh4qZVPwEWfmrvwA==", + "dev": true, + "requires": { + "@google-cloud/logging-bunyan": "^3.0.0", + "@overleaf/o-error": "^3.0.0", + "bunyan": "^1.8.14", + "node-fetch": "^2.6.0", + "raven": "^2.6.4", + "yn": "^4.0.0" + } + }, "loglevel": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", @@ -1756,6 +2524,21 @@ } } }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "make-plural": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-4.3.0.tgz", @@ -1771,6 +2554,17 @@ "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", "dev": true }, + "md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dev": true, + "requires": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, "messageformat": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/messageformat/-/messageformat-2.3.0.tgz", @@ -1794,6 +2588,12 @@ "integrity": "sha512-2fU3XDCanRqeOCkn7R5zW5VQHWf+T3hH65SzuqRvjatBK7r4uyFa5mEX+k6F9Bd04LVM5G4/BHBTUJsOdW7uyg==", "dev": true }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + }, "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -1927,6 +2727,13 @@ } } }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "dev": true, + "optional": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -1938,6 +2745,61 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", + "dev": true, + "optional": true, + "requires": { + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "dev": true, + "optional": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "dev": true, + "optional": true, + "requires": { + "glob": "^6.0.1" + } + } + } + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, "nanoid": { "version": "3.1.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", @@ -1950,6 +2812,13 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "dev": true, + "optional": true + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -1969,6 +2838,18 @@ "path-to-regexp": "^1.7.0" } }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -2031,6 +2912,15 @@ "has": "^1.0.3" } }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2823,6 +3713,56 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "protobufjs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.1.tgz", + "integrity": "sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ==", + "dev": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": "^13.7.0", + "long": "^4.0.0" + }, + "dependencies": { + "@types/node": { + "version": "13.13.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.30.tgz", + "integrity": "sha512-HmqFpNzp3TSELxU/bUuRK+xzarVOAsR00hzcvM0TXrMlt/+wcSLa5q6YhTb6/cA6wqDCZLDcfd8fSL95x5h7AA==", + "dev": true + } + } + }, + "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" + } + }, + "pumpify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", + "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "dev": true, + "requires": { + "duplexify": "^4.1.1", + "inherits": "^2.0.3", + "pump": "^3.0.0" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -2850,6 +3790,33 @@ "safe-buffer": "^5.1.0" } }, + "raven": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/raven/-/raven-2.6.4.tgz", + "integrity": "sha512-6PQdfC4+DQSFncowthLf+B6Hr0JpPsFBgTVYTAOq7tCmx/kR4SXbeawtPch20+3QfUcQDoJBLjWW1ybvZ4kXTw==", + "dev": true, + "requires": { + "cookie": "0.3.1", + "md5": "^2.2.1", + "stack-trace": "0.0.10", + "timed-out": "4.0.1", + "uuid": "3.3.2" + }, + "dependencies": { + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + } + } + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -2922,6 +3889,17 @@ } } }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "readdirp": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", @@ -3005,6 +3983,15 @@ "signal-exit": "^3.0.2" } }, + "retry-request": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.1.3.tgz", + "integrity": "sha512-QnRZUpuPNgX0+D1xVxul6DbJ9slvo4Rm6iV/dn63e048MvGbUZiKySVt6Tenp04JqmchxjiLltGerOJys7kJYQ==", + "dev": true, + "requires": { + "debug": "^4.1.1" + } + }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -3035,6 +4022,13 @@ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, + "safe-json-stringify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", + "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", + "dev": true, + "optional": true + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -3087,6 +4081,12 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "dev": true + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -3130,6 +4130,16 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "snakecase-keys": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.2.0.tgz", + "integrity": "sha512-WTJ0NhCH/37J+PU3fuz0x5b6TvtWQChTcKPOndWoUy0pteKOe0hrHMzSRsJOWSIP48EQkzUEsgQPmrG3W8pFNQ==", + "dev": true, + "requires": { + "map-obj": "^4.0.0", + "to-snake-case": "^1.0.0" + } + }, "spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -3179,6 +4189,21 @@ "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.0.1.tgz", "integrity": "sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==" }, + "stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "dev": true, + "requires": { + "stubs": "^3.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -3270,6 +4295,15 @@ } } }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -3299,6 +4333,12 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "dev": true + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -3341,6 +4381,19 @@ } } }, + "teeny-request": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.0.1.tgz", + "integrity": "sha512-sasJmQ37klOlplL4Ia/786M5YlOcoLGQyq2TE4WHSRupbAuDaQW0PfVxV4MtdBtRJ4ngzS+1qim8zP6Zp35qCw==", + "dev": true, + "requires": { + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^8.0.0" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3353,6 +4406,21 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "requires": { + "readable-stream": "3" + } + }, + "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", @@ -3362,6 +4430,12 @@ "os-tmpdir": "~1.0.2" } }, + "to-no-case": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz", + "integrity": "sha1-xyKQcWTvaxeBMsjmmTAhLRtKoWo=", + "dev": true + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3371,6 +4445,24 @@ "is-number": "^7.0.0" } }, + "to-snake-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-snake-case/-/to-snake-case-1.0.0.tgz", + "integrity": "sha1-znRpE4l5RgGah+Yu366upMYIq4w=", + "dev": true, + "requires": { + "to-space-case": "^1.0.0" + } + }, + "to-space-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz", + "integrity": "sha1-sFLar7Gysp3HcM6gFj5ewOvJ/Bc=", + "dev": true, + "requires": { + "to-no-case": "^1.0.0" + } + }, "tsconfig-paths": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", @@ -3430,6 +4522,18 @@ "punycode": "^2.1.0" } }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", + "dev": true + }, "v8-compile-cache": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", @@ -3645,6 +4749,12 @@ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "yargs": { "version": "13.3.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", @@ -3769,6 +4879,12 @@ "dev": true } } + }, + "yn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-4.0.0.tgz", + "integrity": "sha512-huWiiCS4TxKc4SfgmTwW1K7JmXPPAmuXWYy4j9qjQo4+27Kni8mGhAAi1cloRWmBe2EqcLgt3IGqQoRL/MtPgg==", + "dev": true } } } diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index e0990a924a..323f6a92ce 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -29,6 +29,7 @@ "eslint-plugin-prettier": "^3.1.3", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.1", + "logger-sharelatex": "^2.2.0", "mocha": "^8.2.1", "prettier": "^2.0.2", "prettier-eslint-cli": "^5.0.0", diff --git a/libraries/redis-wrapper/test/scripts/cluster/cluster.js b/libraries/redis-wrapper/test/scripts/cluster/cluster.js index 54dedb1385..1e8dd8076e 100644 --- a/libraries/redis-wrapper/test/scripts/cluster/cluster.js +++ b/libraries/redis-wrapper/test/scripts/cluster/cluster.js @@ -7,6 +7,7 @@ */ const redis = require('../../../') +const logger = require('logger-sharelatex') const rclient = redis.createClient({ cluster: Array.from({ length: 9 }).map((value, index) => { @@ -17,9 +18,9 @@ const rclient = redis.createClient({ setInterval(() => { rclient.healthCheck((err) => { if (err) { - console.log('HEALTH CHECK FAILED', err) + logger.error({ err }, 'HEALTH CHECK FAILED') } else { - console.log('HEALTH CHECK OK') + logger.log('HEALTH CHECK OK') } }) }, 1000) diff --git a/libraries/redis-wrapper/test/scripts/standalone.js b/libraries/redis-wrapper/test/scripts/standalone.js index 8e85c90888..c87df8fddc 100644 --- a/libraries/redis-wrapper/test/scripts/standalone.js +++ b/libraries/redis-wrapper/test/scripts/standalone.js @@ -2,15 +2,16 @@ // starting and stopping redis with this script running is a good test const redis = require('../../') +const logger = require('logger-sharelatex') const rclient = redis.createClient({ host: 'localhost', port: '6379' }) setInterval(() => { rclient.healthCheck((err) => { if (err) { - console.log('HEALTH CHECK FAILED', err) + logger.error({ err }, 'HEALTH CHECK FAILED') } else { - console.log('HEALTH CHECK OK') + logger.log('HEALTH CHECK OK') } }) }, 1000) From aabe2d18b9770c99c6e8bf767c7bd78a5446ca86 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Tue, 10 Nov 2020 10:34:06 +0000 Subject: [PATCH 69/79] [misc] rewrite: squash history - promisify - merge health check for single node and cluster - replace the first multi with simple SET in health check - reworked health check with o-error context/stack-traces for failures - drop console.error on health check timeout, consumer logs the error - cleanup unwrapping of ioredis multi result - Promise support for multi.exec This has been squashed from das7pad s fork. REF: b3dd8c5cf4cc6482fd450e6bb67013508844f93f --- libraries/redis-wrapper/Errors.js | 15 ++ libraries/redis-wrapper/index.js | 239 ++++++++++++---------- libraries/redis-wrapper/package-lock.json | 18 -- libraries/redis-wrapper/package.json | 8 +- 4 files changed, 149 insertions(+), 131 deletions(-) create mode 100644 libraries/redis-wrapper/Errors.js diff --git a/libraries/redis-wrapper/Errors.js b/libraries/redis-wrapper/Errors.js new file mode 100644 index 0000000000..b3b3ec0b62 --- /dev/null +++ b/libraries/redis-wrapper/Errors.js @@ -0,0 +1,15 @@ +const OError = require('@overleaf/o-error') + +class RedisError extends OError {} +class RedisHealthCheckFailed extends RedisError {} +class RedisHealthCheckTimedOut extends RedisHealthCheckFailed {} +class RedisHealthCheckWriteError extends RedisHealthCheckFailed {} +class RedisHealthCheckVerifyError extends RedisHealthCheckFailed {} + +module.exports = { + RedisError, + RedisHealthCheckFailed, + RedisHealthCheckTimedOut, + RedisHealthCheckWriteError, + RedisHealthCheckVerifyError, +} diff --git a/libraries/redis-wrapper/index.js b/libraries/redis-wrapper/index.js index 80be830845..f6c600ae4a 100644 --- a/libraries/redis-wrapper/index.js +++ b/libraries/redis-wrapper/index.js @@ -1,14 +1,16 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS103: Rewrite code to no longer use __guard__, or convert again using --optional-chaining - * DS207: Consider shorter variations of null checks - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md - */ -const _ = require('underscore') -const os = require('os') const crypto = require('crypto') +const os = require('os') +const { promisify } = require('util') + +const Redis = require('ioredis') + +const { + RedisHealthCheckTimedOut, + RedisHealthCheckWriteError, + RedisHealthCheckVerifyError, +} = require('./Errors') + +const HEARTBEAT_TIMEOUT = 2000 // generate unique values for health check const HOST = os.hostname() @@ -17,130 +19,147 @@ const RND = crypto.randomBytes(4).toString('hex') let COUNT = 0 function createClient(opts) { - let client, standardOpts - if (opts == null) { - opts = { port: 6379, host: 'localhost' } - } - if (opts.retry_max_delay == null) { - opts.retry_max_delay = 5000 // ms + const standardOpts = Object.assign({}, opts) + delete standardOpts.key_schema + + if (standardOpts.retry_max_delay == null) { + standardOpts.retry_max_delay = 5000 // ms } - if (opts.cluster != null) { - const Redis = require('ioredis') - standardOpts = _.clone(opts) + let client + if (opts.cluster) { delete standardOpts.cluster - delete standardOpts.key_schema client = new Redis.Cluster(opts.cluster, standardOpts) - client.healthCheck = clusterHealthCheckBuilder(client) - _monkeyPatchIoredisExec(client) } else { - standardOpts = _.clone(opts) - const ioredis = require('ioredis') - client = new ioredis(standardOpts) - _monkeyPatchIoredisExec(client) - client.healthCheck = singleInstanceHealthCheckBuilder(client) + client = new Redis(standardOpts) + } + monkeyPatchIoRedisExec(client) + client.healthCheck = (callback) => { + if (callback) { + // callback based invocation + healthCheck(client).then(callback).catch(callback) + } else { + // Promise based invocation + return healthCheck(client) + } } return client } -const HEARTBEAT_TIMEOUT = 2000 -function singleInstanceHealthCheckBuilder(client) { - const healthCheck = (callback) => _checkClient(client, callback) - return healthCheck -} - -function clusterHealthCheckBuilder(client) { - return singleInstanceHealthCheckBuilder(client) -} - -function _checkClient(client, callback) { - callback = _.once(callback) +async function healthCheck(client) { // check the redis connection by storing and retrieving a unique key/value pair const uniqueToken = `host=${HOST}:pid=${PID}:random=${RND}:time=${Date.now()}:count=${COUNT++}` - const timer = setTimeout(function () { - const error = new Error( - `redis client health check timed out ${__guard__( - client != null ? client.options : undefined, - (x) => x.host - )}` - ) - console.error( - { - err: error, - key: client.options != null ? client.options.key : undefined, // only present for cluster - clientOptions: client.options, - uniqueToken, - }, - 'client timed out' - ) - return callback(error) - }, HEARTBEAT_TIMEOUT) + + // o-error context + const context = { + uniqueToken, + stage: 'add context for a timeout', + } + + await runWithTimeout({ + runner: runCheck(client, uniqueToken, context), + timeout: HEARTBEAT_TIMEOUT, + context, + }) +} + +async function runCheck(client, uniqueToken, context) { const healthCheckKey = `_redis-wrapper:healthCheckKey:{${uniqueToken}}` const healthCheckValue = `_redis-wrapper:healthCheckValue:{${uniqueToken}}` + // set the unique key/value pair - let multi = client.multi() - multi.set(healthCheckKey, healthCheckValue, 'EX', 60) - return multi.exec(function (err, reply) { - if (err != null) { - clearTimeout(timer) - return callback(err) - } - // check that we can retrieve the unique key/value pair - multi = client.multi() - multi.get(healthCheckKey) - multi.del(healthCheckKey) - return multi.exec(function (err, reply) { - clearTimeout(timer) - if (err != null) { - return callback(err) - } - if ( - (reply != null ? reply[0] : undefined) !== healthCheckValue || - (reply != null ? reply[1] : undefined) !== 1 - ) { - return callback(new Error('bad response from redis health check')) - } - return callback() + context.stage = 'write' + const writeAck = await client + .set(healthCheckKey, healthCheckValue, 'EX', 60) + .catch((err) => { + throw new RedisHealthCheckWriteError('write errored', context, err) }) - }) + if (writeAck !== 'OK') { + context.writeAck = writeAck + throw new RedisHealthCheckWriteError('write failed', context) + } + + // check that we can retrieve the unique key/value pair + context.stage = 'verify' + const [roundTrippedHealthCheckValue, deleteAck] = await client + .multi() + .get(healthCheckKey) + .del(healthCheckKey) + .exec() + .catch((err) => { + throw new RedisHealthCheckVerifyError( + 'read/delete errored', + context, + err + ) + }) + if (roundTrippedHealthCheckValue !== healthCheckValue) { + context.roundTrippedHealthCheckValue = roundTrippedHealthCheckValue + throw new RedisHealthCheckVerifyError('read failed', context) + } + if (deleteAck !== 1) { + context.deleteAck = deleteAck + throw new RedisHealthCheckVerifyError('delete failed', context) + } } -function _monkeyPatchIoredisExec(client) { +function unwrapMultiResult(result, callback) { + // ioredis exec returns a results like: + // [ [null, 42], [null, "foo"] ] + // where the first entries in each 2-tuple are + // presumably errors for each individual command, + // and the second entry is the result. We need to transform + // this into the same result as the old redis driver: + // [ 42, "foo" ] + // + // Basically reverse: + // https://github.com/luin/ioredis/blob/v4.17.3/lib/utils/index.ts#L75-L92 + const filteredResult = [] + for (const [err, value] of result || []) { + if (err) { + return callback(err) + } else { + filteredResult.push(value) + } + } + callback(null, filteredResult) +} +const unwrapMultiResultPromisified = promisify(unwrapMultiResult) + +function monkeyPatchIoRedisExec(client) { const _multi = client.multi - return (client.multi = function (...args) { - const multi = _multi.call(client, ...Array.from(args)) + client.multi = function () { + const multi = _multi.apply(client, arguments) const _exec = multi.exec - multi.exec = function (callback) { - if (callback == null) { - callback = function () {} + multi.exec = (callback) => { + if (callback) { + // callback based invocation + _exec.call(multi, (error, result) => { + // The command can fail all-together due to syntax errors + if (error) return callback(error) + unwrapMultiResult(result, callback) + }) + } else { + // Promise based invocation + return _exec.call(multi).then(unwrapMultiResultPromisified) } - return _exec.call(multi, function (error, result) { - // ioredis exec returns an results like: - // [ [null, 42], [null, "foo"] ] - // where the first entries in each 2-tuple are - // presumably errors for each individual command, - // and the second entry is the result. We need to transform - // this into the same result as the old redis driver: - // [ 42, "foo" ] - const filtered_result = [] - for (const entry of Array.from(result || [])) { - if (entry[0] != null) { - return callback(entry[0]) - } else { - filtered_result.push(entry[1]) - } - } - return callback(error, filtered_result) - }) } return multi - }) + } } -function __guard__(value, transform) { - return typeof value !== 'undefined' && value !== null - ? transform(value) - : undefined +async function runWithTimeout({ runner, timeout, context }) { + let healthCheckDeadline + await Promise.race([ + new Promise((resolve, reject) => { + healthCheckDeadline = setTimeout(() => { + // attach the timeout when hitting the timeout only + context.timeout = timeout + reject(new RedisHealthCheckTimedOut('timeout', context)) + }, timeout) + }), + runner.finally(() => clearTimeout(healthCheckDeadline)), + ]) } module.exports = { diff --git a/libraries/redis-wrapper/package-lock.json b/libraries/redis-wrapper/package-lock.json index f46c613bab..86fa19296b 100644 --- a/libraries/redis-wrapper/package-lock.json +++ b/libraries/redis-wrapper/package-lock.json @@ -919,14 +919,6 @@ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" }, - "coffee-script": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.8.0.tgz", - "integrity": "sha1-nJ8dK0pSoADe0Vtll5FwNkgmPB0=", - "requires": { - "mkdirp": "~0.3.5" - } - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2615,11 +2607,6 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, - "mkdirp": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", - "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" - }, "mocha": { "version": "8.2.1", "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", @@ -4508,11 +4495,6 @@ "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", "dev": true }, - "underscore": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" - }, "uri-js": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 323f6a92ce..5d42b60815 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -11,12 +11,14 @@ "format:fix": "prettier-eslint $PWD'/**/*.js' --write", "test": "mocha --recursive test/unit/src/" }, + "peerDependencies": { + "@overleaf/o-error": "^3.1.0" + }, "dependencies": { - "coffee-script": "1.8.0", - "ioredis": "~4.17.3", - "underscore": "1.7.0" + "ioredis": "~4.17.3" }, "devDependencies": { + "@overleaf/o-error": "^3.1.0", "chai": "^4.2.0", "eslint": "^6.8.0", "eslint-config-prettier": "^6.10.1", From d7eb8c7ecf09e08343a9aab28c892177b7cbc82c Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 17:45:59 +0000 Subject: [PATCH 70/79] [misc] refresh package.json - trim down the files for publishing - drop sentinel from description - Overleaf is the new author - add repository reference --- libraries/redis-wrapper/package.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 5d42b60815..c5267ab291 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,9 +1,14 @@ { "name": "redis-sharelatex", "version": "1.0.13", - "description": "Redis wrapper for node which will either use cluster, sentinal, or single instance redis", + "description": "Redis wrapper for node which will either use cluster or single instance redis", "main": "index.js", - "author": "ShareLaTeX", + "files": [ + "index.js", + "Errors.js" + ], + "author": "Overleaf (https://www.overleaf.com)", + "repository": "github:overleaf/redis-wrapper", "license": "ISC", "scripts": { "lint": "eslint --max-warnings 0 .", From 41aa5ec876d0a068b6b9a88b74da7696dfe2a8a6 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 17:51:06 +0000 Subject: [PATCH 71/79] [misc] rename package to @overleaf/redis-wrapper --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index c5267ab291..ffc6cd9ca5 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,5 +1,5 @@ { - "name": "redis-sharelatex", + "name": "@overleaf/redis-wrapper", "version": "1.0.13", "description": "Redis wrapper for node which will either use cluster or single instance redis", "main": "index.js", From bcd5abadce296df6eb50160638bdf5d5411717f8 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 9 Nov 2020 17:51:19 +0000 Subject: [PATCH 72/79] [misc] version bump to 2.0.0 --- libraries/redis-wrapper/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index ffc6cd9ca5..f3f70e057e 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "@overleaf/redis-wrapper", - "version": "1.0.13", + "version": "2.0.0", "description": "Redis wrapper for node which will either use cluster or single instance redis", "main": "index.js", "files": [ From e34f17a3525bd3fd2ff167107fc938bfbaf1cf9f Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Wed, 11 Nov 2020 11:31:44 +0000 Subject: [PATCH 73/79] [misc] creating a redis client with redis-sentinel opts throws an error --- libraries/redis-wrapper/index.js | 6 ++++++ libraries/redis-wrapper/test/unit/src/test.js | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/libraries/redis-wrapper/index.js b/libraries/redis-wrapper/index.js index f6c600ae4a..45d0fc383c 100644 --- a/libraries/redis-wrapper/index.js +++ b/libraries/redis-wrapper/index.js @@ -26,6 +26,12 @@ function createClient(opts) { standardOpts.retry_max_delay = 5000 // ms } + if (standardOpts.endpoints) { + throw new Error( + '@overleaf/redis-wrapper: redis-sentinel is no longer supported' + ) + } + let client if (opts.cluster) { delete standardOpts.cluster diff --git a/libraries/redis-wrapper/test/unit/src/test.js b/libraries/redis-wrapper/test/unit/src/test.js index af1c3db190..12671d539b 100644 --- a/libraries/redis-wrapper/test/unit/src/test.js +++ b/libraries/redis-wrapper/test/unit/src/test.js @@ -55,6 +55,20 @@ describe('index', function () { return (this.auth_pass = '1234 pass') }) + describe('redis-sentinel', function () { + it('should throw an error when creating a client', function () { + const redisSentinelOptions = { + endpoints: ['127.0.0.1:1234', '127.0.0.1:2345', '127.0.0.1:3456'], + } + const createNewClient = () => { + this.redis.createClient(redisSentinelOptions) + } + expect(createNewClient).to.throw( + '@overleaf/redis-wrapper: redis-sentinel is no longer supported' + ) + }) + }) + describe('single node redis', function () { beforeEach(function () { return (this.standardOpts = { From 645295948205ee0da051ae8d2fb17b808c4d8eda Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Wed, 11 Nov 2020 11:35:33 +0000 Subject: [PATCH 74/79] [misc] do not access potentially undefined opts --- libraries/redis-wrapper/index.js | 2 +- libraries/redis-wrapper/test/unit/src/test.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/redis-wrapper/index.js b/libraries/redis-wrapper/index.js index 45d0fc383c..211cb15eff 100644 --- a/libraries/redis-wrapper/index.js +++ b/libraries/redis-wrapper/index.js @@ -33,7 +33,7 @@ function createClient(opts) { } let client - if (opts.cluster) { + if (standardOpts.cluster) { delete standardOpts.cluster client = new Redis.Cluster(opts.cluster, standardOpts) } else { diff --git a/libraries/redis-wrapper/test/unit/src/test.js b/libraries/redis-wrapper/test/unit/src/test.js index 12671d539b..3e9f4fb4de 100644 --- a/libraries/redis-wrapper/test/unit/src/test.js +++ b/libraries/redis-wrapper/test/unit/src/test.js @@ -78,6 +78,10 @@ describe('index', function () { }) }) + it('should work without opts', function () { + this.redis.createClient() + }) + it('should use the ioredis driver in single-instance mode if a non array is passed', function () { const client = this.redis.createClient(this.standardOpts) return assert.equal(client.constructor, this.ioredis) From bf26b7d59694593435c29ffd73ba632ff33df45c Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Thu, 29 Apr 2021 09:20:58 +0100 Subject: [PATCH 75/79] upgrade ioredis and dev dependencies --- libraries/redis-wrapper/package-lock.json | 778 +++++++++++++--------- libraries/redis-wrapper/package.json | 20 +- 2 files changed, 457 insertions(+), 341 deletions(-) diff --git a/libraries/redis-wrapper/package-lock.json b/libraries/redis-wrapper/package-lock.json index 86fa19296b..894912ff70 100644 --- a/libraries/redis-wrapper/package-lock.json +++ b/libraries/redis-wrapper/package-lock.json @@ -1,6 +1,6 @@ { - "name": "redis-sharelatex", - "version": "1.0.13", + "name": "@overleaf/redis-wrapper", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -313,10 +313,13 @@ } }, "@overleaf/o-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@overleaf/o-error/-/o-error-3.1.0.tgz", - "integrity": "sha512-TWJ80ozJ1LeugGTJyGQSPEuTkZ9LqZD7/ndLE6azKa03SU/mKV/FINcfk8atpVil8iv1hHQwzYZc35klplpMpQ==", - "dev": true + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@overleaf/o-error/-/o-error-3.3.1.tgz", + "integrity": "sha512-1FRBYZO0lbJ0U+FRGZVS8ou6RhEw3e2B86WW/NbtBw554g0h5iC8ESf+juIfPMU/WDf/JDIFbg3eB/LnP2RSow==", + "dev": true, + "requires": { + "core-js": "^3.8.3" + } }, "@protobufjs/aspromise": { "version": "1.1.2", @@ -383,9 +386,9 @@ "dev": true }, "@sinonjs/commons": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", - "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -400,20 +403,10 @@ "@sinonjs/commons": "^1.7.0" } }, - "@sinonjs/formatio": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", - "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^5.0.2" - } - }, "@sinonjs/samsam": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.2.0.tgz", - "integrity": "sha512-CaIcyX5cDsjcW/ab7HposFWzV1kC++4HNsfnEdFJa7cP1QIuILAKV+BgfeqRXhcnSAc76r/Rh/O5C+300BwUIw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", "dev": true, "requires": { "@sinonjs/commons": "^1.6.0", @@ -440,9 +433,9 @@ "dev": true }, "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", "dev": true }, "@types/json5": { @@ -620,9 +613,9 @@ } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -714,9 +707,9 @@ "dev": true }, "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, "boolify": { @@ -802,16 +795,16 @@ } }, "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", - "pathval": "^1.1.0", + "pathval": "^1.1.1", "type-detect": "^4.0.5" } }, @@ -845,14 +838,14 @@ "dev": true }, "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", "dev": true, "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", - "fsevents": "~2.1.2", + "fsevents": "~2.3.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -876,40 +869,46 @@ "dev": true }, "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.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==", + "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==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "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==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.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==", + "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": "^4.1.0" + "ansi-regex": "^5.0.0" } } } @@ -969,9 +968,9 @@ "dev": true }, "core-js": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.7.0.tgz", - "integrity": "sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA==", + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.11.1.tgz", + "integrity": "sha512-k93Isqg7e4txZWMGNYwevZL9MiogLk8pd1PtwrmFmi8IBq4GXqUaVW/a33Llt6amSI36uSjd0GWwc9pTT9ALlQ==", "dev": true }, "cross-spawn": { @@ -1011,6 +1010,7 @@ "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" } @@ -1039,21 +1039,21 @@ "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", "dev": true, "requires": { "object-keys": "^1.0.12" } }, "denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz", + "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==" }, "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, "dlv": { @@ -1186,6 +1186,12 @@ "is-symbol": "^1.0.2" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1463,24 +1469,24 @@ } }, "eslint-plugin-prettier": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", - "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz", + "integrity": "sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" } }, "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==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz", + "integrity": "sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ==", "dev": true }, "eslint-plugin-standard": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.2.tgz", - "integrity": "sha512-nKptN8l7jksXkwFk++PhJB3cCDTcXOEyhISIN86Ue2feJ1LFyY3PrY3/xT2keXlJSY5bpmbiTG0f885/YKAvTA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz", + "integrity": "sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ==", "dev": true }, "eslint-scope": { @@ -1709,16 +1715,16 @@ "dev": true }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", "dev": true }, "functional-red-black-tree": { @@ -1882,7 +1888,7 @@ "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -2093,19 +2099,30 @@ } }, "ioredis": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.17.3.tgz", - "integrity": "sha512-iRvq4BOYzNFkDnSyhx7cmJNOi1x/HWYe+A4VXHBu4qpwJaGT1Mp+D2bVGJntH9K/Z/GeOM/Nprb8gB3bmitz1Q==", + "version": "4.27.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.27.1.tgz", + "integrity": "sha512-PaFNFeBbOcEYHXAdrJuy7uesJcyvzStTM1aYMchTuky+VgKqDbXhnTJHaDsjAwcTwPx8Asatx+l2DW8zZ2xlsQ==", "requires": { "cluster-key-slot": "^1.1.0", - "debug": "^4.1.1", + "debug": "^4.3.1", "denque": "^1.1.0", "lodash.defaults": "^4.2.0", "lodash.flatten": "^4.4.0", - "redis-commands": "1.5.0", + "p-map": "^2.1.0", + "redis-commands": "1.7.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", - "standard-as-callback": "^2.0.1" + "standard-as-callback": "^2.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + } } }, "is": { @@ -2296,9 +2313,9 @@ } }, "just-extend": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", - "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "dev": true }, "jwa": { @@ -2424,9 +2441,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -2459,9 +2476,9 @@ } }, "loglevel": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", - "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", + "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==", "dev": true }, "loglevel-colored-level-prefix": { @@ -2607,55 +2624,69 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, "mocha": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", - "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", + "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.4.3", - "debug": "4.2.0", - "diff": "4.0.2", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", "glob": "7.1.6", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "3.14.0", + "js-yaml": "4.0.0", "log-symbols": "4.0.0", "minimatch": "3.0.4", - "ms": "2.1.2", - "nanoid": "3.1.12", + "ms": "2.1.3", + "nanoid": "3.1.20", "serialize-javascript": "5.0.1", "strip-json-comments": "3.1.1", - "supports-color": "7.2.0", + "supports-color": "8.1.1", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.0.2", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "dependencies": { "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { "ms": "2.1.2" + }, + "dependencies": { + "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 + } } }, "escape-string-regexp": { @@ -2664,40 +2695,25 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "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" - } - }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -2788,9 +2804,9 @@ "optional": true }, "nanoid": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", - "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", "dev": true }, "natural-compare": { @@ -2813,9 +2829,9 @@ "dev": true }, "nise": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", - "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0", @@ -2872,7 +2888,7 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=", "dev": true }, "object.assign": { @@ -2947,12 +2963,12 @@ "dev": true }, "p-limit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", - "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { @@ -2964,6 +2980,11 @@ "p-limit": "^3.0.2" } }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -3037,15 +3058,15 @@ } }, "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", "dev": true }, "pify": { @@ -3121,9 +3142,9 @@ "dev": true }, "prettier": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", - "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", "dev": true }, "prettier-eslint": { @@ -3298,15 +3319,6 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -3370,9 +3382,9 @@ } }, "prettier-eslint-cli": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/prettier-eslint-cli/-/prettier-eslint-cli-5.0.0.tgz", - "integrity": "sha512-cei9UbN1aTrz3sQs88CWpvY/10PYTevzd76zoG1tdJ164OhmNTFRKPTOZrutVvscoQWzbnLKkviS3gu5JXwvZg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/prettier-eslint-cli/-/prettier-eslint-cli-5.0.1.tgz", + "integrity": "sha512-fzX26Q6654RN3SD4c8XDBiJyNWOFQKsMLsMiXIGgSN2xNQLmiqjXW3wnR33qMVJOo+wq86a+WjA6wov0krTvCA==", "dev": true, "requires": { "arrify": "^2.0.1", @@ -3427,6 +3439,39 @@ "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", "dev": true }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "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" + } + } + } + }, "eslint": { "version": "5.16.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", @@ -3584,15 +3629,6 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -3664,6 +3700,123 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true + }, + "wrap-ansi": { + "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": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "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" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, @@ -3897,9 +4050,9 @@ } }, "redis-commands": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", - "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" }, "redis-errors": { "version": "1.2.0", @@ -4081,20 +4234,25 @@ "dev": true }, "sinon": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.1.tgz", - "integrity": "sha512-naPfsamB5KEE1aiioaoqJ6MEhdUs/2vtI5w1hPAXX/UwvoPjXcwh1m5HiKx0HGgKR8lQSoFIgY5jM6KK8VrS9w==", + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", + "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", "dev": true, "requires": { "@sinonjs/commons": "^1.8.1", "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.2.0", + "@sinonjs/samsam": "^5.3.1", "diff": "^4.0.2", "nise": "^4.0.4", "supports-color": "^7.1.0" }, "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4172,9 +4330,9 @@ "dev": true }, "standard-as-callback": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.0.1.tgz", - "integrity": "sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" }, "stream-events": { "version": "1.0.5", @@ -4490,9 +4648,9 @@ "dev": true }, "typescript": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", - "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", + "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", "dev": true }, "uri-js": { @@ -4570,9 +4728,9 @@ } }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -4631,70 +4789,61 @@ "dev": true }, "workerpool": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", - "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", "dev": true }, "wrap-ansi": { - "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==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.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==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "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==", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "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==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.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==", + "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": "^4.1.0" + "ansi-regex": "^5.0.0" } } } @@ -4727,8 +4876,7 @@ }, "y18n": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "resolved": "", "dev": true }, "yallist": { @@ -4738,103 +4886,65 @@ "dev": true }, "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "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.1.2" + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, "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==", + "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==", "dev": true }, - "find-up": { + "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "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==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.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==", + "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": "^4.1.0" + "ansi-regex": "^5.0.0" } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true } } }, "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true }, "yargs-unparser": { "version": "2.0.0", @@ -4867,6 +4977,12 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-4.0.0.tgz", "integrity": "sha512-huWiiCS4TxKc4SfgmTwW1K7JmXPPAmuXWYy4j9qjQo4+27Kni8mGhAAi1cloRWmBe2EqcLgt3IGqQoRL/MtPgg==", "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index f3f70e057e..cf8ab8243e 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -20,11 +20,11 @@ "@overleaf/o-error": "^3.1.0" }, "dependencies": { - "ioredis": "~4.17.3" + "ioredis": "~4.27.1" }, "devDependencies": { - "@overleaf/o-error": "^3.1.0", - "chai": "^4.2.0", + "@overleaf/o-error": "^3.3.1", + "chai": "^4.3.4", "eslint": "^6.8.0", "eslint-config-prettier": "^6.10.1", "eslint-config-standard": "^14.1.1", @@ -33,14 +33,14 @@ "eslint-plugin-import": "^2.20.2", "eslint-plugin-mocha": "^6.3.0", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^3.1.3", - "eslint-plugin-promise": "^4.2.1", - "eslint-plugin-standard": "^4.0.1", + "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-promise": "^4.3.1", + "eslint-plugin-standard": "^4.1.0", "logger-sharelatex": "^2.2.0", - "mocha": "^8.2.1", - "prettier": "^2.0.2", - "prettier-eslint-cli": "^5.0.0", + "mocha": "^8.3.2", + "prettier": "^2.2.1", + "prettier-eslint-cli": "^5.0.1", "sandboxed-module": "^2.0.4", - "sinon": "^9.2.1" + "sinon": "^9.2.4" } } From 46da33a67eebeb540887437fcf85f38d6359f645 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Thu, 29 Apr 2021 09:27:25 +0100 Subject: [PATCH 76/79] fix unit tests --- libraries/redis-wrapper/test/unit/src/test.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/redis-wrapper/test/unit/src/test.js b/libraries/redis-wrapper/test/unit/src/test.js index 3e9f4fb4de..50d859bd07 100644 --- a/libraries/redis-wrapper/test/unit/src/test.js +++ b/libraries/redis-wrapper/test/unit/src/test.js @@ -51,6 +51,9 @@ describe('index', function () { requires: { ioredis: this.ioredis, }, + globals: { + process: process, + }, }) return (this.auth_pass = '1234 pass') }) From 2b088dc87098a8596f092f429468cd26f342c526 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Thu, 29 Apr 2021 09:30:27 +0100 Subject: [PATCH 77/79] increase package version number --- libraries/redis-wrapper/package-lock.json | 13 +++++++------ libraries/redis-wrapper/package.json | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libraries/redis-wrapper/package-lock.json b/libraries/redis-wrapper/package-lock.json index 894912ff70..9a10354c24 100644 --- a/libraries/redis-wrapper/package-lock.json +++ b/libraries/redis-wrapper/package-lock.json @@ -1,6 +1,6 @@ { "name": "@overleaf/redis-wrapper", - "version": "2.0.0", + "version": "2.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1039,7 +1039,7 @@ "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { "object-keys": "^1.0.12" @@ -1724,7 +1724,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "functional-red-black-tree": { @@ -1888,7 +1888,7 @@ "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -2888,7 +2888,7 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true }, "object.assign": { @@ -4876,7 +4876,8 @@ }, "y18n": { "version": "4.0.0", - "resolved": "", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yallist": { diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index cf8ab8243e..94059efb57 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "@overleaf/redis-wrapper", - "version": "2.0.0", + "version": "2.0.1", "description": "Redis wrapper for node which will either use cluster or single instance redis", "main": "index.js", "files": [ From cee9c8cc3628706b7dfb07dcaff05c8b289ba489 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Apr 2021 09:22:54 +0000 Subject: [PATCH 78/79] Bump y18n from 4.0.0 to 4.0.3 Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.3. - [Release notes](https://github.com/yargs/y18n/releases) - [Changelog](https://github.com/yargs/y18n/blob/y18n-v4.0.3/CHANGELOG.md) - [Commits](https://github.com/yargs/y18n/compare/v4.0.0...y18n-v4.0.3) Signed-off-by: dependabot[bot] --- libraries/redis-wrapper/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/redis-wrapper/package-lock.json b/libraries/redis-wrapper/package-lock.json index 9a10354c24..3d95813cd8 100644 --- a/libraries/redis-wrapper/package-lock.json +++ b/libraries/redis-wrapper/package-lock.json @@ -4875,9 +4875,9 @@ } }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "yallist": { From eaebef2298b319929cf56ab6c2e44c13281c521b Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Tue, 27 Jul 2021 16:35:41 +0100 Subject: [PATCH 79/79] [misc] prepare for monorepo - add git ignore entries - sync/create package-lock.json - delete .nvmrc --- libraries/redis-wrapper/.gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/redis-wrapper/.gitignore b/libraries/redis-wrapper/.gitignore index cb03337081..a023589c70 100644 --- a/libraries/redis-wrapper/.gitignore +++ b/libraries/redis-wrapper/.gitignore @@ -9,3 +9,6 @@ node_modules/ /public/js/chat.js plato/ + +.npmrc +Dockerfile