├── .github └── workflows │ ├── nodejs-current-lts-linux.yml │ ├── nodejs-current-lts-mac-win.yml │ ├── nodejs-legacy.yml │ └── nodejs-main.yml ├── .gitignore ├── .jshintignore ├── .jshintrc ├── .npmignore ├── .npmrc ├── README.md ├── lib ├── index.js ├── mongoStore.js └── utils │ ├── getCallbackFromArgs.js │ └── index.js ├── package-lock.json ├── package.json └── test ├── mongoStore ├── _createCollection │ ├── utils.js │ ├── withConnectionOptions.js │ ├── withSuitableParams.js │ ├── withUserAndPassword.js │ └── withUserAndPasswordAndAuthSource.js ├── _getCollection │ ├── utils.js │ ├── withCollectionCreateIndexError.js │ ├── withNotPreparedCollectionStateAndCollection.js │ ├── withNotPreparedCollectionStateAndDisabledCreateTtlIndexOption.js │ ├── withNotPreparedCollectionStateAndWithoutCollection.js │ ├── withPrepairingCollectionState.js │ └── withPreparedCollectionState.js ├── constructor ├── decrement │ ├── utils.js │ ├── withFindOneAndUpdateError.js │ ├── withResetExpireDateOnCange.js │ └── withoutResetExpireDateOnChange.js ├── getClient │ ├── utils.js │ ├── withClient.js │ ├── withoutClientAndWithCollection.js │ └── withoutClientAndWithoutCollection.js ├── incr │ ├── utils.js │ ├── withFindOndAndUpdateDuplicateKeyError.js │ ├── withFindOneAndUpdateError.js │ ├── withResetExpireDateOnCange.js │ └── withoutResetExpireDateOnChange.js └── resetKey │ ├── utils.js │ ├── withDeleteOneError.js │ └── withSuitableParams.js └── utils └── getCallbackFromArgs ├── withArgsWithOneItem.js ├── withLastArgsItemFunction.js └── withLastArgsItemNotFunction.js /.github/workflows/nodejs-current-lts-linux.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Current LTS Linux CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | jobs: 9 | build: 10 | runs-on: ubuntu-20.04 11 | 12 | strategy: 13 | matrix: 14 | node-version: [14.x] 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | - run: npm ci 23 | 24 | - run: npm run lint 25 | - run: npm run makeCodeCoverageSummaryReport 26 | - run: npm run makeCodeCoverageDetailReport 27 | 28 | - name: Coveralls GitHub Action 29 | uses: coverallsapp/github-action@v1.1.2 30 | with: 31 | github-token: ${{ secrets.GITHUB_TOKEN }} 32 | -------------------------------------------------------------------------------- /.github/workflows/nodejs-current-lts-mac-win.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Current LTS macOS and Windows CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | jobs: 9 | build: 10 | runs-on: ubuntu-20.04 11 | 12 | strategy: 13 | matrix: 14 | os: [macos-latest, windows-latest] 15 | node-version: [14.x] 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Node ${{ matrix.node-version }} on ${{ matrix.os }} 20 | uses: actions/setup-node@v1 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - run: npm ci 24 | - run: npm test 25 | -------------------------------------------------------------------------------- /.github/workflows/nodejs-legacy.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Legacy CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | jobs: 9 | build: 10 | runs-on: ubuntu-20.04 11 | 12 | strategy: 13 | matrix: 14 | node-version: [4.x, 6.x, 8.x] 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | - run: npm install 23 | - run: npm test 24 | -------------------------------------------------------------------------------- /.github/workflows/nodejs-main.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Main CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | jobs: 9 | build: 10 | runs-on: ubuntu-20.04 11 | 12 | strategy: 13 | matrix: 14 | node-version: [10.x, 12.x, 14.x, 16.x] 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | - run: npm ci 23 | - run: npm test 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | .nyc_output/ 4 | 5 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | 4 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "newcap": false, 4 | "supernew": false, 5 | "maxlen": 80, 6 | "smarttabs": true, 7 | "indent": 1, 8 | "globalstrict": true, 9 | "strict": true, 10 | // use es3 to get 'extra comma' at object literal error 11 | "es3": true, 12 | // suppress warnings about switches with just one case 13 | "onecase": true, 14 | "nonew": false, 15 | "trailing": true, 16 | "sub": false, 17 | "loopfunc": true, 18 | "boss": false, 19 | "lastsemic": false, 20 | "quotmark": "single", 21 | "undef": true, 22 | "immed": true, 23 | "globals": { 24 | "describe": false, 25 | "it": false, 26 | "before": false, 27 | "after": false 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test/ 2 | .nyc_output/ 3 | coverage/ 4 | .npmignore 5 | .github/ 6 | .jshintrc 7 | .jshintignore 8 | .npmrc 9 | 10 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rate Limit Mongo 2 | 3 | MongoDB store for the [express-rate-limit](https://github.com/nfriedly/express-rate-limit) middleware. 4 | 5 | [![Npm version](https://img.shields.io/npm/v/rate-limit-mongo.svg)](https://www.npmjs.org/package/rate-limit-mongo) 6 | [![Build Status](https://github.com/2do2go/rate-limit-mongo/actions/workflows/nodejs-main.yml/badge.svg?branch=master)](https://github.com/2do2go/rate-limit-mongo/actions/workflows/nodejs-main.yml?query=branch%3Amaster) 7 | [![Coverage Status](https://coveralls.io/repos/github/2do2go/rate-limit-mongo/badge.svg?branch=master)](https://coveralls.io/github/2do2go/rate-limit-mongo?branch=master) 8 | [![Known Vulnerabilities](https://snyk.io/test/npm/rate-limit-mongo/badge.svg)](https://snyk.io/test/npm/rate-limit-mongo) 9 | 10 | 11 | ## Install 12 | 13 | ```sh 14 | $ npm install --save rate-limit-mongo 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```js 20 | var RateLimit = require('express-rate-limit'); 21 | var MongoStore = require('rate-limit-mongo'); 22 | 23 | var limiter = new RateLimit({ 24 | store: new MongoStore({ 25 | uri: 'mongodb://127.0.0.1:27017/test_db', 26 | user: 'mongouser', 27 | password: 'mongopassword', 28 | // should match windowMs 29 | expireTimeMs: 15 * 60 * 1000, 30 | errorHandler: console.error.bind(null, 'rate-limit-mongo') 31 | // see Configuration section for more options and details 32 | }), 33 | max: 100, 34 | // should match expireTimeMs 35 | windowMs: 15 * 60 * 1000 36 | }); 37 | 38 | // apply to all requests 39 | app.use(limiter); 40 | ``` 41 | 42 | 43 | ## Configuration 44 | 45 | * **uri**: string -- uri for connecting to mongodb, `mongodb://127.0.0.1:27017/test_db` for example. 46 | Required if collection hasn't been set. 47 | 48 | * **collectionName**: string -- name of collection for storing records. Defaults to `expressRateRecords` 49 | 50 | * **user**: string -- username for authentication in mongodb 51 | 52 | * **password**: string -- password for authentication in mongodb 53 | 54 | * **authSource**: string -- db name against which authenticate use. If not set db name from uri will be taken. 55 | 56 | * **collection**: object -- mongodb collection instance. Required if uri hasn't been set. 57 | 58 | * **connectionOptions**: object -- mongodb connection options. Allows to pass additional connection options to mongodb. The default connection options are `useUnifiedTopology: true`, `useNewUrlParser: true`. 59 | 60 | * **expireTimeMs**: integer -- time period, in milliseconds, after which record will be reset (deleted). 61 | Defaults to `60 * 1000`. Notice that current implementation uses on mongodb ttl indexes - background task that removes expired documents runs every 60 seconds. As a result, documents may remain in a collection during the period between the expiration of the document and the running of the background task. See [mongodb ttl indexes doc](https://docs.mongodb.com/v3.6/core/index-ttl/#timing-of-the-delete-operation) for more information. 62 | 63 | Note: unless express-tate-limit's headers are disabled, `windowMs` on express-tate-limit's options should be set to the same value as `expireTimeMs` on rate-limit-mongo's options in order for the `Retry-After` header to be correct. 64 | 65 | * **resetExpireDateOnChange**: boolean -- indicates whether expireDate should be reset when changed or not. 66 | Defaults to `false`. 67 | 68 | * **errorHandler**: function -- function that will be called if error happened 69 | during incr, decrement or resetKey methods. Defaults to `_.noop`. 70 | 71 | * **createTtlIndex**: boolean -- defines whether create ttl index ( 72 | on `expirationDate` field with `expireAfterSeconds: 0`) on collection 73 | or not. Could be useful in situations when you don't want to create index 74 | from the app e.g. due to restricted db permissions (see 75 | [#15](https://github.com/2do2go/rate-limit-mongo/issues/15) for details). 76 | Defaults to `true`. 77 | 78 | 79 | ## Methods 80 | 81 | `MongoStore` class provides public methods (`incr`, `decrement`, `resetKey`) 82 | required by [express-rate-limit](https://github.com/nfriedly/express-rate-limit). 83 | 84 | In addition following methods provided: 85 | 86 | * `getClient(callback)` - if `collection` was not passed to the constructor then 87 | that method will pass (as second argument) initiated instace of 88 | [MongoClient](http://mongodb.github.io/node-mongodb-native/3.3/api/MongoClient.html) 89 | to the `callback`, otherwise `null` will be passed. Thus this method provides 90 | control over connection initiated by the library to the end user. This method 91 | is promisified (when `util.promisify` is presented (node.js >= 8)). 92 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = require('./mongoStore'); 4 | -------------------------------------------------------------------------------- /lib/mongoStore.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require('underscore'); 4 | var Steppy = require('twostep').Steppy; 5 | var MongoClient = require('mongodb').MongoClient; 6 | var utils = require('./utils'); 7 | var util = require('util'); 8 | 9 | var MongoStore = function(options) { 10 | var allOptions = _({}).defaults( 11 | options, 12 | { 13 | collectionName: 'expressRateRecords', 14 | expireTimeMs: 60000, 15 | resetExpireDateOnChange: false, 16 | errorHandler: _.noop, 17 | createTtlIndex: true 18 | } 19 | ); 20 | 21 | if ( 22 | !allOptions.collection && 23 | ( 24 | !allOptions.collectionName || 25 | !allOptions.uri 26 | ) 27 | ) { 28 | throw new Error('collection or collectionName and uri should be set'); 29 | } 30 | 31 | this.dbOptions = _(allOptions).pick( 32 | 'uri', 'user', 'password', 'authSource', 'collectionName' 33 | ); 34 | 35 | _(this).extend( 36 | _(allOptions).pick( 37 | 'collection', 'expireTimeMs', 'resetExpireDateOnChange', 38 | 'errorHandler', 'createTtlIndex', 'connectionOptions' 39 | ) 40 | ); 41 | 42 | this._collectionState = 'notPrepared'; 43 | }; 44 | 45 | MongoStore.prototype._createCollection = function(callback) { 46 | var self = this; 47 | Steppy( 48 | function() { 49 | var connectionOptions = _({}).defaults( 50 | self.connectionOptions, 51 | { 52 | useNewUrlParser: true, 53 | useUnifiedTopology: true 54 | } 55 | ); 56 | 57 | if (self.dbOptions.user && self.dbOptions.password) { 58 | var dbName = _(self.dbOptions.uri.split('/')).last(); 59 | 60 | connectionOptions.authSource = self.dbOptions.authSource || dbName; 61 | connectionOptions.auth = { 62 | user: self.dbOptions.user, 63 | password: self.dbOptions.password 64 | }; 65 | } 66 | 67 | MongoClient.connect( 68 | self.dbOptions.uri, 69 | connectionOptions, 70 | this.slot() 71 | ); 72 | }, 73 | function(err, client) { 74 | self.client = client; 75 | var db = self.client.db(); 76 | 77 | self.collection = db.collection(self.dbOptions.collectionName); 78 | 79 | this.pass(null); 80 | }, 81 | callback 82 | ); 83 | }; 84 | 85 | MongoStore.prototype._getCollection = function(callback) { 86 | var self = this; 87 | 88 | if (this._collectionState === 'notPrepared') { 89 | this._collectionState = 'preparing'; 90 | } else if (this._collectionState === 'prepared') { 91 | return callback(null, this.collection); 92 | } else { 93 | return setImmediate(function() { 94 | self._getCollection(callback); 95 | }); 96 | } 97 | 98 | Steppy( 99 | function() { 100 | if (self.collection) { 101 | this.pass(null); 102 | } else { 103 | self._createCollection(this.slot()); 104 | } 105 | }, 106 | function() { 107 | if (self.createTtlIndex) { 108 | self.collection.createIndex( 109 | {expirationDate: 1}, 110 | {expireAfterSeconds: 0}, 111 | this.slot() 112 | ); 113 | } else { 114 | this.pass(null); 115 | } 116 | }, 117 | function(err) { 118 | self._collectionState = err ? 'notPrepared' : 'prepared'; 119 | 120 | callback(err, self.collection); 121 | } 122 | ); 123 | }; 124 | 125 | MongoStore.prototype.incr = function(key, callback) { 126 | var self = this; 127 | Steppy( 128 | function() { 129 | self._getCollection(this.slot()); 130 | }, 131 | function(err, collection) { 132 | var modifier = { 133 | $inc: {counter: 1} 134 | }; 135 | var expirationDate = new Date( 136 | Date.now() + self.expireTimeMs 137 | ); 138 | 139 | if (self.resetExpireDateOnChange) { 140 | modifier.$set = {expirationDate: expirationDate}; 141 | } else { 142 | modifier.$setOnInsert = {expirationDate: expirationDate}; 143 | } 144 | 145 | collection.findOneAndUpdate( 146 | {_id: key}, 147 | modifier, 148 | { 149 | upsert: true, 150 | returnDocument: 'after' 151 | }, 152 | this.slot() 153 | ); 154 | }, 155 | function(err, result) { 156 | var expressRateRecord = result.value; 157 | 158 | this.pass(expressRateRecord.counter, expressRateRecord.expirationDate); 159 | }, 160 | function(err, counter, expirationDate) { 161 | // call function again in case of duplicate key error 162 | if (err && err.code === 11000) { 163 | return self.incr(key, callback); 164 | } 165 | 166 | if (err) { 167 | self.errorHandler(err); 168 | } 169 | 170 | callback(err, counter, expirationDate); 171 | } 172 | ); 173 | }; 174 | 175 | MongoStore.prototype.decrement = function(key) { 176 | var self = this; 177 | var callback = utils.getCallbackFromArgs( 178 | _(arguments).toArray() 179 | ); 180 | 181 | Steppy( 182 | function() { 183 | self._getCollection(this.slot()); 184 | }, 185 | function(err, collection) { 186 | var modifier = { 187 | $inc: {counter: -1} 188 | }; 189 | var expirationDate = new Date( 190 | Date.now() + self.expireTimeMs 191 | ); 192 | 193 | if (self.resetExpireDateOnChange) { 194 | modifier.$set = {expirationDate: expirationDate}; 195 | } else { 196 | modifier.$setOnInsert = {expirationDate: expirationDate}; 197 | } 198 | 199 | collection.findOneAndUpdate( 200 | {_id: key}, 201 | modifier, 202 | { 203 | upsert: true, 204 | returnDocument: 'after' 205 | }, 206 | this.slot() 207 | ); 208 | }, 209 | function(err) { 210 | if (err) { 211 | self.errorHandler(err); 212 | } 213 | 214 | if (callback) { 215 | callback(err); 216 | } 217 | } 218 | ); 219 | }; 220 | 221 | MongoStore.prototype.resetKey = function(key) { 222 | var self = this; 223 | var callback = utils.getCallbackFromArgs( 224 | _(arguments).toArray() 225 | ); 226 | 227 | Steppy( 228 | function() { 229 | self._getCollection(this.slot()); 230 | }, 231 | function(err, collection) { 232 | collection.deleteOne( 233 | {_id: key}, 234 | this.slot() 235 | ); 236 | }, 237 | function(err) { 238 | if (err) { 239 | self.errorHandler(err); 240 | } 241 | 242 | if (callback) { 243 | callback(err); 244 | } 245 | } 246 | ); 247 | }; 248 | 249 | MongoStore.prototype.getClient = function(callback) { 250 | var self = this; 251 | 252 | if (self.client) { 253 | callback(null, self.client); 254 | } else { 255 | // if no client but there is collection then it's an external collection 256 | if (self.collection) { 257 | callback(null, null); 258 | } else { 259 | // if no client and no collection then wait for client appear 260 | setImmediate(function() { 261 | self.getClient(callback); 262 | }); 263 | } 264 | } 265 | }; 266 | 267 | // should remove this condition when support of nodejs < 8 will be dropped 268 | // istanbul ignore else 269 | if (util.promisify) { 270 | MongoStore.prototype.getClient = util.promisify( 271 | MongoStore.prototype.getClient 272 | ); 273 | } 274 | 275 | module.exports = MongoStore; 276 | -------------------------------------------------------------------------------- /lib/utils/getCallbackFromArgs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require('underscore'); 4 | 5 | module.exports = function(args) { 6 | var lastArg = _(args).last(); 7 | var callback; 8 | 9 | if (args.length > 1 && _(lastArg).isFunction()) { 10 | callback = lastArg; 11 | } 12 | 13 | return callback; 14 | }; 15 | -------------------------------------------------------------------------------- /lib/utils/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.getCallbackFromArgs = require('./getCallbackFromArgs'); 4 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rate-limit-mongo", 3 | "version": "2.3.2", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.8.3", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", 10 | "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.8.3" 14 | } 15 | }, 16 | "@babel/core": { 17 | "version": "7.9.6", 18 | "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.6.tgz", 19 | "integrity": "sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg==", 20 | "dev": true, 21 | "requires": { 22 | "@babel/code-frame": "^7.8.3", 23 | "@babel/generator": "^7.9.6", 24 | "@babel/helper-module-transforms": "^7.9.0", 25 | "@babel/helpers": "^7.9.6", 26 | "@babel/parser": "^7.9.6", 27 | "@babel/template": "^7.8.6", 28 | "@babel/traverse": "^7.9.6", 29 | "@babel/types": "^7.9.6", 30 | "convert-source-map": "^1.7.0", 31 | "debug": "^4.1.0", 32 | "gensync": "^1.0.0-beta.1", 33 | "json5": "^2.1.2", 34 | "lodash": "^4.17.13", 35 | "resolve": "^1.3.2", 36 | "semver": "^5.4.1", 37 | "source-map": "^0.5.0" 38 | }, 39 | "dependencies": { 40 | "debug": { 41 | "version": "4.1.1", 42 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 43 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 44 | "dev": true, 45 | "requires": { 46 | "ms": "^2.1.1" 47 | } 48 | }, 49 | "ms": { 50 | "version": "2.1.2", 51 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 52 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 53 | "dev": true 54 | } 55 | } 56 | }, 57 | "@babel/generator": { 58 | "version": "7.9.6", 59 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz", 60 | "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==", 61 | "dev": true, 62 | "requires": { 63 | "@babel/types": "^7.9.6", 64 | "jsesc": "^2.5.1", 65 | "lodash": "^4.17.13", 66 | "source-map": "^0.5.0" 67 | } 68 | }, 69 | "@babel/helper-function-name": { 70 | "version": "7.9.5", 71 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz", 72 | "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==", 73 | "dev": true, 74 | "requires": { 75 | "@babel/helper-get-function-arity": "^7.8.3", 76 | "@babel/template": "^7.8.3", 77 | "@babel/types": "^7.9.5" 78 | } 79 | }, 80 | "@babel/helper-get-function-arity": { 81 | "version": "7.8.3", 82 | "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", 83 | "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", 84 | "dev": true, 85 | "requires": { 86 | "@babel/types": "^7.8.3" 87 | } 88 | }, 89 | "@babel/helper-member-expression-to-functions": { 90 | "version": "7.8.3", 91 | "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", 92 | "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", 93 | "dev": true, 94 | "requires": { 95 | "@babel/types": "^7.8.3" 96 | } 97 | }, 98 | "@babel/helper-module-imports": { 99 | "version": "7.8.3", 100 | "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", 101 | "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", 102 | "dev": true, 103 | "requires": { 104 | "@babel/types": "^7.8.3" 105 | } 106 | }, 107 | "@babel/helper-module-transforms": { 108 | "version": "7.9.0", 109 | "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", 110 | "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==", 111 | "dev": true, 112 | "requires": { 113 | "@babel/helper-module-imports": "^7.8.3", 114 | "@babel/helper-replace-supers": "^7.8.6", 115 | "@babel/helper-simple-access": "^7.8.3", 116 | "@babel/helper-split-export-declaration": "^7.8.3", 117 | "@babel/template": "^7.8.6", 118 | "@babel/types": "^7.9.0", 119 | "lodash": "^4.17.13" 120 | } 121 | }, 122 | "@babel/helper-optimise-call-expression": { 123 | "version": "7.8.3", 124 | "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", 125 | "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", 126 | "dev": true, 127 | "requires": { 128 | "@babel/types": "^7.8.3" 129 | } 130 | }, 131 | "@babel/helper-replace-supers": { 132 | "version": "7.9.6", 133 | "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.9.6.tgz", 134 | "integrity": "sha512-qX+chbxkbArLyCImk3bWV+jB5gTNU/rsze+JlcF6Nf8tVTigPJSI1o1oBow/9Resa1yehUO9lIipsmu9oG4RzA==", 135 | "dev": true, 136 | "requires": { 137 | "@babel/helper-member-expression-to-functions": "^7.8.3", 138 | "@babel/helper-optimise-call-expression": "^7.8.3", 139 | "@babel/traverse": "^7.9.6", 140 | "@babel/types": "^7.9.6" 141 | } 142 | }, 143 | "@babel/helper-simple-access": { 144 | "version": "7.8.3", 145 | "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", 146 | "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", 147 | "dev": true, 148 | "requires": { 149 | "@babel/template": "^7.8.3", 150 | "@babel/types": "^7.8.3" 151 | } 152 | }, 153 | "@babel/helper-split-export-declaration": { 154 | "version": "7.8.3", 155 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", 156 | "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", 157 | "dev": true, 158 | "requires": { 159 | "@babel/types": "^7.8.3" 160 | } 161 | }, 162 | "@babel/helper-validator-identifier": { 163 | "version": "7.9.5", 164 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", 165 | "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", 166 | "dev": true 167 | }, 168 | "@babel/helpers": { 169 | "version": "7.9.6", 170 | "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.6.tgz", 171 | "integrity": "sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw==", 172 | "dev": true, 173 | "requires": { 174 | "@babel/template": "^7.8.3", 175 | "@babel/traverse": "^7.9.6", 176 | "@babel/types": "^7.9.6" 177 | } 178 | }, 179 | "@babel/highlight": { 180 | "version": "7.9.0", 181 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", 182 | "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", 183 | "dev": true, 184 | "requires": { 185 | "@babel/helper-validator-identifier": "^7.9.0", 186 | "chalk": "^2.0.0", 187 | "js-tokens": "^4.0.0" 188 | }, 189 | "dependencies": { 190 | "js-tokens": { 191 | "version": "4.0.0", 192 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 193 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 194 | "dev": true 195 | } 196 | } 197 | }, 198 | "@babel/parser": { 199 | "version": "7.9.6", 200 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz", 201 | "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==", 202 | "dev": true 203 | }, 204 | "@babel/template": { 205 | "version": "7.8.6", 206 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", 207 | "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", 208 | "dev": true, 209 | "requires": { 210 | "@babel/code-frame": "^7.8.3", 211 | "@babel/parser": "^7.8.6", 212 | "@babel/types": "^7.8.6" 213 | } 214 | }, 215 | "@babel/traverse": { 216 | "version": "7.9.6", 217 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz", 218 | "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==", 219 | "dev": true, 220 | "requires": { 221 | "@babel/code-frame": "^7.8.3", 222 | "@babel/generator": "^7.9.6", 223 | "@babel/helper-function-name": "^7.9.5", 224 | "@babel/helper-split-export-declaration": "^7.8.3", 225 | "@babel/parser": "^7.9.6", 226 | "@babel/types": "^7.9.6", 227 | "debug": "^4.1.0", 228 | "globals": "^11.1.0", 229 | "lodash": "^4.17.13" 230 | }, 231 | "dependencies": { 232 | "debug": { 233 | "version": "4.1.1", 234 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 235 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 236 | "dev": true, 237 | "requires": { 238 | "ms": "^2.1.1" 239 | } 240 | }, 241 | "ms": { 242 | "version": "2.1.2", 243 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 244 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 245 | "dev": true 246 | } 247 | } 248 | }, 249 | "@babel/types": { 250 | "version": "7.9.6", 251 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz", 252 | "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==", 253 | "dev": true, 254 | "requires": { 255 | "@babel/helper-validator-identifier": "^7.9.5", 256 | "lodash": "^4.17.13", 257 | "to-fast-properties": "^2.0.0" 258 | } 259 | }, 260 | "@istanbuljs/load-nyc-config": { 261 | "version": "1.1.0", 262 | "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", 263 | "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", 264 | "dev": true, 265 | "requires": { 266 | "camelcase": "^5.3.1", 267 | "find-up": "^4.1.0", 268 | "get-package-type": "^0.1.0", 269 | "js-yaml": "^3.13.1", 270 | "resolve-from": "^5.0.0" 271 | }, 272 | "dependencies": { 273 | "resolve-from": { 274 | "version": "5.0.0", 275 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", 276 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", 277 | "dev": true 278 | } 279 | } 280 | }, 281 | "@istanbuljs/schema": { 282 | "version": "0.1.2", 283 | "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", 284 | "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", 285 | "dev": true 286 | }, 287 | "@sinonjs/commons": { 288 | "version": "1.6.0", 289 | "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.6.0.tgz", 290 | "integrity": "sha512-w4/WHG7C4WWFyE5geCieFJF6MZkbW4VAriol5KlmQXpAQdxvV0p26sqNZOW6Qyw6Y0l9K4g+cHvvczR2sEEpqg==", 291 | "dev": true, 292 | "requires": { 293 | "type-detect": "4.0.8" 294 | } 295 | }, 296 | "@sinonjs/formatio": { 297 | "version": "3.2.2", 298 | "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", 299 | "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", 300 | "dev": true, 301 | "requires": { 302 | "@sinonjs/commons": "^1", 303 | "@sinonjs/samsam": "^3.1.0" 304 | } 305 | }, 306 | "@sinonjs/samsam": { 307 | "version": "3.3.3", 308 | "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", 309 | "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", 310 | "dev": true, 311 | "requires": { 312 | "@sinonjs/commons": "^1.3.0", 313 | "array-from": "^2.1.1", 314 | "lodash": "^4.17.15" 315 | } 316 | }, 317 | "@sinonjs/text-encoding": { 318 | "version": "0.7.1", 319 | "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", 320 | "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", 321 | "dev": true 322 | }, 323 | "@types/color-name": { 324 | "version": "1.1.1", 325 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 326 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", 327 | "dev": true 328 | }, 329 | "acorn": { 330 | "version": "5.7.4", 331 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", 332 | "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", 333 | "dev": true 334 | }, 335 | "acorn-jsx": { 336 | "version": "3.0.1", 337 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", 338 | "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", 339 | "dev": true, 340 | "requires": { 341 | "acorn": "^3.0.4" 342 | }, 343 | "dependencies": { 344 | "acorn": { 345 | "version": "3.3.0", 346 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 347 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", 348 | "dev": true 349 | } 350 | } 351 | }, 352 | "aggregate-error": { 353 | "version": "3.0.1", 354 | "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", 355 | "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", 356 | "dev": true, 357 | "requires": { 358 | "clean-stack": "^2.0.0", 359 | "indent-string": "^4.0.0" 360 | } 361 | }, 362 | "ajv": { 363 | "version": "5.5.2", 364 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", 365 | "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", 366 | "dev": true, 367 | "requires": { 368 | "co": "^4.6.0", 369 | "fast-deep-equal": "^1.0.0", 370 | "fast-json-stable-stringify": "^2.0.0", 371 | "json-schema-traverse": "^0.3.0" 372 | } 373 | }, 374 | "ajv-keywords": { 375 | "version": "2.1.1", 376 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", 377 | "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", 378 | "dev": true 379 | }, 380 | "ansi-escapes": { 381 | "version": "3.2.0", 382 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", 383 | "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", 384 | "dev": true 385 | }, 386 | "ansi-regex": { 387 | "version": "2.1.1", 388 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 389 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 390 | "dev": true 391 | }, 392 | "ansi-styles": { 393 | "version": "2.2.1", 394 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 395 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", 396 | "dev": true 397 | }, 398 | "append-transform": { 399 | "version": "2.0.0", 400 | "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", 401 | "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", 402 | "dev": true, 403 | "requires": { 404 | "default-require-extensions": "^3.0.0" 405 | } 406 | }, 407 | "archy": { 408 | "version": "1.0.0", 409 | "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", 410 | "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", 411 | "dev": true 412 | }, 413 | "argparse": { 414 | "version": "1.0.10", 415 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 416 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 417 | "dev": true, 418 | "requires": { 419 | "sprintf-js": "~1.0.2" 420 | } 421 | }, 422 | "array-from": { 423 | "version": "2.1.1", 424 | "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", 425 | "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", 426 | "dev": true 427 | }, 428 | "babel-code-frame": { 429 | "version": "6.26.0", 430 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", 431 | "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", 432 | "dev": true, 433 | "requires": { 434 | "chalk": "^1.1.3", 435 | "esutils": "^2.0.2", 436 | "js-tokens": "^3.0.2" 437 | }, 438 | "dependencies": { 439 | "chalk": { 440 | "version": "1.1.3", 441 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 442 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 443 | "dev": true, 444 | "requires": { 445 | "ansi-styles": "^2.2.1", 446 | "escape-string-regexp": "^1.0.2", 447 | "has-ansi": "^2.0.0", 448 | "strip-ansi": "^3.0.0", 449 | "supports-color": "^2.0.0" 450 | } 451 | }, 452 | "strip-ansi": { 453 | "version": "3.0.1", 454 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 455 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 456 | "dev": true, 457 | "requires": { 458 | "ansi-regex": "^2.0.0" 459 | } 460 | }, 461 | "supports-color": { 462 | "version": "2.0.0", 463 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 464 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", 465 | "dev": true 466 | } 467 | } 468 | }, 469 | "balanced-match": { 470 | "version": "1.0.0", 471 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 472 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 473 | "dev": true 474 | }, 475 | "bl": { 476 | "version": "2.2.1", 477 | "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", 478 | "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", 479 | "requires": { 480 | "readable-stream": "^2.3.5", 481 | "safe-buffer": "^5.1.1" 482 | }, 483 | "dependencies": { 484 | "isarray": { 485 | "version": "1.0.0", 486 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 487 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 488 | }, 489 | "readable-stream": { 490 | "version": "2.3.7", 491 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 492 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 493 | "requires": { 494 | "core-util-is": "~1.0.0", 495 | "inherits": "~2.0.3", 496 | "isarray": "~1.0.0", 497 | "process-nextick-args": "~2.0.0", 498 | "safe-buffer": "~5.1.1", 499 | "string_decoder": "~1.1.1", 500 | "util-deprecate": "~1.0.1" 501 | }, 502 | "dependencies": { 503 | "safe-buffer": { 504 | "version": "5.1.2", 505 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 506 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 507 | } 508 | } 509 | }, 510 | "string_decoder": { 511 | "version": "1.1.1", 512 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 513 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 514 | "requires": { 515 | "safe-buffer": "~5.1.0" 516 | }, 517 | "dependencies": { 518 | "safe-buffer": { 519 | "version": "5.1.2", 520 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 521 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 522 | } 523 | } 524 | } 525 | } 526 | }, 527 | "brace-expansion": { 528 | "version": "1.1.11", 529 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 530 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 531 | "dev": true, 532 | "requires": { 533 | "balanced-match": "^1.0.0", 534 | "concat-map": "0.0.1" 535 | } 536 | }, 537 | "browser-stdout": { 538 | "version": "1.3.1", 539 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 540 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 541 | "dev": true 542 | }, 543 | "bson": { 544 | "version": "1.1.6", 545 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", 546 | "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==" 547 | }, 548 | "buffer-from": { 549 | "version": "1.1.1", 550 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 551 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 552 | "dev": true 553 | }, 554 | "caching-transform": { 555 | "version": "4.0.0", 556 | "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", 557 | "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", 558 | "dev": true, 559 | "requires": { 560 | "hasha": "^5.0.0", 561 | "make-dir": "^3.0.0", 562 | "package-hash": "^4.0.0", 563 | "write-file-atomic": "^3.0.0" 564 | } 565 | }, 566 | "caller-path": { 567 | "version": "0.1.0", 568 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", 569 | "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", 570 | "dev": true, 571 | "requires": { 572 | "callsites": "^0.2.0" 573 | } 574 | }, 575 | "callsites": { 576 | "version": "0.2.0", 577 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", 578 | "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", 579 | "dev": true 580 | }, 581 | "camelcase": { 582 | "version": "5.3.1", 583 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 584 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 585 | "dev": true 586 | }, 587 | "chalk": { 588 | "version": "2.4.2", 589 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 590 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 591 | "dev": true, 592 | "requires": { 593 | "ansi-styles": "^3.2.1", 594 | "escape-string-regexp": "^1.0.5", 595 | "supports-color": "^5.3.0" 596 | }, 597 | "dependencies": { 598 | "ansi-styles": { 599 | "version": "3.2.1", 600 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 601 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 602 | "dev": true, 603 | "requires": { 604 | "color-convert": "^1.9.0" 605 | } 606 | } 607 | } 608 | }, 609 | "chardet": { 610 | "version": "0.4.2", 611 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", 612 | "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", 613 | "dev": true 614 | }, 615 | "circular-json": { 616 | "version": "0.3.3", 617 | "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", 618 | "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", 619 | "dev": true 620 | }, 621 | "clean-stack": { 622 | "version": "2.2.0", 623 | "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", 624 | "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", 625 | "dev": true 626 | }, 627 | "cli": { 628 | "version": "1.0.1", 629 | "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", 630 | "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", 631 | "dev": true, 632 | "requires": { 633 | "exit": "0.1.2", 634 | "glob": "^7.1.1" 635 | } 636 | }, 637 | "cli-cursor": { 638 | "version": "2.1.0", 639 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 640 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 641 | "dev": true, 642 | "requires": { 643 | "restore-cursor": "^2.0.0" 644 | } 645 | }, 646 | "cli-width": { 647 | "version": "2.2.0", 648 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 649 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", 650 | "dev": true 651 | }, 652 | "cliui": { 653 | "version": "6.0.0", 654 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", 655 | "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", 656 | "dev": true, 657 | "requires": { 658 | "string-width": "^4.2.0", 659 | "strip-ansi": "^6.0.0", 660 | "wrap-ansi": "^6.2.0" 661 | }, 662 | "dependencies": { 663 | "ansi-regex": { 664 | "version": "5.0.0", 665 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 666 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 667 | "dev": true 668 | }, 669 | "is-fullwidth-code-point": { 670 | "version": "3.0.0", 671 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 672 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 673 | "dev": true 674 | }, 675 | "string-width": { 676 | "version": "4.2.0", 677 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 678 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 679 | "dev": true, 680 | "requires": { 681 | "emoji-regex": "^8.0.0", 682 | "is-fullwidth-code-point": "^3.0.0", 683 | "strip-ansi": "^6.0.0" 684 | } 685 | }, 686 | "strip-ansi": { 687 | "version": "6.0.0", 688 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 689 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 690 | "dev": true, 691 | "requires": { 692 | "ansi-regex": "^5.0.0" 693 | } 694 | } 695 | } 696 | }, 697 | "co": { 698 | "version": "4.6.0", 699 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 700 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 701 | "dev": true 702 | }, 703 | "color-convert": { 704 | "version": "1.9.3", 705 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 706 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 707 | "dev": true, 708 | "requires": { 709 | "color-name": "1.1.3" 710 | } 711 | }, 712 | "color-name": { 713 | "version": "1.1.3", 714 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 715 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 716 | "dev": true 717 | }, 718 | "commander": { 719 | "version": "2.15.1", 720 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", 721 | "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", 722 | "dev": true 723 | }, 724 | "commondir": { 725 | "version": "1.0.1", 726 | "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", 727 | "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", 728 | "dev": true 729 | }, 730 | "concat-map": { 731 | "version": "0.0.1", 732 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 733 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 734 | "dev": true 735 | }, 736 | "concat-stream": { 737 | "version": "1.6.2", 738 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 739 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 740 | "dev": true, 741 | "requires": { 742 | "buffer-from": "^1.0.0", 743 | "inherits": "^2.0.3", 744 | "readable-stream": "^2.2.2", 745 | "typedarray": "^0.0.6" 746 | }, 747 | "dependencies": { 748 | "isarray": { 749 | "version": "1.0.0", 750 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 751 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 752 | "dev": true 753 | }, 754 | "readable-stream": { 755 | "version": "2.3.6", 756 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 757 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 758 | "dev": true, 759 | "requires": { 760 | "core-util-is": "~1.0.0", 761 | "inherits": "~2.0.3", 762 | "isarray": "~1.0.0", 763 | "process-nextick-args": "~2.0.0", 764 | "safe-buffer": "~5.1.1", 765 | "string_decoder": "~1.1.1", 766 | "util-deprecate": "~1.0.1" 767 | } 768 | }, 769 | "safe-buffer": { 770 | "version": "5.1.2", 771 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 772 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 773 | "dev": true 774 | }, 775 | "string_decoder": { 776 | "version": "1.1.1", 777 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 778 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 779 | "dev": true, 780 | "requires": { 781 | "safe-buffer": "~5.1.0" 782 | } 783 | } 784 | } 785 | }, 786 | "console-browserify": { 787 | "version": "1.1.0", 788 | "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", 789 | "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", 790 | "dev": true, 791 | "requires": { 792 | "date-now": "^0.1.4" 793 | } 794 | }, 795 | "convert-source-map": { 796 | "version": "1.7.0", 797 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", 798 | "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", 799 | "dev": true, 800 | "requires": { 801 | "safe-buffer": "~5.1.1" 802 | }, 803 | "dependencies": { 804 | "safe-buffer": { 805 | "version": "5.1.2", 806 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 807 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 808 | "dev": true 809 | } 810 | } 811 | }, 812 | "core-util-is": { 813 | "version": "1.0.2", 814 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 815 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 816 | }, 817 | "cross-spawn": { 818 | "version": "5.1.0", 819 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", 820 | "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", 821 | "dev": true, 822 | "requires": { 823 | "lru-cache": "^4.0.1", 824 | "shebang-command": "^1.2.0", 825 | "which": "^1.2.9" 826 | } 827 | }, 828 | "date-now": { 829 | "version": "0.1.4", 830 | "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", 831 | "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", 832 | "dev": true 833 | }, 834 | "debug": { 835 | "version": "3.1.0", 836 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 837 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 838 | "dev": true, 839 | "requires": { 840 | "ms": "2.0.0" 841 | } 842 | }, 843 | "decamelize": { 844 | "version": "1.2.0", 845 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 846 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 847 | "dev": true 848 | }, 849 | "deep-is": { 850 | "version": "0.1.3", 851 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 852 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 853 | "dev": true 854 | }, 855 | "default-require-extensions": { 856 | "version": "3.0.0", 857 | "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", 858 | "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", 859 | "dev": true, 860 | "requires": { 861 | "strip-bom": "^4.0.0" 862 | } 863 | }, 864 | "denque": { 865 | "version": "1.5.1", 866 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", 867 | "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" 868 | }, 869 | "diff": { 870 | "version": "3.5.0", 871 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 872 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 873 | "dev": true 874 | }, 875 | "doctrine": { 876 | "version": "2.1.0", 877 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 878 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 879 | "dev": true, 880 | "requires": { 881 | "esutils": "^2.0.2" 882 | } 883 | }, 884 | "dom-serializer": { 885 | "version": "0.2.2", 886 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", 887 | "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", 888 | "dev": true, 889 | "requires": { 890 | "domelementtype": "^2.0.1", 891 | "entities": "^2.0.0" 892 | }, 893 | "dependencies": { 894 | "domelementtype": { 895 | "version": "2.0.1", 896 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", 897 | "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", 898 | "dev": true 899 | }, 900 | "entities": { 901 | "version": "2.0.0", 902 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", 903 | "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", 904 | "dev": true 905 | } 906 | } 907 | }, 908 | "domelementtype": { 909 | "version": "1.3.1", 910 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", 911 | "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", 912 | "dev": true 913 | }, 914 | "domhandler": { 915 | "version": "2.3.0", 916 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", 917 | "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", 918 | "dev": true, 919 | "requires": { 920 | "domelementtype": "1" 921 | } 922 | }, 923 | "domutils": { 924 | "version": "1.5.1", 925 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", 926 | "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", 927 | "dev": true, 928 | "requires": { 929 | "dom-serializer": "0", 930 | "domelementtype": "1" 931 | } 932 | }, 933 | "emoji-regex": { 934 | "version": "8.0.0", 935 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 936 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 937 | "dev": true 938 | }, 939 | "entities": { 940 | "version": "1.0.0", 941 | "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", 942 | "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", 943 | "dev": true 944 | }, 945 | "es6-error": { 946 | "version": "4.1.1", 947 | "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", 948 | "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", 949 | "dev": true 950 | }, 951 | "escape-string-regexp": { 952 | "version": "1.0.5", 953 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 954 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 955 | "dev": true 956 | }, 957 | "eslint": { 958 | "version": "4.19.1", 959 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", 960 | "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", 961 | "dev": true, 962 | "requires": { 963 | "ajv": "^5.3.0", 964 | "babel-code-frame": "^6.22.0", 965 | "chalk": "^2.1.0", 966 | "concat-stream": "^1.6.0", 967 | "cross-spawn": "^5.1.0", 968 | "debug": "^3.1.0", 969 | "doctrine": "^2.1.0", 970 | "eslint-scope": "^3.7.1", 971 | "eslint-visitor-keys": "^1.0.0", 972 | "espree": "^3.5.4", 973 | "esquery": "^1.0.0", 974 | "esutils": "^2.0.2", 975 | "file-entry-cache": "^2.0.0", 976 | "functional-red-black-tree": "^1.0.1", 977 | "glob": "^7.1.2", 978 | "globals": "^11.0.1", 979 | "ignore": "^3.3.3", 980 | "imurmurhash": "^0.1.4", 981 | "inquirer": "^3.0.6", 982 | "is-resolvable": "^1.0.0", 983 | "js-yaml": "^3.9.1", 984 | "json-stable-stringify-without-jsonify": "^1.0.1", 985 | "levn": "^0.3.0", 986 | "lodash": "^4.17.4", 987 | "minimatch": "^3.0.2", 988 | "mkdirp": "^0.5.1", 989 | "natural-compare": "^1.4.0", 990 | "optionator": "^0.8.2", 991 | "path-is-inside": "^1.0.2", 992 | "pluralize": "^7.0.0", 993 | "progress": "^2.0.0", 994 | "regexpp": "^1.0.1", 995 | "require-uncached": "^1.0.3", 996 | "semver": "^5.3.0", 997 | "strip-ansi": "^4.0.0", 998 | "strip-json-comments": "~2.0.1", 999 | "table": "4.0.2", 1000 | "text-table": "~0.2.0" 1001 | } 1002 | }, 1003 | "eslint-scope": { 1004 | "version": "3.7.3", 1005 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", 1006 | "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", 1007 | "dev": true, 1008 | "requires": { 1009 | "esrecurse": "^4.1.0", 1010 | "estraverse": "^4.1.1" 1011 | } 1012 | }, 1013 | "eslint-visitor-keys": { 1014 | "version": "1.1.0", 1015 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", 1016 | "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", 1017 | "dev": true 1018 | }, 1019 | "espree": { 1020 | "version": "3.5.4", 1021 | "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", 1022 | "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", 1023 | "dev": true, 1024 | "requires": { 1025 | "acorn": "^5.5.0", 1026 | "acorn-jsx": "^3.0.0" 1027 | } 1028 | }, 1029 | "esprima": { 1030 | "version": "4.0.1", 1031 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 1032 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 1033 | "dev": true 1034 | }, 1035 | "esquery": { 1036 | "version": "1.0.1", 1037 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", 1038 | "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", 1039 | "dev": true, 1040 | "requires": { 1041 | "estraverse": "^4.0.0" 1042 | } 1043 | }, 1044 | "esrecurse": { 1045 | "version": "4.2.1", 1046 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", 1047 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", 1048 | "dev": true, 1049 | "requires": { 1050 | "estraverse": "^4.1.0" 1051 | } 1052 | }, 1053 | "estraverse": { 1054 | "version": "4.3.0", 1055 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 1056 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 1057 | "dev": true 1058 | }, 1059 | "esutils": { 1060 | "version": "2.0.3", 1061 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1062 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1063 | "dev": true 1064 | }, 1065 | "exit": { 1066 | "version": "0.1.2", 1067 | "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", 1068 | "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", 1069 | "dev": true 1070 | }, 1071 | "expect.js": { 1072 | "version": "0.3.1", 1073 | "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.3.1.tgz", 1074 | "integrity": "sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s=", 1075 | "dev": true 1076 | }, 1077 | "external-editor": { 1078 | "version": "2.2.0", 1079 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", 1080 | "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", 1081 | "dev": true, 1082 | "requires": { 1083 | "chardet": "^0.4.0", 1084 | "iconv-lite": "^0.4.17", 1085 | "tmp": "^0.0.33" 1086 | } 1087 | }, 1088 | "fast-deep-equal": { 1089 | "version": "1.1.0", 1090 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", 1091 | "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", 1092 | "dev": true 1093 | }, 1094 | "fast-json-stable-stringify": { 1095 | "version": "2.0.0", 1096 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 1097 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", 1098 | "dev": true 1099 | }, 1100 | "fast-levenshtein": { 1101 | "version": "2.0.6", 1102 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1103 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 1104 | "dev": true 1105 | }, 1106 | "figures": { 1107 | "version": "2.0.0", 1108 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 1109 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 1110 | "dev": true, 1111 | "requires": { 1112 | "escape-string-regexp": "^1.0.5" 1113 | } 1114 | }, 1115 | "file-entry-cache": { 1116 | "version": "2.0.0", 1117 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", 1118 | "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", 1119 | "dev": true, 1120 | "requires": { 1121 | "flat-cache": "^1.2.1", 1122 | "object-assign": "^4.0.1" 1123 | } 1124 | }, 1125 | "find-cache-dir": { 1126 | "version": "3.3.1", 1127 | "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", 1128 | "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", 1129 | "dev": true, 1130 | "requires": { 1131 | "commondir": "^1.0.1", 1132 | "make-dir": "^3.0.2", 1133 | "pkg-dir": "^4.1.0" 1134 | } 1135 | }, 1136 | "find-up": { 1137 | "version": "4.1.0", 1138 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 1139 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 1140 | "dev": true, 1141 | "requires": { 1142 | "locate-path": "^5.0.0", 1143 | "path-exists": "^4.0.0" 1144 | } 1145 | }, 1146 | "flat-cache": { 1147 | "version": "1.3.4", 1148 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", 1149 | "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", 1150 | "dev": true, 1151 | "requires": { 1152 | "circular-json": "^0.3.1", 1153 | "graceful-fs": "^4.1.2", 1154 | "rimraf": "~2.6.2", 1155 | "write": "^0.2.1" 1156 | } 1157 | }, 1158 | "foreground-child": { 1159 | "version": "2.0.0", 1160 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", 1161 | "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", 1162 | "dev": true, 1163 | "requires": { 1164 | "cross-spawn": "^7.0.0", 1165 | "signal-exit": "^3.0.2" 1166 | }, 1167 | "dependencies": { 1168 | "cross-spawn": { 1169 | "version": "7.0.2", 1170 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", 1171 | "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", 1172 | "dev": true, 1173 | "requires": { 1174 | "path-key": "^3.1.0", 1175 | "shebang-command": "^2.0.0", 1176 | "which": "^2.0.1" 1177 | } 1178 | }, 1179 | "shebang-command": { 1180 | "version": "2.0.0", 1181 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1182 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1183 | "dev": true, 1184 | "requires": { 1185 | "shebang-regex": "^3.0.0" 1186 | } 1187 | }, 1188 | "shebang-regex": { 1189 | "version": "3.0.0", 1190 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1191 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1192 | "dev": true 1193 | }, 1194 | "which": { 1195 | "version": "2.0.2", 1196 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1197 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1198 | "dev": true, 1199 | "requires": { 1200 | "isexe": "^2.0.0" 1201 | } 1202 | } 1203 | } 1204 | }, 1205 | "fromentries": { 1206 | "version": "1.2.0", 1207 | "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", 1208 | "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", 1209 | "dev": true 1210 | }, 1211 | "fs.realpath": { 1212 | "version": "1.0.0", 1213 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1214 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 1215 | "dev": true 1216 | }, 1217 | "functional-red-black-tree": { 1218 | "version": "1.0.1", 1219 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 1220 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 1221 | "dev": true 1222 | }, 1223 | "gensync": { 1224 | "version": "1.0.0-beta.1", 1225 | "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", 1226 | "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", 1227 | "dev": true 1228 | }, 1229 | "get-caller-file": { 1230 | "version": "2.0.5", 1231 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1232 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 1233 | "dev": true 1234 | }, 1235 | "get-package-type": { 1236 | "version": "0.1.0", 1237 | "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", 1238 | "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", 1239 | "dev": true 1240 | }, 1241 | "glob": { 1242 | "version": "7.1.6", 1243 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 1244 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 1245 | "dev": true, 1246 | "requires": { 1247 | "fs.realpath": "^1.0.0", 1248 | "inflight": "^1.0.4", 1249 | "inherits": "2", 1250 | "minimatch": "^3.0.4", 1251 | "once": "^1.3.0", 1252 | "path-is-absolute": "^1.0.0" 1253 | }, 1254 | "dependencies": { 1255 | "minimatch": { 1256 | "version": "3.0.4", 1257 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1258 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1259 | "dev": true, 1260 | "requires": { 1261 | "brace-expansion": "^1.1.7" 1262 | } 1263 | } 1264 | } 1265 | }, 1266 | "globals": { 1267 | "version": "11.12.0", 1268 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 1269 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 1270 | "dev": true 1271 | }, 1272 | "graceful-fs": { 1273 | "version": "4.2.3", 1274 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", 1275 | "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", 1276 | "dev": true 1277 | }, 1278 | "growl": { 1279 | "version": "1.10.5", 1280 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 1281 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 1282 | "dev": true 1283 | }, 1284 | "has-ansi": { 1285 | "version": "2.0.0", 1286 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 1287 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 1288 | "dev": true, 1289 | "requires": { 1290 | "ansi-regex": "^2.0.0" 1291 | } 1292 | }, 1293 | "has-flag": { 1294 | "version": "3.0.0", 1295 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 1296 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 1297 | "dev": true 1298 | }, 1299 | "hasha": { 1300 | "version": "5.2.0", 1301 | "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", 1302 | "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", 1303 | "dev": true, 1304 | "requires": { 1305 | "is-stream": "^2.0.0", 1306 | "type-fest": "^0.8.0" 1307 | } 1308 | }, 1309 | "he": { 1310 | "version": "1.1.1", 1311 | "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", 1312 | "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", 1313 | "dev": true 1314 | }, 1315 | "html-escaper": { 1316 | "version": "2.0.2", 1317 | "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", 1318 | "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", 1319 | "dev": true 1320 | }, 1321 | "htmlparser2": { 1322 | "version": "3.8.3", 1323 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", 1324 | "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", 1325 | "dev": true, 1326 | "requires": { 1327 | "domelementtype": "1", 1328 | "domhandler": "2.3", 1329 | "domutils": "1.5", 1330 | "entities": "1.0", 1331 | "readable-stream": "1.1" 1332 | } 1333 | }, 1334 | "iconv-lite": { 1335 | "version": "0.4.24", 1336 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1337 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1338 | "dev": true, 1339 | "requires": { 1340 | "safer-buffer": ">= 2.1.2 < 3" 1341 | } 1342 | }, 1343 | "ignore": { 1344 | "version": "3.3.10", 1345 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", 1346 | "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", 1347 | "dev": true 1348 | }, 1349 | "imurmurhash": { 1350 | "version": "0.1.4", 1351 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1352 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1353 | "dev": true 1354 | }, 1355 | "indent-string": { 1356 | "version": "4.0.0", 1357 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", 1358 | "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", 1359 | "dev": true 1360 | }, 1361 | "inflight": { 1362 | "version": "1.0.6", 1363 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1364 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1365 | "dev": true, 1366 | "requires": { 1367 | "once": "^1.3.0", 1368 | "wrappy": "1" 1369 | } 1370 | }, 1371 | "inherits": { 1372 | "version": "2.0.4", 1373 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1374 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1375 | }, 1376 | "inquirer": { 1377 | "version": "3.3.0", 1378 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", 1379 | "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", 1380 | "dev": true, 1381 | "requires": { 1382 | "ansi-escapes": "^3.0.0", 1383 | "chalk": "^2.0.0", 1384 | "cli-cursor": "^2.1.0", 1385 | "cli-width": "^2.0.0", 1386 | "external-editor": "^2.0.4", 1387 | "figures": "^2.0.0", 1388 | "lodash": "^4.3.0", 1389 | "mute-stream": "0.0.7", 1390 | "run-async": "^2.2.0", 1391 | "rx-lite": "^4.0.8", 1392 | "rx-lite-aggregates": "^4.0.8", 1393 | "string-width": "^2.1.0", 1394 | "strip-ansi": "^4.0.0", 1395 | "through": "^2.3.6" 1396 | } 1397 | }, 1398 | "is-fullwidth-code-point": { 1399 | "version": "2.0.0", 1400 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1401 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 1402 | "dev": true 1403 | }, 1404 | "is-promise": { 1405 | "version": "2.1.0", 1406 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 1407 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", 1408 | "dev": true 1409 | }, 1410 | "is-resolvable": { 1411 | "version": "1.1.0", 1412 | "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", 1413 | "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", 1414 | "dev": true 1415 | }, 1416 | "is-stream": { 1417 | "version": "2.0.0", 1418 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", 1419 | "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", 1420 | "dev": true 1421 | }, 1422 | "is-typedarray": { 1423 | "version": "1.0.0", 1424 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1425 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 1426 | "dev": true 1427 | }, 1428 | "is-windows": { 1429 | "version": "1.0.2", 1430 | "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", 1431 | "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", 1432 | "dev": true 1433 | }, 1434 | "isarray": { 1435 | "version": "0.0.1", 1436 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 1437 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", 1438 | "dev": true 1439 | }, 1440 | "isexe": { 1441 | "version": "2.0.0", 1442 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1443 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1444 | "dev": true 1445 | }, 1446 | "istanbul-lib-coverage": { 1447 | "version": "3.0.0", 1448 | "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", 1449 | "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", 1450 | "dev": true 1451 | }, 1452 | "istanbul-lib-hook": { 1453 | "version": "3.0.0", 1454 | "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", 1455 | "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", 1456 | "dev": true, 1457 | "requires": { 1458 | "append-transform": "^2.0.0" 1459 | } 1460 | }, 1461 | "istanbul-lib-instrument": { 1462 | "version": "4.0.3", 1463 | "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", 1464 | "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", 1465 | "dev": true, 1466 | "requires": { 1467 | "@babel/core": "^7.7.5", 1468 | "@istanbuljs/schema": "^0.1.2", 1469 | "istanbul-lib-coverage": "^3.0.0", 1470 | "semver": "^6.3.0" 1471 | }, 1472 | "dependencies": { 1473 | "semver": { 1474 | "version": "6.3.0", 1475 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1476 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1477 | "dev": true 1478 | } 1479 | } 1480 | }, 1481 | "istanbul-lib-processinfo": { 1482 | "version": "2.0.2", 1483 | "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", 1484 | "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", 1485 | "dev": true, 1486 | "requires": { 1487 | "archy": "^1.0.0", 1488 | "cross-spawn": "^7.0.0", 1489 | "istanbul-lib-coverage": "^3.0.0-alpha.1", 1490 | "make-dir": "^3.0.0", 1491 | "p-map": "^3.0.0", 1492 | "rimraf": "^3.0.0", 1493 | "uuid": "^3.3.3" 1494 | }, 1495 | "dependencies": { 1496 | "cross-spawn": { 1497 | "version": "7.0.2", 1498 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", 1499 | "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", 1500 | "dev": true, 1501 | "requires": { 1502 | "path-key": "^3.1.0", 1503 | "shebang-command": "^2.0.0", 1504 | "which": "^2.0.1" 1505 | } 1506 | }, 1507 | "rimraf": { 1508 | "version": "3.0.2", 1509 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1510 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1511 | "dev": true, 1512 | "requires": { 1513 | "glob": "^7.1.3" 1514 | } 1515 | }, 1516 | "shebang-command": { 1517 | "version": "2.0.0", 1518 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1519 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1520 | "dev": true, 1521 | "requires": { 1522 | "shebang-regex": "^3.0.0" 1523 | } 1524 | }, 1525 | "shebang-regex": { 1526 | "version": "3.0.0", 1527 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1528 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1529 | "dev": true 1530 | }, 1531 | "which": { 1532 | "version": "2.0.2", 1533 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1534 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1535 | "dev": true, 1536 | "requires": { 1537 | "isexe": "^2.0.0" 1538 | } 1539 | } 1540 | } 1541 | }, 1542 | "istanbul-lib-report": { 1543 | "version": "3.0.0", 1544 | "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", 1545 | "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", 1546 | "dev": true, 1547 | "requires": { 1548 | "istanbul-lib-coverage": "^3.0.0", 1549 | "make-dir": "^3.0.0", 1550 | "supports-color": "^7.1.0" 1551 | }, 1552 | "dependencies": { 1553 | "has-flag": { 1554 | "version": "4.0.0", 1555 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1556 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1557 | "dev": true 1558 | }, 1559 | "supports-color": { 1560 | "version": "7.1.0", 1561 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 1562 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 1563 | "dev": true, 1564 | "requires": { 1565 | "has-flag": "^4.0.0" 1566 | } 1567 | } 1568 | } 1569 | }, 1570 | "istanbul-lib-source-maps": { 1571 | "version": "4.0.0", 1572 | "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", 1573 | "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", 1574 | "dev": true, 1575 | "requires": { 1576 | "debug": "^4.1.1", 1577 | "istanbul-lib-coverage": "^3.0.0", 1578 | "source-map": "^0.6.1" 1579 | }, 1580 | "dependencies": { 1581 | "debug": { 1582 | "version": "4.1.1", 1583 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 1584 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 1585 | "dev": true, 1586 | "requires": { 1587 | "ms": "^2.1.1" 1588 | } 1589 | }, 1590 | "ms": { 1591 | "version": "2.1.2", 1592 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1593 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1594 | "dev": true 1595 | }, 1596 | "source-map": { 1597 | "version": "0.6.1", 1598 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1599 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1600 | "dev": true 1601 | } 1602 | } 1603 | }, 1604 | "istanbul-reports": { 1605 | "version": "3.0.2", 1606 | "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", 1607 | "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", 1608 | "dev": true, 1609 | "requires": { 1610 | "html-escaper": "^2.0.0", 1611 | "istanbul-lib-report": "^3.0.0" 1612 | } 1613 | }, 1614 | "js-tokens": { 1615 | "version": "3.0.2", 1616 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 1617 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", 1618 | "dev": true 1619 | }, 1620 | "js-yaml": { 1621 | "version": "3.13.1", 1622 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 1623 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 1624 | "dev": true, 1625 | "requires": { 1626 | "argparse": "^1.0.7", 1627 | "esprima": "^4.0.0" 1628 | } 1629 | }, 1630 | "jsesc": { 1631 | "version": "2.5.2", 1632 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 1633 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", 1634 | "dev": true 1635 | }, 1636 | "jshint": { 1637 | "version": "2.10.3", 1638 | "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.10.3.tgz", 1639 | "integrity": "sha512-d8AoXcNNYzmm7cdmulQ3dQApbrPYArtVBO6n4xOICe4QsXGNHCAKDcFORzqP52LhK61KX0VhY39yYzCsNq+bxQ==", 1640 | "dev": true, 1641 | "requires": { 1642 | "cli": "~1.0.0", 1643 | "console-browserify": "1.1.x", 1644 | "exit": "0.1.x", 1645 | "htmlparser2": "3.8.x", 1646 | "lodash": "~4.17.11", 1647 | "minimatch": "~3.0.2", 1648 | "shelljs": "0.3.x", 1649 | "strip-json-comments": "1.0.x" 1650 | }, 1651 | "dependencies": { 1652 | "strip-json-comments": { 1653 | "version": "1.0.4", 1654 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", 1655 | "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", 1656 | "dev": true 1657 | } 1658 | } 1659 | }, 1660 | "json-schema-traverse": { 1661 | "version": "0.3.1", 1662 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", 1663 | "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", 1664 | "dev": true 1665 | }, 1666 | "json-stable-stringify-without-jsonify": { 1667 | "version": "1.0.1", 1668 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1669 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1670 | "dev": true 1671 | }, 1672 | "json5": { 1673 | "version": "2.1.3", 1674 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", 1675 | "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", 1676 | "dev": true, 1677 | "requires": { 1678 | "minimist": "^1.2.5" 1679 | }, 1680 | "dependencies": { 1681 | "minimist": { 1682 | "version": "1.2.5", 1683 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1684 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1685 | "dev": true 1686 | } 1687 | } 1688 | }, 1689 | "just-extend": { 1690 | "version": "4.0.2", 1691 | "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", 1692 | "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", 1693 | "dev": true 1694 | }, 1695 | "levn": { 1696 | "version": "0.3.0", 1697 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 1698 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 1699 | "dev": true, 1700 | "requires": { 1701 | "prelude-ls": "~1.1.2", 1702 | "type-check": "~0.3.2" 1703 | } 1704 | }, 1705 | "locate-path": { 1706 | "version": "5.0.0", 1707 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 1708 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 1709 | "dev": true, 1710 | "requires": { 1711 | "p-locate": "^4.1.0" 1712 | } 1713 | }, 1714 | "lodash": { 1715 | "version": "4.17.21", 1716 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1717 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 1718 | "dev": true 1719 | }, 1720 | "lodash.flattendeep": { 1721 | "version": "4.4.0", 1722 | "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", 1723 | "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", 1724 | "dev": true 1725 | }, 1726 | "lolex": { 1727 | "version": "4.2.0", 1728 | "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", 1729 | "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", 1730 | "dev": true 1731 | }, 1732 | "lru-cache": { 1733 | "version": "4.1.5", 1734 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 1735 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 1736 | "dev": true, 1737 | "requires": { 1738 | "pseudomap": "^1.0.2", 1739 | "yallist": "^2.1.2" 1740 | } 1741 | }, 1742 | "make-dir": { 1743 | "version": "3.1.0", 1744 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 1745 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 1746 | "dev": true, 1747 | "requires": { 1748 | "semver": "^6.0.0" 1749 | }, 1750 | "dependencies": { 1751 | "semver": { 1752 | "version": "6.3.0", 1753 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1754 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1755 | "dev": true 1756 | } 1757 | } 1758 | }, 1759 | "memory-pager": { 1760 | "version": "1.5.0", 1761 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", 1762 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", 1763 | "optional": true 1764 | }, 1765 | "mimic-fn": { 1766 | "version": "1.2.0", 1767 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 1768 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", 1769 | "dev": true 1770 | }, 1771 | "minimatch": { 1772 | "version": "3.0.4", 1773 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1774 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1775 | "dev": true, 1776 | "requires": { 1777 | "brace-expansion": "^1.1.7" 1778 | } 1779 | }, 1780 | "minimist": { 1781 | "version": "0.0.8", 1782 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1783 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 1784 | "dev": true 1785 | }, 1786 | "mkdirp": { 1787 | "version": "0.5.5", 1788 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 1789 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 1790 | "dev": true, 1791 | "requires": { 1792 | "minimist": "^1.2.5" 1793 | }, 1794 | "dependencies": { 1795 | "minimist": { 1796 | "version": "1.2.5", 1797 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1798 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1799 | "dev": true 1800 | } 1801 | } 1802 | }, 1803 | "mocha": { 1804 | "version": "5.2.0", 1805 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", 1806 | "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", 1807 | "dev": true, 1808 | "requires": { 1809 | "browser-stdout": "1.3.1", 1810 | "commander": "2.15.1", 1811 | "debug": "3.1.0", 1812 | "diff": "3.5.0", 1813 | "escape-string-regexp": "1.0.5", 1814 | "glob": "7.1.2", 1815 | "growl": "1.10.5", 1816 | "he": "1.1.1", 1817 | "minimatch": "3.0.4", 1818 | "mkdirp": "0.5.1", 1819 | "supports-color": "5.4.0" 1820 | }, 1821 | "dependencies": { 1822 | "diff": { 1823 | "version": "3.5.0", 1824 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 1825 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 1826 | "dev": true 1827 | }, 1828 | "glob": { 1829 | "version": "7.1.2", 1830 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 1831 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 1832 | "dev": true, 1833 | "requires": { 1834 | "fs.realpath": "^1.0.0", 1835 | "inflight": "^1.0.4", 1836 | "inherits": "2", 1837 | "minimatch": "^3.0.4", 1838 | "once": "^1.3.0", 1839 | "path-is-absolute": "^1.0.0" 1840 | } 1841 | }, 1842 | "minimatch": { 1843 | "version": "3.0.4", 1844 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1845 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1846 | "dev": true, 1847 | "requires": { 1848 | "brace-expansion": "^1.1.7" 1849 | } 1850 | }, 1851 | "mkdirp": { 1852 | "version": "0.5.1", 1853 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1854 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1855 | "dev": true, 1856 | "requires": { 1857 | "minimist": "0.0.8" 1858 | } 1859 | } 1860 | } 1861 | }, 1862 | "mongodb": { 1863 | "version": "3.7.0", 1864 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.0.tgz", 1865 | "integrity": "sha512-JOAYjT9WYeRFkIP6XtDidAr3qvpfLRJhT2iokRWWH0tgqCQr9kmSfOJBZ3Ry0E5A3EqKxVPVhN3MV8Gn03o7pA==", 1866 | "requires": { 1867 | "bl": "^2.2.1", 1868 | "bson": "^1.1.4", 1869 | "denque": "^1.4.1", 1870 | "optional-require": "^1.0.3", 1871 | "safe-buffer": "^5.1.2", 1872 | "saslprep": "^1.0.0" 1873 | } 1874 | }, 1875 | "ms": { 1876 | "version": "2.0.0", 1877 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1878 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1879 | "dev": true 1880 | }, 1881 | "mute-stream": { 1882 | "version": "0.0.7", 1883 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 1884 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", 1885 | "dev": true 1886 | }, 1887 | "natural-compare": { 1888 | "version": "1.4.0", 1889 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1890 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1891 | "dev": true 1892 | }, 1893 | "nise": { 1894 | "version": "1.5.2", 1895 | "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz", 1896 | "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==", 1897 | "dev": true, 1898 | "requires": { 1899 | "@sinonjs/formatio": "^3.2.1", 1900 | "@sinonjs/text-encoding": "^0.7.1", 1901 | "just-extend": "^4.0.2", 1902 | "lolex": "^4.1.0", 1903 | "path-to-regexp": "^1.7.0" 1904 | } 1905 | }, 1906 | "node-preload": { 1907 | "version": "0.2.1", 1908 | "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", 1909 | "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", 1910 | "dev": true, 1911 | "requires": { 1912 | "process-on-spawn": "^1.0.0" 1913 | } 1914 | }, 1915 | "nyc": { 1916 | "version": "15.0.1", 1917 | "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.0.1.tgz", 1918 | "integrity": "sha512-n0MBXYBYRqa67IVt62qW1r/d9UH/Qtr7SF1w/nQLJ9KxvWF6b2xCHImRAixHN9tnMMYHC2P14uo6KddNGwMgGg==", 1919 | "dev": true, 1920 | "requires": { 1921 | "@istanbuljs/load-nyc-config": "^1.0.0", 1922 | "@istanbuljs/schema": "^0.1.2", 1923 | "caching-transform": "^4.0.0", 1924 | "convert-source-map": "^1.7.0", 1925 | "decamelize": "^1.2.0", 1926 | "find-cache-dir": "^3.2.0", 1927 | "find-up": "^4.1.0", 1928 | "foreground-child": "^2.0.0", 1929 | "glob": "^7.1.6", 1930 | "istanbul-lib-coverage": "^3.0.0", 1931 | "istanbul-lib-hook": "^3.0.0", 1932 | "istanbul-lib-instrument": "^4.0.0", 1933 | "istanbul-lib-processinfo": "^2.0.2", 1934 | "istanbul-lib-report": "^3.0.0", 1935 | "istanbul-lib-source-maps": "^4.0.0", 1936 | "istanbul-reports": "^3.0.2", 1937 | "make-dir": "^3.0.0", 1938 | "node-preload": "^0.2.1", 1939 | "p-map": "^3.0.0", 1940 | "process-on-spawn": "^1.0.0", 1941 | "resolve-from": "^5.0.0", 1942 | "rimraf": "^3.0.0", 1943 | "signal-exit": "^3.0.2", 1944 | "spawn-wrap": "^2.0.0", 1945 | "test-exclude": "^6.0.0", 1946 | "yargs": "^15.0.2" 1947 | }, 1948 | "dependencies": { 1949 | "resolve-from": { 1950 | "version": "5.0.0", 1951 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", 1952 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", 1953 | "dev": true 1954 | }, 1955 | "rimraf": { 1956 | "version": "3.0.2", 1957 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1958 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1959 | "dev": true, 1960 | "requires": { 1961 | "glob": "^7.1.3" 1962 | } 1963 | } 1964 | } 1965 | }, 1966 | "object-assign": { 1967 | "version": "4.1.1", 1968 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1969 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 1970 | "dev": true 1971 | }, 1972 | "once": { 1973 | "version": "1.4.0", 1974 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1975 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1976 | "dev": true, 1977 | "requires": { 1978 | "wrappy": "1" 1979 | } 1980 | }, 1981 | "onetime": { 1982 | "version": "2.0.1", 1983 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 1984 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 1985 | "dev": true, 1986 | "requires": { 1987 | "mimic-fn": "^1.0.0" 1988 | } 1989 | }, 1990 | "optional-require": { 1991 | "version": "1.1.7", 1992 | "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.7.tgz", 1993 | "integrity": "sha512-cIeRZocXsZnZYn+SevbtSqNlLbeoS4mLzuNn4fvXRMDRNhTGg0sxuKXl0FnZCtnew85LorNxIbZp5OeliILhMw==", 1994 | "requires": { 1995 | "require-at": "^1.0.6" 1996 | } 1997 | }, 1998 | "optionator": { 1999 | "version": "0.8.3", 2000 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", 2001 | "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", 2002 | "dev": true, 2003 | "requires": { 2004 | "deep-is": "~0.1.3", 2005 | "fast-levenshtein": "~2.0.6", 2006 | "levn": "~0.3.0", 2007 | "prelude-ls": "~1.1.2", 2008 | "type-check": "~0.3.2", 2009 | "word-wrap": "~1.2.3" 2010 | } 2011 | }, 2012 | "os-tmpdir": { 2013 | "version": "1.0.2", 2014 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 2015 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 2016 | "dev": true 2017 | }, 2018 | "p-limit": { 2019 | "version": "2.3.0", 2020 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 2021 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 2022 | "dev": true, 2023 | "requires": { 2024 | "p-try": "^2.0.0" 2025 | } 2026 | }, 2027 | "p-locate": { 2028 | "version": "4.1.0", 2029 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 2030 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 2031 | "dev": true, 2032 | "requires": { 2033 | "p-limit": "^2.2.0" 2034 | } 2035 | }, 2036 | "p-map": { 2037 | "version": "3.0.0", 2038 | "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", 2039 | "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", 2040 | "dev": true, 2041 | "requires": { 2042 | "aggregate-error": "^3.0.0" 2043 | } 2044 | }, 2045 | "p-try": { 2046 | "version": "2.2.0", 2047 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 2048 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 2049 | "dev": true 2050 | }, 2051 | "package-hash": { 2052 | "version": "4.0.0", 2053 | "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", 2054 | "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", 2055 | "dev": true, 2056 | "requires": { 2057 | "graceful-fs": "^4.1.15", 2058 | "hasha": "^5.0.0", 2059 | "lodash.flattendeep": "^4.4.0", 2060 | "release-zalgo": "^1.0.0" 2061 | } 2062 | }, 2063 | "path-exists": { 2064 | "version": "4.0.0", 2065 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 2066 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 2067 | "dev": true 2068 | }, 2069 | "path-is-absolute": { 2070 | "version": "1.0.1", 2071 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2072 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 2073 | "dev": true 2074 | }, 2075 | "path-is-inside": { 2076 | "version": "1.0.2", 2077 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 2078 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 2079 | "dev": true 2080 | }, 2081 | "path-key": { 2082 | "version": "3.1.1", 2083 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 2084 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 2085 | "dev": true 2086 | }, 2087 | "path-parse": { 2088 | "version": "1.0.7", 2089 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 2090 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 2091 | "dev": true 2092 | }, 2093 | "path-to-regexp": { 2094 | "version": "1.8.0", 2095 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", 2096 | "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", 2097 | "dev": true, 2098 | "requires": { 2099 | "isarray": "0.0.1" 2100 | } 2101 | }, 2102 | "pkg-dir": { 2103 | "version": "4.2.0", 2104 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 2105 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 2106 | "dev": true, 2107 | "requires": { 2108 | "find-up": "^4.0.0" 2109 | } 2110 | }, 2111 | "pluralize": { 2112 | "version": "7.0.0", 2113 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", 2114 | "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", 2115 | "dev": true 2116 | }, 2117 | "prelude-ls": { 2118 | "version": "1.1.2", 2119 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 2120 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 2121 | "dev": true 2122 | }, 2123 | "process-nextick-args": { 2124 | "version": "2.0.1", 2125 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 2126 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 2127 | }, 2128 | "process-on-spawn": { 2129 | "version": "1.0.0", 2130 | "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", 2131 | "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", 2132 | "dev": true, 2133 | "requires": { 2134 | "fromentries": "^1.2.0" 2135 | } 2136 | }, 2137 | "progress": { 2138 | "version": "2.0.3", 2139 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 2140 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 2141 | "dev": true 2142 | }, 2143 | "pseudomap": { 2144 | "version": "1.0.2", 2145 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 2146 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", 2147 | "dev": true 2148 | }, 2149 | "readable-stream": { 2150 | "version": "1.1.14", 2151 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 2152 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 2153 | "dev": true, 2154 | "requires": { 2155 | "core-util-is": "~1.0.0", 2156 | "inherits": "~2.0.1", 2157 | "isarray": "0.0.1", 2158 | "string_decoder": "~0.10.x" 2159 | } 2160 | }, 2161 | "regexpp": { 2162 | "version": "1.1.0", 2163 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", 2164 | "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", 2165 | "dev": true 2166 | }, 2167 | "release-zalgo": { 2168 | "version": "1.0.0", 2169 | "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", 2170 | "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", 2171 | "dev": true, 2172 | "requires": { 2173 | "es6-error": "^4.0.1" 2174 | } 2175 | }, 2176 | "require-at": { 2177 | "version": "1.0.6", 2178 | "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", 2179 | "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" 2180 | }, 2181 | "require-directory": { 2182 | "version": "2.1.1", 2183 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 2184 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 2185 | "dev": true 2186 | }, 2187 | "require-main-filename": { 2188 | "version": "2.0.0", 2189 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 2190 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 2191 | "dev": true 2192 | }, 2193 | "require-uncached": { 2194 | "version": "1.0.3", 2195 | "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", 2196 | "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", 2197 | "dev": true, 2198 | "requires": { 2199 | "caller-path": "^0.1.0", 2200 | "resolve-from": "^1.0.0" 2201 | }, 2202 | "dependencies": { 2203 | "resolve-from": { 2204 | "version": "1.0.1", 2205 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", 2206 | "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", 2207 | "dev": true 2208 | } 2209 | } 2210 | }, 2211 | "resolve": { 2212 | "version": "1.17.0", 2213 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", 2214 | "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", 2215 | "dev": true, 2216 | "requires": { 2217 | "path-parse": "^1.0.6" 2218 | } 2219 | }, 2220 | "restore-cursor": { 2221 | "version": "2.0.0", 2222 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 2223 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 2224 | "dev": true, 2225 | "requires": { 2226 | "onetime": "^2.0.0", 2227 | "signal-exit": "^3.0.2" 2228 | } 2229 | }, 2230 | "rewire": { 2231 | "version": "4.0.1", 2232 | "resolved": "https://registry.npmjs.org/rewire/-/rewire-4.0.1.tgz", 2233 | "integrity": "sha512-+7RQ/BYwTieHVXetpKhT11UbfF6v1kGhKFrtZN7UDL2PybMsSt/rpLWeEUGF5Ndsl1D5BxiCB14VDJyoX+noYw==", 2234 | "dev": true, 2235 | "requires": { 2236 | "eslint": "^4.19.1" 2237 | } 2238 | }, 2239 | "rimraf": { 2240 | "version": "2.6.3", 2241 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", 2242 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", 2243 | "dev": true, 2244 | "requires": { 2245 | "glob": "^7.1.3" 2246 | } 2247 | }, 2248 | "run-async": { 2249 | "version": "2.3.0", 2250 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 2251 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 2252 | "dev": true, 2253 | "requires": { 2254 | "is-promise": "^2.1.0" 2255 | } 2256 | }, 2257 | "rx-lite": { 2258 | "version": "4.0.8", 2259 | "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", 2260 | "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", 2261 | "dev": true 2262 | }, 2263 | "rx-lite-aggregates": { 2264 | "version": "4.0.8", 2265 | "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", 2266 | "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", 2267 | "dev": true, 2268 | "requires": { 2269 | "rx-lite": "*" 2270 | } 2271 | }, 2272 | "safe-buffer": { 2273 | "version": "5.2.1", 2274 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2275 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 2276 | }, 2277 | "safer-buffer": { 2278 | "version": "2.1.2", 2279 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2280 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 2281 | "dev": true 2282 | }, 2283 | "saslprep": { 2284 | "version": "1.0.3", 2285 | "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", 2286 | "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", 2287 | "optional": true, 2288 | "requires": { 2289 | "sparse-bitfield": "^3.0.3" 2290 | } 2291 | }, 2292 | "semver": { 2293 | "version": "5.7.1", 2294 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 2295 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 2296 | "dev": true 2297 | }, 2298 | "set-blocking": { 2299 | "version": "2.0.0", 2300 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 2301 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 2302 | "dev": true 2303 | }, 2304 | "shebang-command": { 2305 | "version": "1.2.0", 2306 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 2307 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 2308 | "dev": true, 2309 | "requires": { 2310 | "shebang-regex": "^1.0.0" 2311 | } 2312 | }, 2313 | "shebang-regex": { 2314 | "version": "1.0.0", 2315 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 2316 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 2317 | "dev": true 2318 | }, 2319 | "shelljs": { 2320 | "version": "0.3.0", 2321 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", 2322 | "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", 2323 | "dev": true 2324 | }, 2325 | "signal-exit": { 2326 | "version": "3.0.2", 2327 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 2328 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 2329 | "dev": true 2330 | }, 2331 | "sinon": { 2332 | "version": "7.5.0", 2333 | "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", 2334 | "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", 2335 | "dev": true, 2336 | "requires": { 2337 | "@sinonjs/commons": "^1.4.0", 2338 | "@sinonjs/formatio": "^3.2.1", 2339 | "@sinonjs/samsam": "^3.3.3", 2340 | "diff": "^3.5.0", 2341 | "lolex": "^4.2.0", 2342 | "nise": "^1.5.2", 2343 | "supports-color": "^5.5.0" 2344 | }, 2345 | "dependencies": { 2346 | "supports-color": { 2347 | "version": "5.5.0", 2348 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 2349 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 2350 | "dev": true, 2351 | "requires": { 2352 | "has-flag": "^3.0.0" 2353 | } 2354 | } 2355 | } 2356 | }, 2357 | "slice-ansi": { 2358 | "version": "1.0.0", 2359 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", 2360 | "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", 2361 | "dev": true, 2362 | "requires": { 2363 | "is-fullwidth-code-point": "^2.0.0" 2364 | } 2365 | }, 2366 | "source-map": { 2367 | "version": "0.5.7", 2368 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 2369 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 2370 | "dev": true 2371 | }, 2372 | "sparse-bitfield": { 2373 | "version": "3.0.3", 2374 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", 2375 | "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", 2376 | "optional": true, 2377 | "requires": { 2378 | "memory-pager": "^1.0.2" 2379 | } 2380 | }, 2381 | "spawn-wrap": { 2382 | "version": "2.0.0", 2383 | "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", 2384 | "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", 2385 | "dev": true, 2386 | "requires": { 2387 | "foreground-child": "^2.0.0", 2388 | "is-windows": "^1.0.2", 2389 | "make-dir": "^3.0.0", 2390 | "rimraf": "^3.0.0", 2391 | "signal-exit": "^3.0.2", 2392 | "which": "^2.0.1" 2393 | }, 2394 | "dependencies": { 2395 | "rimraf": { 2396 | "version": "3.0.2", 2397 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2398 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2399 | "dev": true, 2400 | "requires": { 2401 | "glob": "^7.1.3" 2402 | } 2403 | }, 2404 | "which": { 2405 | "version": "2.0.2", 2406 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2407 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2408 | "dev": true, 2409 | "requires": { 2410 | "isexe": "^2.0.0" 2411 | } 2412 | } 2413 | } 2414 | }, 2415 | "sprintf-js": { 2416 | "version": "1.0.3", 2417 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2418 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 2419 | "dev": true 2420 | }, 2421 | "string-width": { 2422 | "version": "2.1.1", 2423 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 2424 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 2425 | "dev": true, 2426 | "requires": { 2427 | "is-fullwidth-code-point": "^2.0.0", 2428 | "strip-ansi": "^4.0.0" 2429 | } 2430 | }, 2431 | "string_decoder": { 2432 | "version": "0.10.31", 2433 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 2434 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", 2435 | "dev": true 2436 | }, 2437 | "strip-ansi": { 2438 | "version": "4.0.0", 2439 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 2440 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 2441 | "dev": true, 2442 | "requires": { 2443 | "ansi-regex": "^3.0.0" 2444 | }, 2445 | "dependencies": { 2446 | "ansi-regex": { 2447 | "version": "3.0.0", 2448 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 2449 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 2450 | "dev": true 2451 | } 2452 | } 2453 | }, 2454 | "strip-bom": { 2455 | "version": "4.0.0", 2456 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", 2457 | "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", 2458 | "dev": true 2459 | }, 2460 | "strip-json-comments": { 2461 | "version": "2.0.1", 2462 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 2463 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 2464 | "dev": true 2465 | }, 2466 | "supports-color": { 2467 | "version": "5.4.0", 2468 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", 2469 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", 2470 | "dev": true, 2471 | "requires": { 2472 | "has-flag": "^3.0.0" 2473 | } 2474 | }, 2475 | "table": { 2476 | "version": "4.0.2", 2477 | "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", 2478 | "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", 2479 | "dev": true, 2480 | "requires": { 2481 | "ajv": "^5.2.3", 2482 | "ajv-keywords": "^2.1.0", 2483 | "chalk": "^2.1.0", 2484 | "lodash": "^4.17.4", 2485 | "slice-ansi": "1.0.0", 2486 | "string-width": "^2.1.1" 2487 | } 2488 | }, 2489 | "test-exclude": { 2490 | "version": "6.0.0", 2491 | "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", 2492 | "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", 2493 | "dev": true, 2494 | "requires": { 2495 | "@istanbuljs/schema": "^0.1.2", 2496 | "glob": "^7.1.4", 2497 | "minimatch": "^3.0.4" 2498 | } 2499 | }, 2500 | "text-table": { 2501 | "version": "0.2.0", 2502 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2503 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 2504 | "dev": true 2505 | }, 2506 | "through": { 2507 | "version": "2.3.8", 2508 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 2509 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 2510 | "dev": true 2511 | }, 2512 | "tmp": { 2513 | "version": "0.0.33", 2514 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 2515 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 2516 | "dev": true, 2517 | "requires": { 2518 | "os-tmpdir": "~1.0.2" 2519 | } 2520 | }, 2521 | "to-fast-properties": { 2522 | "version": "2.0.0", 2523 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 2524 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", 2525 | "dev": true 2526 | }, 2527 | "twostep": { 2528 | "version": "0.4.2", 2529 | "resolved": "https://registry.npmjs.org/twostep/-/twostep-0.4.2.tgz", 2530 | "integrity": "sha1-hLxQh6hxV00ev3vjB54D4SLUFbY=" 2531 | }, 2532 | "type-check": { 2533 | "version": "0.3.2", 2534 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 2535 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 2536 | "dev": true, 2537 | "requires": { 2538 | "prelude-ls": "~1.1.2" 2539 | } 2540 | }, 2541 | "type-detect": { 2542 | "version": "4.0.8", 2543 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 2544 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 2545 | "dev": true 2546 | }, 2547 | "type-fest": { 2548 | "version": "0.8.1", 2549 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", 2550 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", 2551 | "dev": true 2552 | }, 2553 | "typedarray": { 2554 | "version": "0.0.6", 2555 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 2556 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 2557 | "dev": true 2558 | }, 2559 | "typedarray-to-buffer": { 2560 | "version": "3.1.5", 2561 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 2562 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 2563 | "dev": true, 2564 | "requires": { 2565 | "is-typedarray": "^1.0.0" 2566 | } 2567 | }, 2568 | "underscore": { 2569 | "version": "1.12.1", 2570 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", 2571 | "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" 2572 | }, 2573 | "util-deprecate": { 2574 | "version": "1.0.2", 2575 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2576 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 2577 | }, 2578 | "uuid": { 2579 | "version": "3.3.3", 2580 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", 2581 | "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", 2582 | "dev": true 2583 | }, 2584 | "which": { 2585 | "version": "1.3.1", 2586 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 2587 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 2588 | "dev": true, 2589 | "requires": { 2590 | "isexe": "^2.0.0" 2591 | } 2592 | }, 2593 | "which-module": { 2594 | "version": "2.0.0", 2595 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 2596 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 2597 | "dev": true 2598 | }, 2599 | "word-wrap": { 2600 | "version": "1.2.3", 2601 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 2602 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 2603 | "dev": true 2604 | }, 2605 | "wrap-ansi": { 2606 | "version": "6.2.0", 2607 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 2608 | "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 2609 | "dev": true, 2610 | "requires": { 2611 | "ansi-styles": "^4.0.0", 2612 | "string-width": "^4.1.0", 2613 | "strip-ansi": "^6.0.0" 2614 | }, 2615 | "dependencies": { 2616 | "ansi-regex": { 2617 | "version": "5.0.0", 2618 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 2619 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 2620 | "dev": true 2621 | }, 2622 | "ansi-styles": { 2623 | "version": "4.2.1", 2624 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 2625 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 2626 | "dev": true, 2627 | "requires": { 2628 | "@types/color-name": "^1.1.1", 2629 | "color-convert": "^2.0.1" 2630 | } 2631 | }, 2632 | "color-convert": { 2633 | "version": "2.0.1", 2634 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 2635 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 2636 | "dev": true, 2637 | "requires": { 2638 | "color-name": "~1.1.4" 2639 | } 2640 | }, 2641 | "color-name": { 2642 | "version": "1.1.4", 2643 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 2644 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 2645 | "dev": true 2646 | }, 2647 | "is-fullwidth-code-point": { 2648 | "version": "3.0.0", 2649 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2650 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2651 | "dev": true 2652 | }, 2653 | "string-width": { 2654 | "version": "4.2.0", 2655 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 2656 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 2657 | "dev": true, 2658 | "requires": { 2659 | "emoji-regex": "^8.0.0", 2660 | "is-fullwidth-code-point": "^3.0.0", 2661 | "strip-ansi": "^6.0.0" 2662 | } 2663 | }, 2664 | "strip-ansi": { 2665 | "version": "6.0.0", 2666 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2667 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2668 | "dev": true, 2669 | "requires": { 2670 | "ansi-regex": "^5.0.0" 2671 | } 2672 | } 2673 | } 2674 | }, 2675 | "wrappy": { 2676 | "version": "1.0.2", 2677 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2678 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2679 | "dev": true 2680 | }, 2681 | "write": { 2682 | "version": "0.2.1", 2683 | "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", 2684 | "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", 2685 | "dev": true, 2686 | "requires": { 2687 | "mkdirp": "^0.5.1" 2688 | } 2689 | }, 2690 | "write-file-atomic": { 2691 | "version": "3.0.3", 2692 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", 2693 | "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", 2694 | "dev": true, 2695 | "requires": { 2696 | "imurmurhash": "^0.1.4", 2697 | "is-typedarray": "^1.0.0", 2698 | "signal-exit": "^3.0.2", 2699 | "typedarray-to-buffer": "^3.1.5" 2700 | } 2701 | }, 2702 | "y18n": { 2703 | "version": "4.0.1", 2704 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", 2705 | "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", 2706 | "dev": true 2707 | }, 2708 | "yallist": { 2709 | "version": "2.1.2", 2710 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 2711 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", 2712 | "dev": true 2713 | }, 2714 | "yargs": { 2715 | "version": "15.3.1", 2716 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", 2717 | "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", 2718 | "dev": true, 2719 | "requires": { 2720 | "cliui": "^6.0.0", 2721 | "decamelize": "^1.2.0", 2722 | "find-up": "^4.1.0", 2723 | "get-caller-file": "^2.0.1", 2724 | "require-directory": "^2.1.1", 2725 | "require-main-filename": "^2.0.0", 2726 | "set-blocking": "^2.0.0", 2727 | "string-width": "^4.2.0", 2728 | "which-module": "^2.0.0", 2729 | "y18n": "^4.0.0", 2730 | "yargs-parser": "^18.1.1" 2731 | }, 2732 | "dependencies": { 2733 | "ansi-regex": { 2734 | "version": "5.0.0", 2735 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 2736 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 2737 | "dev": true 2738 | }, 2739 | "is-fullwidth-code-point": { 2740 | "version": "3.0.0", 2741 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2742 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2743 | "dev": true 2744 | }, 2745 | "string-width": { 2746 | "version": "4.2.0", 2747 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 2748 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 2749 | "dev": true, 2750 | "requires": { 2751 | "emoji-regex": "^8.0.0", 2752 | "is-fullwidth-code-point": "^3.0.0", 2753 | "strip-ansi": "^6.0.0" 2754 | } 2755 | }, 2756 | "strip-ansi": { 2757 | "version": "6.0.0", 2758 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2759 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2760 | "dev": true, 2761 | "requires": { 2762 | "ansi-regex": "^5.0.0" 2763 | } 2764 | } 2765 | } 2766 | }, 2767 | "yargs-parser": { 2768 | "version": "18.1.3", 2769 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", 2770 | "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", 2771 | "dev": true, 2772 | "requires": { 2773 | "camelcase": "^5.0.0", 2774 | "decamelize": "^1.2.0" 2775 | } 2776 | } 2777 | } 2778 | } 2779 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rate-limit-mongo", 3 | "description": "Provides a Mongo store for the express-rate-limit middleware.", 4 | "version": "2.3.2", 5 | "author": "2do2go team ", 6 | "license": "MIT", 7 | "main": "lib/index.js", 8 | "repository": { 9 | "type": "git", 10 | "url": "git@github.com:2do2go/rate-limit-mongo.git" 11 | }, 12 | "keywords": [ 13 | "express-rate-limit", 14 | "express", 15 | "rate", 16 | "limit", 17 | "ratelimit", 18 | "rate-limit", 19 | "security", 20 | "brute", 21 | "force", 22 | "bruteforce", 23 | "brute-force", 24 | "attack", 25 | "mongo", 26 | "mongodb" 27 | ], 28 | "dependencies": { 29 | "mongodb": "^3.6.7", 30 | "twostep": "0.4.2", 31 | "underscore": "1.12.1" 32 | }, 33 | "devDependencies": { 34 | "expect.js": "0.3.1", 35 | "jshint": "2.10.3", 36 | "mocha": "5.2.0", 37 | "nyc": "15.0.1", 38 | "rewire": "4.0.1", 39 | "sinon": "7.5.0" 40 | }, 41 | "scripts": { 42 | "lint": "jshint ./", 43 | "test": "mocha --reporter spec --bail --timeout 10000 --recursive", 44 | "makeCodeCoverageDetailReport": "nyc --all --exclude migrations --exclude coverage --exclude test --reporter lcov --reporter html npm test -- --reporter dot && echo \"*** Code coverage report done, checkout ./coverage dir\"", 45 | "makeCodeCoverageSummaryReport": "nyc --all --exclude migrations --exclude coverage --exclude test --reporter text-summary npm test -- --reporter dot" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/mongoStore/_createCollection/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var sinon = require('sinon'); 4 | 5 | exports.getTestData = function() { 6 | return { 7 | mongoStoreContext: { 8 | dbOptions: { 9 | uri: 'testUri/testDbName', 10 | collectionName: 'testCollectionName' 11 | } 12 | }, 13 | db: { 14 | collectionResult: 'testCollection' 15 | } 16 | }; 17 | }; 18 | 19 | exports.getMocks = function(testData) { 20 | var dbCollectionMock = sinon.stub().returns( 21 | testData.db.collectionResult 22 | ); 23 | 24 | var clientDbMock = sinon.stub().returns({ 25 | collection: dbCollectionMock 26 | }); 27 | 28 | var mongoClientConnectResult = { 29 | db: clientDbMock 30 | }; 31 | 32 | return { 33 | MongoClient: { 34 | connect: sinon.stub().callsArgWithAsync( 35 | 2, null, mongoClientConnectResult 36 | ) 37 | }, 38 | _dynamic: { 39 | db: { 40 | collection: dbCollectionMock 41 | }, 42 | client: { 43 | db: clientDbMock 44 | } 45 | } 46 | }; 47 | }; 48 | -------------------------------------------------------------------------------- /test/mongoStore/_createCollection/withConnectionOptions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoClient.prototype._createCollection ' + 12 | 'with connection options'; 13 | describe(describeTitle, function() { 14 | var testData = testUtils.getTestData(); 15 | testData.mongoStoreContext.dbOptions.user = 'testUser'; 16 | testData.mongoStoreContext.dbOptions.password = 'testPassword'; 17 | testData.mongoStoreContext.dbOptions.authSource = 'testAuthSource'; 18 | testData.mongoStoreContext.connectionOptions = { 19 | useUnifiedTopology: false, 20 | ssl: true, 21 | sslCA: Buffer.alloc(5) 22 | }; 23 | 24 | var mocks = testUtils.getMocks(testData); 25 | 26 | var revertMocks; 27 | 28 | before(function() { 29 | revertMocks = MongoStore.__set__( 30 | _(mocks).omit('_dynamic') 31 | ); 32 | }); 33 | 34 | it('should set collection to mongoStore context', function(done) { 35 | Steppy( 36 | function() { 37 | MongoStore.prototype._createCollection.call( 38 | testData.mongoStoreContext, 39 | this.slot() 40 | ); 41 | }, 42 | function() { 43 | expect(testData.mongoStoreContext).keys('collection'); 44 | expect( 45 | testData.mongoStoreContext.collection 46 | ).eql(testData.db.collectionResult); 47 | 48 | this.pass(null); 49 | }, 50 | done 51 | ); 52 | }); 53 | 54 | it('MongoClient.connect should be called with uri and options', function() { 55 | expect(mocks.MongoClient.connect.callCount).eql(1); 56 | 57 | var MongoClientConnectArgs = mocks.MongoClient.connect.args[0]; 58 | 59 | expect( 60 | _(MongoClientConnectArgs).initial() 61 | ).eql([ 62 | testData.mongoStoreContext.dbOptions.uri, 63 | { 64 | useNewUrlParser: true, 65 | useUnifiedTopology: false, 66 | authSource: testData.mongoStoreContext.dbOptions.authSource, 67 | auth: { 68 | user: testData.mongoStoreContext.dbOptions.user, 69 | password: testData.mongoStoreContext.dbOptions.password 70 | }, 71 | ssl: testData.mongoStoreContext.connectionOptions.ssl, 72 | sslCA: testData.mongoStoreContext.connectionOptions.sslCA 73 | } 74 | ]); 75 | 76 | expect( 77 | _(MongoClientConnectArgs).last() 78 | ).a('function'); 79 | }); 80 | 81 | it('client.db should be called', function() { 82 | expect(mocks._dynamic.client.db.callCount).eql(1); 83 | 84 | var clientDbArgs = mocks._dynamic.client.db.args[0]; 85 | 86 | expect(clientDbArgs).eql([]); 87 | }); 88 | 89 | it('db.collection should be called with collection name', function() { 90 | expect(mocks._dynamic.db.collection.callCount).eql(1); 91 | 92 | var dbCollectionArgs = mocks._dynamic.db.collection.args[0]; 93 | 94 | expect(dbCollectionArgs).eql([ 95 | testData.mongoStoreContext.dbOptions.collectionName 96 | ]); 97 | }); 98 | 99 | after(function() { 100 | revertMocks(); 101 | }); 102 | }); 103 | -------------------------------------------------------------------------------- /test/mongoStore/_createCollection/withSuitableParams.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoClient.prototype._createCollection ' + 12 | 'with suitable params'; 13 | describe(describeTitle, function() { 14 | var testData = testUtils.getTestData(); 15 | 16 | var mocks = testUtils.getMocks(testData); 17 | 18 | var revertMocks; 19 | 20 | before(function() { 21 | revertMocks = MongoStore.__set__( 22 | _(mocks).omit('_dynamic') 23 | ); 24 | }); 25 | 26 | it('should set collection to mongoStore context', function(done) { 27 | Steppy( 28 | function() { 29 | MongoStore.prototype._createCollection.call( 30 | testData.mongoStoreContext, 31 | this.slot() 32 | ); 33 | }, 34 | function() { 35 | expect(testData.mongoStoreContext).keys('collection'); 36 | expect( 37 | testData.mongoStoreContext.collection 38 | ).eql(testData.db.collectionResult); 39 | 40 | this.pass(null); 41 | }, 42 | done 43 | ); 44 | }); 45 | 46 | it('MongoClient.connect should be called with uri and options', function() { 47 | expect(mocks._dynamic.db.collection.callCount).eql(1); 48 | 49 | var MongoClientConnectArgs = mocks.MongoClient.connect.args[0]; 50 | 51 | expect( 52 | _(MongoClientConnectArgs).initial() 53 | ).eql([ 54 | testData.mongoStoreContext.dbOptions.uri, 55 | { 56 | useNewUrlParser: true, 57 | useUnifiedTopology: true 58 | } 59 | ]); 60 | 61 | expect( 62 | _(MongoClientConnectArgs).last() 63 | ).a('function'); 64 | }); 65 | 66 | it('client.db should be called', function() { 67 | expect(mocks._dynamic.client.db.callCount).eql(1); 68 | 69 | var clientDbArgs = mocks._dynamic.client.db.args[0]; 70 | 71 | expect(clientDbArgs).eql([]); 72 | }); 73 | 74 | it('db.collection should be called with collection name', function() { 75 | expect(mocks._dynamic.db.collection.callCount).eql(1); 76 | 77 | var dbCollectionArgs = mocks._dynamic.db.collection.args[0]; 78 | 79 | expect(dbCollectionArgs).eql([ 80 | testData.mongoStoreContext.dbOptions.collectionName 81 | ]); 82 | }); 83 | 84 | after(function() { 85 | revertMocks(); 86 | }); 87 | }); 88 | -------------------------------------------------------------------------------- /test/mongoStore/_createCollection/withUserAndPassword.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoClient.prototype._createCollection ' + 12 | 'with user and password'; 13 | describe(describeTitle, function() { 14 | var testData = testUtils.getTestData(); 15 | testData.mongoStoreContext.dbOptions.user = 'testUser'; 16 | testData.mongoStoreContext.dbOptions.password = 'testPassword'; 17 | 18 | var mocks = testUtils.getMocks(testData); 19 | 20 | var revertMocks; 21 | 22 | before(function() { 23 | revertMocks = MongoStore.__set__( 24 | _(mocks).omit('_dynamic') 25 | ); 26 | }); 27 | 28 | it('should set collection to mongoStore context', function(done) { 29 | Steppy( 30 | function() { 31 | MongoStore.prototype._createCollection.call( 32 | testData.mongoStoreContext, 33 | this.slot() 34 | ); 35 | }, 36 | function() { 37 | expect(testData.mongoStoreContext).keys('collection'); 38 | expect( 39 | testData.mongoStoreContext.collection 40 | ).eql(testData.db.collectionResult); 41 | 42 | this.pass(null); 43 | }, 44 | done 45 | ); 46 | }); 47 | 48 | it('MongoClient.connect should be called with uri and options', function() { 49 | expect(mocks.MongoClient.connect.callCount).eql(1); 50 | 51 | var MongoClientConnectArgs = mocks.MongoClient.connect.args[0]; 52 | 53 | expect( 54 | _(MongoClientConnectArgs).initial() 55 | ).eql([ 56 | testData.mongoStoreContext.dbOptions.uri, 57 | { 58 | useNewUrlParser: true, 59 | useUnifiedTopology: true, 60 | authSource: 'testDbName', 61 | auth: { 62 | user: testData.mongoStoreContext.dbOptions.user, 63 | password: testData.mongoStoreContext.dbOptions.password 64 | } 65 | } 66 | ]); 67 | 68 | expect( 69 | _(MongoClientConnectArgs).last() 70 | ).a('function'); 71 | }); 72 | 73 | it('client.db should be called', function() { 74 | expect(mocks._dynamic.client.db.callCount).eql(1); 75 | 76 | var clientDbArgs = mocks._dynamic.client.db.args[0]; 77 | 78 | expect(clientDbArgs).eql([]); 79 | }); 80 | 81 | it('db.collection should be called with collection name', function() { 82 | expect(mocks._dynamic.db.collection.callCount).eql(1); 83 | 84 | var dbCollectionArgs = mocks._dynamic.db.collection.args[0]; 85 | 86 | expect(dbCollectionArgs).eql([ 87 | testData.mongoStoreContext.dbOptions.collectionName 88 | ]); 89 | }); 90 | 91 | after(function() { 92 | revertMocks(); 93 | }); 94 | }); 95 | -------------------------------------------------------------------------------- /test/mongoStore/_createCollection/withUserAndPasswordAndAuthSource.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoClient.prototype._createCollection ' + 12 | 'with user and password and authSource'; 13 | describe(describeTitle, function() { 14 | var testData = testUtils.getTestData(); 15 | testData.mongoStoreContext.dbOptions.user = 'testUser'; 16 | testData.mongoStoreContext.dbOptions.password = 'testPassword'; 17 | testData.mongoStoreContext.dbOptions.authSource = 'testAuthSource'; 18 | 19 | var mocks = testUtils.getMocks(testData); 20 | 21 | var revertMocks; 22 | 23 | before(function() { 24 | revertMocks = MongoStore.__set__( 25 | _(mocks).omit('_dynamic') 26 | ); 27 | }); 28 | 29 | it('should set collection to mongoStore context', function(done) { 30 | Steppy( 31 | function() { 32 | MongoStore.prototype._createCollection.call( 33 | testData.mongoStoreContext, 34 | this.slot() 35 | ); 36 | }, 37 | function() { 38 | expect(testData.mongoStoreContext).keys('collection'); 39 | expect( 40 | testData.mongoStoreContext.collection 41 | ).eql(testData.db.collectionResult); 42 | 43 | this.pass(null); 44 | }, 45 | done 46 | ); 47 | }); 48 | 49 | it('MongoClient.connect should be called with uri and auth info', function() { 50 | expect(mocks.MongoClient.connect.callCount).eql(1); 51 | 52 | var MongoClientConnectArgs = mocks.MongoClient.connect.args[0]; 53 | 54 | expect( 55 | _(MongoClientConnectArgs).initial() 56 | ).eql([ 57 | testData.mongoStoreContext.dbOptions.uri, 58 | { 59 | useNewUrlParser: true, 60 | useUnifiedTopology: true, 61 | authSource: testData.mongoStoreContext.dbOptions.authSource, 62 | auth: { 63 | user: testData.mongoStoreContext.dbOptions.user, 64 | password: testData.mongoStoreContext.dbOptions.password 65 | } 66 | } 67 | ]); 68 | 69 | expect( 70 | _(MongoClientConnectArgs).last() 71 | ).a('function'); 72 | }); 73 | 74 | it('client.db should be called', function() { 75 | expect(mocks._dynamic.client.db.callCount).eql(1); 76 | 77 | var clientDbArgs = mocks._dynamic.client.db.args[0]; 78 | 79 | expect(clientDbArgs).eql([]); 80 | }); 81 | 82 | it('db.collection should be called with collection name', function() { 83 | expect(mocks._dynamic.db.collection.callCount).eql(1); 84 | 85 | var dbCollectionArgs = mocks._dynamic.db.collection.args[0]; 86 | 87 | expect(dbCollectionArgs).eql([ 88 | testData.mongoStoreContext.dbOptions.collectionName 89 | ]); 90 | }); 91 | 92 | after(function() { 93 | revertMocks(); 94 | }); 95 | }); 96 | -------------------------------------------------------------------------------- /test/mongoStore/_getCollection/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var sinon = require('sinon'); 4 | 5 | exports.getMocks = function(testData) { 6 | testData = testData || {}; 7 | 8 | var collectionMock = { 9 | createIndex: sinon.stub().callsArgWithAsync( 10 | 2, testData.collectionCreateIndexError 11 | ) 12 | }; 13 | 14 | return { 15 | setImmediate: sinon.stub().callsArgWithAsync(0), 16 | _dynamic: { 17 | mongoStoreContext: { 18 | _createCollection: sinon.stub().callsFake(function(callback){ 19 | this.collection = collectionMock; 20 | callback(); 21 | }), 22 | _getCollection: sinon.stub().callsArgWithAsync(0) 23 | }, 24 | collection: collectionMock 25 | } 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /test/mongoStore/_getCollection/withCollectionCreateIndexError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype._getCollection ' + 12 | 'with collection.createIndex error'; 13 | describe(describeTitle, function() { 14 | var testData = { 15 | mongoStoreContext: { 16 | _collectionState: 'notPrepared', 17 | createTtlIndex: true 18 | }, 19 | collectionCreateIndexError: new Error('test createIndex error') 20 | }; 21 | 22 | var mocks = testUtils.getMocks(testData); 23 | 24 | var revertMocks; 25 | 26 | before(function() { 27 | revertMocks = MongoStore.__set__( 28 | _(mocks).omit('_dynamic') 29 | ); 30 | }); 31 | 32 | it('should throw error', function(done) { 33 | Steppy( 34 | function() { 35 | MongoStore.prototype._getCollection.call( 36 | _({}).extend( 37 | testData.mongoStoreContext, 38 | mocks._dynamic.mongoStoreContext 39 | ), 40 | this.slot() 41 | ); 42 | }, 43 | function(err) { 44 | expect(err).eql( 45 | testData.collectionCreateIndexError 46 | ); 47 | 48 | done(); 49 | } 50 | ); 51 | }); 52 | 53 | it('mongoStore._collectionState should be "notPrepared"', function() { 54 | expect( 55 | testData.mongoStoreContext._collectionState 56 | ).eql('notPrepared'); 57 | }); 58 | 59 | it('setImmediate should not be called', function() { 60 | expect(mocks.setImmediate.callCount).eql(0); 61 | }); 62 | 63 | it('self._getCollection should not be called', function() { 64 | expect( 65 | mocks._dynamic.mongoStoreContext._getCollection.callCount 66 | ).eql(0); 67 | }); 68 | 69 | it('_createCollection should be called', function() { 70 | expect( 71 | mocks._dynamic.mongoStoreContext._createCollection.callCount 72 | ).eql(1); 73 | 74 | var createCollectionArgs = mocks._dynamic.mongoStoreContext 75 | ._createCollection.args[0]; 76 | 77 | expect(createCollectionArgs).length(1); 78 | expect(createCollectionArgs[0]).a('function'); 79 | }); 80 | 81 | it( 82 | 'collection.createIndex should be called for setting ttl index', 83 | function() { 84 | var collectionMock = mocks._dynamic.collection; 85 | 86 | expect(collectionMock.createIndex.callCount).eql(1); 87 | 88 | var collectionCreateIndexArgs = collectionMock.createIndex.args[0]; 89 | 90 | expect( 91 | _(collectionCreateIndexArgs).initial() 92 | ).eql([ 93 | {expirationDate: 1}, 94 | {expireAfterSeconds: 0} 95 | ]); 96 | 97 | expect( 98 | _(collectionCreateIndexArgs).last() 99 | ).a('function'); 100 | } 101 | ); 102 | 103 | after(function() { 104 | revertMocks(); 105 | }); 106 | }); 107 | -------------------------------------------------------------------------------- /test/mongoStore/_getCollection/withNotPreparedCollectionStateAndCollection.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype._getCollection ' + 12 | 'with "notPrepared" collectionState and collection'; 13 | describe(describeTitle, function() { 14 | var testData = { 15 | mongoStoreContext: { 16 | _collectionState: 'notPrepared', 17 | createTtlIndex: true 18 | } 19 | }; 20 | 21 | var mocks = testUtils.getMocks(); 22 | mocks._dynamic.mongoStoreContext.collection = mocks._dynamic.collection; 23 | 24 | var revertMocks; 25 | 26 | before(function() { 27 | revertMocks = MongoStore.__set__( 28 | _(mocks).omit('_dynamic') 29 | ); 30 | }); 31 | 32 | it('should return collection', function(done) { 33 | Steppy( 34 | function() { 35 | MongoStore.prototype._getCollection.call( 36 | _({}).extend( 37 | testData.mongoStoreContext, 38 | mocks._dynamic.mongoStoreContext 39 | ), 40 | this.slot() 41 | ); 42 | }, 43 | function(err, collection) { 44 | expect(collection).eql( 45 | mocks._dynamic.mongoStoreContext.collection 46 | ); 47 | 48 | this.pass(null); 49 | }, 50 | done 51 | ); 52 | }); 53 | 54 | it('setImmediate should not be called', function() { 55 | expect(mocks.setImmediate.callCount).eql(0); 56 | }); 57 | 58 | it('self._getCollection should not be called', function() { 59 | expect( 60 | mocks._dynamic.mongoStoreContext._getCollection.callCount 61 | ).eql(0); 62 | }); 63 | 64 | it('_createCollection should not be called', function() { 65 | expect( 66 | mocks._dynamic.mongoStoreContext._createCollection.callCount 67 | ).eql(0); 68 | }); 69 | 70 | it( 71 | 'collection.createIndex should be called for setting ttl index', 72 | function() { 73 | var collectionMock = mocks._dynamic.mongoStoreContext.collection; 74 | 75 | expect(collectionMock.createIndex.callCount).eql(1); 76 | 77 | var collectionCreateIndexArgs = collectionMock.createIndex.args[0]; 78 | 79 | expect( 80 | _(collectionCreateIndexArgs).initial() 81 | ).eql([ 82 | {expirationDate: 1}, 83 | {expireAfterSeconds: 0} 84 | ]); 85 | 86 | expect( 87 | _(collectionCreateIndexArgs).last() 88 | ).a('function'); 89 | } 90 | ); 91 | 92 | after(function() { 93 | revertMocks(); 94 | }); 95 | }); 96 | -------------------------------------------------------------------------------- /test/mongoStore/_getCollection/withNotPreparedCollectionStateAndDisabledCreateTtlIndexOption.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype._getCollection ' + 12 | 'with "notPrepared" collectionState and disabled create ttl index option'; 13 | describe(describeTitle, function() { 14 | var testData = { 15 | mongoStoreContext: { 16 | _collectionState: 'notPrepared', 17 | createTtlIndex: false 18 | } 19 | }; 20 | 21 | var mocks = testUtils.getMocks(); 22 | 23 | var revertMocks; 24 | 25 | before(function() { 26 | revertMocks = MongoStore.__set__( 27 | _(mocks).omit('_dynamic') 28 | ); 29 | }); 30 | 31 | it('should return collection', function(done) { 32 | Steppy( 33 | function() { 34 | MongoStore.prototype._getCollection.call( 35 | _({}).extend( 36 | testData.mongoStoreContext, 37 | mocks._dynamic.mongoStoreContext 38 | ), 39 | this.slot() 40 | ); 41 | }, 42 | function(err, collection) { 43 | expect(collection).eql( 44 | mocks._dynamic.collection 45 | ); 46 | 47 | this.pass(null); 48 | }, 49 | done 50 | ); 51 | }); 52 | 53 | it('setImmediate should not be called', function() { 54 | expect(mocks.setImmediate.callCount).eql(0); 55 | }); 56 | 57 | it('self._getCollection should not be called', function() { 58 | expect( 59 | mocks._dynamic.mongoStoreContext._getCollection.callCount 60 | ).eql(0); 61 | }); 62 | 63 | it('_createCollection should be called', function() { 64 | expect( 65 | mocks._dynamic.mongoStoreContext._createCollection.callCount 66 | ).eql(1); 67 | 68 | var createCollectionArgs = mocks._dynamic.mongoStoreContext 69 | ._createCollection.args[0]; 70 | 71 | expect(createCollectionArgs).length(1); 72 | expect(createCollectionArgs[0]).a('function'); 73 | }); 74 | 75 | it( 76 | 'collection.createIndex should not be called', 77 | function() { 78 | expect(mocks._dynamic.collection.createIndex.callCount).eql(0); 79 | } 80 | ); 81 | 82 | after(function() { 83 | revertMocks(); 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /test/mongoStore/_getCollection/withNotPreparedCollectionStateAndWithoutCollection.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype._getCollection ' + 12 | 'with "notPrepared" collectionState and without collection'; 13 | describe(describeTitle, function() { 14 | var testData = { 15 | mongoStoreContext: { 16 | _collectionState: 'notPrepared', 17 | createTtlIndex: true 18 | } 19 | }; 20 | 21 | var mocks = testUtils.getMocks(); 22 | 23 | var revertMocks; 24 | 25 | before(function() { 26 | revertMocks = MongoStore.__set__( 27 | _(mocks).omit('_dynamic') 28 | ); 29 | }); 30 | 31 | it('should return collection', function(done) { 32 | Steppy( 33 | function() { 34 | MongoStore.prototype._getCollection.call( 35 | _({}).extend( 36 | testData.mongoStoreContext, 37 | mocks._dynamic.mongoStoreContext 38 | ), 39 | this.slot() 40 | ); 41 | }, 42 | function(err, collection) { 43 | expect(collection).eql( 44 | mocks._dynamic.collection 45 | ); 46 | 47 | this.pass(null); 48 | }, 49 | done 50 | ); 51 | }); 52 | 53 | it('setImmediate should not be called', function() { 54 | expect(mocks.setImmediate.callCount).eql(0); 55 | }); 56 | 57 | it('self._getCollection should not be called', function() { 58 | expect( 59 | mocks._dynamic.mongoStoreContext._getCollection.callCount 60 | ).eql(0); 61 | }); 62 | 63 | it('_createCollection should be called', function() { 64 | expect( 65 | mocks._dynamic.mongoStoreContext._createCollection.callCount 66 | ).eql(1); 67 | 68 | var createCollectionArgs = mocks._dynamic.mongoStoreContext 69 | ._createCollection.args[0]; 70 | 71 | expect(createCollectionArgs).length(1); 72 | expect(createCollectionArgs[0]).a('function'); 73 | }); 74 | 75 | it( 76 | 'collection.createIndex should be called for setting ttl index', 77 | function() { 78 | var collectionMock = mocks._dynamic.collection; 79 | 80 | expect(collectionMock.createIndex.callCount).eql(1); 81 | 82 | var collectionCreateIndexArgs = collectionMock.createIndex.args[0]; 83 | 84 | expect( 85 | _(collectionCreateIndexArgs).initial() 86 | ).eql([ 87 | {expirationDate: 1}, 88 | {expireAfterSeconds: 0} 89 | ]); 90 | 91 | expect( 92 | _(collectionCreateIndexArgs).last() 93 | ).a('function'); 94 | } 95 | ); 96 | 97 | after(function() { 98 | revertMocks(); 99 | }); 100 | }); 101 | -------------------------------------------------------------------------------- /test/mongoStore/_getCollection/withPrepairingCollectionState.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype._getCollection ' + 12 | 'with "prepairing" collectionState'; 13 | describe(describeTitle, function() { 14 | var testData = { 15 | mongoStoreContext: { 16 | _collectionState: 'prepairing', 17 | options: { 18 | collection: 'testCollection' 19 | } 20 | } 21 | }; 22 | 23 | var mocks = testUtils.getMocks(); 24 | 25 | var revertMocks; 26 | 27 | before(function() { 28 | revertMocks = MongoStore.__set__( 29 | _(mocks).omit('_dynamic') 30 | ); 31 | }); 32 | 33 | it('should be ok', function(done) { 34 | Steppy( 35 | function() { 36 | MongoStore.prototype._getCollection.call( 37 | _({}).extend( 38 | testData.mongoStoreContext, 39 | mocks._dynamic.mongoStoreContext 40 | ), 41 | this.slot() 42 | ); 43 | }, 44 | done 45 | ); 46 | }); 47 | 48 | it('setImmediate should be called', function() { 49 | expect(mocks.setImmediate.callCount).eql(1); 50 | 51 | var setImmediateArgs = mocks.setImmediate.args[0]; 52 | 53 | expect(setImmediateArgs).length(1); 54 | expect(setImmediateArgs[0]).a('function'); 55 | }); 56 | 57 | it('self._getCollection should be called', function() { 58 | expect( 59 | mocks._dynamic.mongoStoreContext._getCollection.callCount 60 | ).eql(1); 61 | 62 | var getCollectionArgs = mocks._dynamic.mongoStoreContext 63 | ._getCollection.args[0]; 64 | 65 | expect(getCollectionArgs).length(1); 66 | expect(getCollectionArgs[0]).a('function'); 67 | }); 68 | 69 | it('_createCollection should not be called', function() { 70 | expect( 71 | mocks._dynamic.mongoStoreContext._createCollection.callCount 72 | ).eql(0); 73 | }); 74 | 75 | it('collection.createIndex should not be called', function() { 76 | expect( 77 | mocks._dynamic.collection.createIndex.callCount 78 | ).eql(0); 79 | }); 80 | 81 | after(function() { 82 | revertMocks(); 83 | }); 84 | }); 85 | -------------------------------------------------------------------------------- /test/mongoStore/_getCollection/withPreparedCollectionState.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype._getCollection ' + 12 | 'with "prepared" collectionState'; 13 | describe(describeTitle, function() { 14 | var testData = { 15 | mongoStoreContext: { 16 | _collectionState: 'prepared', 17 | collection: 'testCollection' 18 | } 19 | }; 20 | 21 | var mocks = testUtils.getMocks(); 22 | 23 | var revertMocks; 24 | 25 | before(function() { 26 | revertMocks = MongoStore.__set__( 27 | _(mocks).omit('_dynamic') 28 | ); 29 | }); 30 | 31 | it('should return collection', function(done) { 32 | Steppy( 33 | function() { 34 | MongoStore.prototype._getCollection.call( 35 | _({}).extend( 36 | testData.mongoStoreContext, 37 | mocks._dynamic.mongoStoreContext 38 | ), 39 | this.slot() 40 | ); 41 | }, 42 | function(err, collection) { 43 | expect(collection).eql( 44 | testData.mongoStoreContext.collection 45 | ); 46 | 47 | this.pass(null); 48 | }, 49 | done 50 | ); 51 | }); 52 | 53 | it('setImmediate should not be called', function() { 54 | expect(mocks.setImmediate.callCount).eql(0); 55 | }); 56 | 57 | it('self._getCollection should not be called', function() { 58 | expect( 59 | mocks._dynamic.mongoStoreContext._getCollection.callCount 60 | ).eql(0); 61 | }); 62 | 63 | it('_createCollection should not be called', function() { 64 | expect( 65 | mocks._dynamic.mongoStoreContext._createCollection.callCount 66 | ).eql(0); 67 | }); 68 | 69 | it('collection.createIndex should not be called', function() { 70 | expect( 71 | mocks._dynamic.collection.createIndex.callCount 72 | ).eql(0); 73 | }); 74 | 75 | after(function() { 76 | revertMocks(); 77 | }); 78 | }); 79 | -------------------------------------------------------------------------------- /test/mongoStore/constructor/withSuitableParams.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var _ = require('underscore'); 5 | var MongoStore = require('../../../lib/mongoStore'); 6 | 7 | describe('MongoStore with suitable params', function() { 8 | 9 | it('should return MongoStore instance', function() { 10 | var mongoStore = new MongoStore({ 11 | uri: 'testUri', 12 | user: 'testUser', 13 | password: 'testPassword' 14 | }); 15 | 16 | expect(mongoStore.dbOptions).eql({ 17 | uri: 'testUri', 18 | collectionName: 'expressRateRecords', 19 | user: 'testUser', 20 | password: 'testPassword' 21 | }); 22 | 23 | expect(mongoStore.expireTimeMs).eql(60000); 24 | expect(mongoStore.resetExpireDateOnChange).eql(false); 25 | expect(mongoStore.errorHandler).eql(_.noop); 26 | expect(mongoStore.createTtlIndex).equal(true); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/mongoStore/constructor/withoutCollectionAndCollectionName.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var MongoStore = require('../../../lib/mongoStore'); 5 | 6 | describe('MongoStore without collection and collectionName', function() { 7 | 8 | it('should throw error', function() { 9 | expect(function() { 10 | new MongoStore({ 11 | collectionName: null 12 | }); 13 | }).throwException(function(err) { 14 | expect(err.message).eql( 15 | 'collection or collectionName and uri should be set' 16 | ); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/mongoStore/constructor/withoutCollectionAndUri.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var MongoStore = require('../../../lib/mongoStore'); 5 | 6 | describe('MongoStore without collection and collectionName', function() { 7 | 8 | it('should throw error', function() { 9 | expect(function() { 10 | new MongoStore({}); 11 | }).throwException(function(err) { 12 | expect(err.message).eql( 13 | 'collection or collectionName and uri should be set' 14 | ); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/mongoStore/decrement/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var sinon = require('sinon'); 4 | var _ = require('underscore'); 5 | 6 | exports.getTestData = function() { 7 | return { 8 | key: 'testKey', 9 | DateResult: { 10 | someKey: _.random(1, 10) 11 | }, 12 | Date: { 13 | nowResult: _.random(1, 10) 14 | }, 15 | collection: { 16 | findOneAndUpdateResult: { 17 | value: { 18 | counter: _.random(1, 10), 19 | expirationDate: _.random(1, 10) 20 | } 21 | } 22 | }, 23 | mongoStoreContext: { 24 | expireTimeMs: _.random(1, 10) 25 | } 26 | }; 27 | }; 28 | 29 | exports.getMocks = function(testData) { 30 | var dateMock = sinon.stub().callsFake(function() { 31 | _(this).extend(testData.DateResult); 32 | }); 33 | dateMock.now = sinon.stub().returns(testData.Date.nowResult); 34 | 35 | var collectionFindOneAndUpdateMock = sinon.stub().callsArgWithAsync( 36 | 3, 37 | testData.findOneAndUpdateError, 38 | testData.collection.findOneAndUpdateResult 39 | ); 40 | var collectionMock = { 41 | findOneAndUpdate: collectionFindOneAndUpdateMock 42 | }; 43 | 44 | return { 45 | Date: dateMock, 46 | _dynamic: { 47 | mongoStoreContext: { 48 | _getCollection: sinon.stub().callsArgWithAsync( 49 | 0, null, collectionMock 50 | ), 51 | errorHandler: sinon.stub().returns() 52 | }, 53 | collection: collectionMock 54 | } 55 | }; 56 | }; 57 | -------------------------------------------------------------------------------- /test/mongoStore/decrement/withFindOneAndUpdateError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype.decrement ' + 12 | 'with findOneAndUpdate error'; 13 | describe(describeTitle, function() { 14 | var testData = testUtils.getTestData(); 15 | testData.findOneAndUpdateError = new Error(); 16 | 17 | var mocks = testUtils.getMocks(testData); 18 | 19 | var revertMocks; 20 | 21 | before(function() { 22 | revertMocks = MongoStore.__set__( 23 | _(mocks).omit('_dynamic') 24 | ); 25 | }); 26 | 27 | it('should throw error in callback', function(done) { 28 | Steppy( 29 | function() { 30 | MongoStore.prototype.decrement.call( 31 | _({}).extend( 32 | testData.mongoStoreContext, 33 | mocks._dynamic.mongoStoreContext 34 | ), 35 | testData.key, 36 | this.slot() 37 | ); 38 | }, 39 | function(err) { 40 | expect(err).eql(testData.findOneAndUpdateError); 41 | 42 | done(); 43 | } 44 | ); 45 | }); 46 | 47 | it('_getCollection should be called', function() { 48 | expect( 49 | mocks._dynamic.mongoStoreContext._getCollection.callCount 50 | ).eql(1); 51 | 52 | var getCollectionArgs = mocks._dynamic.mongoStoreContext 53 | ._getCollection.args[0]; 54 | 55 | expect(getCollectionArgs).length(1); 56 | expect(getCollectionArgs[0]).a('function'); 57 | }); 58 | 59 | it('Date.now should be called', function() { 60 | expect(mocks.Date.now.callCount).eql(1); 61 | expect(mocks.Date.now.args[0]).eql([]); 62 | }); 63 | 64 | it('Date should be called to construct expirationDate', function() { 65 | expect(mocks.Date.callCount).eql(1); 66 | 67 | var dateArgs = mocks.Date.args[0]; 68 | 69 | expect(dateArgs).eql([ 70 | testData.mongoStoreContext.expireTimeMs + testData.Date.nowResult 71 | ]); 72 | }); 73 | 74 | it('Date should be called as constructor', function() { 75 | expect(mocks.Date.calledWithNew()).eql(true); 76 | }); 77 | 78 | it( 79 | 'collection.findOneAndUpdate should be called for incrementing counter', 80 | function() { 81 | expect( 82 | mocks._dynamic.collection.findOneAndUpdate.callCount 83 | ).eql(1); 84 | 85 | var findOneAndUpdateArgs = mocks._dynamic.collection 86 | .findOneAndUpdate.args[0]; 87 | 88 | expect( 89 | _(findOneAndUpdateArgs).initial() 90 | ).eql([ 91 | {_id: testData.key}, 92 | { 93 | $inc: {counter: -1}, 94 | $setOnInsert: { 95 | expirationDate: testData.DateResult 96 | } 97 | }, 98 | { 99 | upsert: true, 100 | returnDocument: 'after' 101 | } 102 | ]); 103 | 104 | expect( 105 | _(findOneAndUpdateArgs).last() 106 | ).a('function'); 107 | } 108 | ); 109 | 110 | it('errorHandler should be called with error', function() { 111 | expect( 112 | mocks._dynamic.mongoStoreContext.errorHandler.callCount 113 | ).eql(1); 114 | 115 | var errorHandlerArgs = mocks._dynamic.mongoStoreContext.errorHandler 116 | .args[0]; 117 | 118 | expect(errorHandlerArgs).eql([ 119 | testData.findOneAndUpdateError 120 | ]); 121 | }); 122 | 123 | after(function() { 124 | revertMocks(); 125 | }); 126 | }); 127 | -------------------------------------------------------------------------------- /test/mongoStore/decrement/withResetExpireDateOnCange.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype.decrement ' + 12 | 'with resetExpireDateOnChange'; 13 | describe(describeTitle, function() { 14 | var testData = testUtils.getTestData(); 15 | testData.mongoStoreContext.resetExpireDateOnChange = true; 16 | 17 | var mocks = testUtils.getMocks(testData); 18 | 19 | var revertMocks; 20 | 21 | before(function() { 22 | revertMocks = MongoStore.__set__( 23 | _(mocks).omit('_dynamic') 24 | ); 25 | }); 26 | 27 | it('should be ok', function(done) { 28 | Steppy( 29 | function() { 30 | MongoStore.prototype.decrement.call( 31 | _({}).extend( 32 | testData.mongoStoreContext, 33 | mocks._dynamic.mongoStoreContext 34 | ), 35 | testData.key, 36 | this.slot() 37 | ); 38 | }, 39 | done 40 | ); 41 | }); 42 | 43 | it('_getCollection should be called', function() { 44 | expect( 45 | mocks._dynamic.mongoStoreContext._getCollection.callCount 46 | ).eql(1); 47 | 48 | var getCollectionArgs = mocks._dynamic.mongoStoreContext 49 | ._getCollection.args[0]; 50 | 51 | expect(getCollectionArgs).length(1); 52 | expect(getCollectionArgs[0]).a('function'); 53 | }); 54 | 55 | it('Date.now should be called', function() { 56 | expect(mocks.Date.now.callCount).eql(1); 57 | expect(mocks.Date.now.args[0]).eql([]); 58 | }); 59 | 60 | it('Date should be called to construct expirationDate', function() { 61 | expect(mocks.Date.callCount).eql(1); 62 | 63 | var dateArgs = mocks.Date.args[0]; 64 | 65 | expect(dateArgs).eql([ 66 | testData.mongoStoreContext.expireTimeMs + testData.Date.nowResult 67 | ]); 68 | }); 69 | 70 | it('Date should be called as constructor', function() { 71 | expect(mocks.Date.calledWithNew()).eql(true); 72 | }); 73 | 74 | it( 75 | 'collection.findOneAndUpdate should be called for decrementing counter', 76 | function() { 77 | expect( 78 | mocks._dynamic.collection.findOneAndUpdate.callCount 79 | ).eql(1); 80 | 81 | var findOneAndUpdateArgs = mocks._dynamic.collection 82 | .findOneAndUpdate.args[0]; 83 | 84 | expect( 85 | _(findOneAndUpdateArgs).initial() 86 | ).eql([ 87 | {_id: testData.key}, 88 | { 89 | $inc: {counter: -1}, 90 | $set: { 91 | expirationDate: testData.DateResult 92 | } 93 | }, 94 | { 95 | upsert: true, 96 | returnDocument: 'after' 97 | } 98 | ]); 99 | 100 | expect( 101 | _(findOneAndUpdateArgs).last() 102 | ).a('function'); 103 | } 104 | ); 105 | 106 | it('errorHandler should not be called', function() { 107 | expect( 108 | mocks._dynamic.mongoStoreContext.errorHandler.callCount 109 | ).eql(0); 110 | }); 111 | 112 | after(function() { 113 | revertMocks(); 114 | }); 115 | }); 116 | -------------------------------------------------------------------------------- /test/mongoStore/decrement/withoutResetExpireDateOnChange.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype.decrement ' + 12 | 'without resetExpireDateOnChange'; 13 | describe(describeTitle, function() { 14 | var testData = testUtils.getTestData(); 15 | testData.mongoStoreContext.resetExpireDateOnChange = false; 16 | 17 | var mocks = testUtils.getMocks(testData); 18 | 19 | var revertMocks; 20 | 21 | before(function() { 22 | revertMocks = MongoStore.__set__( 23 | _(mocks).omit('_dynamic') 24 | ); 25 | }); 26 | 27 | it('should be ok', function(done) { 28 | Steppy( 29 | function() { 30 | MongoStore.prototype.decrement.call( 31 | _({}).extend( 32 | testData.mongoStoreContext, 33 | mocks._dynamic.mongoStoreContext 34 | ), 35 | testData.key, 36 | this.slot() 37 | ); 38 | }, 39 | done 40 | ); 41 | }); 42 | 43 | it('_getCollection should be called', function() { 44 | expect( 45 | mocks._dynamic.mongoStoreContext._getCollection.callCount 46 | ).eql(1); 47 | 48 | var getCollectionArgs = mocks._dynamic.mongoStoreContext 49 | ._getCollection.args[0]; 50 | 51 | expect(getCollectionArgs).length(1); 52 | expect(getCollectionArgs[0]).a('function'); 53 | }); 54 | 55 | it('Date.now should be called', function() { 56 | expect(mocks.Date.now.callCount).eql(1); 57 | expect(mocks.Date.now.args[0]).eql([]); 58 | }); 59 | 60 | it('Date should be called to construct expirationDate', function() { 61 | expect(mocks.Date.callCount).eql(1); 62 | 63 | var dateArgs = mocks.Date.args[0]; 64 | 65 | expect(dateArgs).eql([ 66 | testData.mongoStoreContext.expireTimeMs + testData.Date.nowResult 67 | ]); 68 | }); 69 | 70 | it('Date should be called as constructor', function() { 71 | expect(mocks.Date.calledWithNew()).eql(true); 72 | }); 73 | 74 | it( 75 | 'collection.findOneAndUpdate should be called for decrementing counter', 76 | function() { 77 | expect( 78 | mocks._dynamic.collection.findOneAndUpdate.callCount 79 | ).eql(1); 80 | 81 | var findOneAndUpdateArgs = mocks._dynamic.collection 82 | .findOneAndUpdate.args[0]; 83 | 84 | expect( 85 | _(findOneAndUpdateArgs).initial() 86 | ).eql([ 87 | {_id: testData.key}, 88 | { 89 | $inc: {counter: -1}, 90 | $setOnInsert: { 91 | expirationDate: testData.DateResult 92 | } 93 | }, 94 | { 95 | upsert: true, 96 | returnDocument: 'after' 97 | } 98 | ]); 99 | 100 | expect( 101 | _(findOneAndUpdateArgs).last() 102 | ).a('function'); 103 | } 104 | ); 105 | 106 | it('errorHandler should not be called', function() { 107 | expect( 108 | mocks._dynamic.mongoStoreContext.errorHandler.callCount 109 | ).eql(0); 110 | }); 111 | 112 | after(function() { 113 | revertMocks(); 114 | }); 115 | }); 116 | -------------------------------------------------------------------------------- /test/mongoStore/getClient/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var sinon = require('sinon'); 4 | 5 | exports.getMocks = function(testData) { 6 | testData = testData || {}; 7 | 8 | return { 9 | setImmediate: sinon.stub().callsArgWithAsync(0), 10 | _dynamic: { 11 | mongoStoreContext: { 12 | getClient: sinon.stub().callsArgWithAsync( 13 | 0, 14 | null, 15 | testData.getClientResult 16 | ) 17 | } 18 | } 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /test/mongoStore/getClient/withClient.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var _ = require('underscore'); 6 | var rewire = require('rewire'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype.getClient with client'; 12 | describe(describeTitle, function() { 13 | var testData = { 14 | mongoStoreContext: { 15 | client: {} 16 | } 17 | }; 18 | 19 | var mocks = testUtils.getMocks(); 20 | 21 | var revertMocks; 22 | 23 | before(function() { 24 | revertMocks = MongoStore.__set__( 25 | _(mocks).omit('_dynamic') 26 | ); 27 | }); 28 | 29 | it('should return client', function(done) { 30 | Steppy( 31 | function() { 32 | MongoStore.prototype.getClient.call( 33 | _({}).extend( 34 | testData.mongoStoreContext, 35 | mocks._dynamic.mongoStoreContext 36 | ), 37 | this.slot() 38 | ); 39 | }, 40 | function(err, client) { 41 | expect(client).eql( 42 | testData.mongoStoreContext.client 43 | ); 44 | 45 | this.pass(null); 46 | }, 47 | done 48 | ); 49 | }); 50 | 51 | it('setImmediate should not be called', function() { 52 | expect(mocks.setImmediate.callCount).eql(0); 53 | }); 54 | 55 | it('getClient should not be called', function() { 56 | expect( 57 | mocks._dynamic.mongoStoreContext.getClient.callCount 58 | ).eql(0); 59 | }); 60 | 61 | after(function() { 62 | revertMocks(); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /test/mongoStore/getClient/withoutClientAndWithCollection.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var _ = require('underscore'); 6 | var rewire = require('rewire'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = ( 12 | 'MongoStore.prototype.getClient without client and with collection' 13 | ); 14 | 15 | describe(describeTitle, function() { 16 | var testData = { 17 | mongoStoreContext: { 18 | collection: {} 19 | } 20 | }; 21 | 22 | var mocks = testUtils.getMocks(); 23 | 24 | var revertMocks; 25 | 26 | before(function() { 27 | revertMocks = MongoStore.__set__( 28 | _(mocks).omit('_dynamic') 29 | ); 30 | }); 31 | 32 | it('should return null', function(done) { 33 | Steppy( 34 | function() { 35 | MongoStore.prototype.getClient.call( 36 | _({}).extend( 37 | testData.mongoStoreContext, 38 | mocks._dynamic.mongoStoreContext 39 | ), 40 | this.slot() 41 | ); 42 | }, 43 | function(err, client) { 44 | expect(client).equal(null); 45 | 46 | this.pass(null); 47 | }, 48 | done 49 | ); 50 | }); 51 | 52 | it('setImmediate should not be called', function() { 53 | expect(mocks.setImmediate.callCount).eql(0); 54 | }); 55 | 56 | it('getClient should not be called', function() { 57 | expect( 58 | mocks._dynamic.mongoStoreContext.getClient.callCount 59 | ).eql(0); 60 | }); 61 | 62 | after(function() { 63 | revertMocks(); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /test/mongoStore/getClient/withoutClientAndWithoutCollection.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var _ = require('underscore'); 6 | var rewire = require('rewire'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = ( 12 | 'MongoStore.prototype.getClient without client and without collection' 13 | ); 14 | 15 | describe(describeTitle, function() { 16 | var testData = { 17 | getClientResult: {}, 18 | mongoStoreContext: { 19 | } 20 | }; 21 | 22 | var mocks = testUtils.getMocks(testData); 23 | 24 | var revertMocks; 25 | 26 | before(function() { 27 | revertMocks = MongoStore.__set__( 28 | _(mocks).omit('_dynamic') 29 | ); 30 | }); 31 | 32 | it('should return getClient call result', function(done) { 33 | Steppy( 34 | function() { 35 | MongoStore.prototype.getClient.call( 36 | _({}).extend( 37 | testData.mongoStoreContext, 38 | mocks._dynamic.mongoStoreContext 39 | ), 40 | this.slot() 41 | ); 42 | }, 43 | function(err, client) { 44 | expect(client).equal(testData.getClientResult); 45 | 46 | this.pass(null); 47 | }, 48 | done 49 | ); 50 | }); 51 | 52 | it('setImmediate should be called', function() { 53 | expect(mocks.setImmediate.callCount).eql(1); 54 | 55 | var setImmediateArgs = mocks.setImmediate.args[0]; 56 | 57 | expect(setImmediateArgs).length(1); 58 | expect(setImmediateArgs[0]).a('function'); 59 | }); 60 | 61 | it('getClient should be called', function() { 62 | expect( 63 | mocks._dynamic.mongoStoreContext.getClient.callCount 64 | ).eql(1); 65 | 66 | var getCollectionArgs = mocks._dynamic.mongoStoreContext 67 | .getClient.args[0]; 68 | 69 | expect(getCollectionArgs).length(1); 70 | expect(getCollectionArgs[0]).a('function'); 71 | }); 72 | 73 | after(function() { 74 | revertMocks(); 75 | }); 76 | }); 77 | -------------------------------------------------------------------------------- /test/mongoStore/incr/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var sinon = require('sinon'); 4 | var _ = require('underscore'); 5 | 6 | exports.getTestData = function() { 7 | return { 8 | key: 'testKey', 9 | DateResult: { 10 | someKey: _.random(1, 10) 11 | }, 12 | Date: { 13 | nowResult: _.random(1, 10) 14 | }, 15 | collection: { 16 | findOneAndUpdateResult: { 17 | value: { 18 | counter: _.random(1, 10), 19 | expirationDate: _.random(1, 10) 20 | } 21 | } 22 | }, 23 | mongoStoreContext: { 24 | expireTimeMs: _.random(1, 10) 25 | } 26 | }; 27 | }; 28 | 29 | exports.getMocks = function(testData) { 30 | var dateMock = sinon.stub().callsFake(function() { 31 | _(this).extend(testData.DateResult); 32 | }); 33 | dateMock.now = sinon.stub().returns(testData.Date.nowResult); 34 | 35 | var collectionFindOneAndUpdateMock = sinon.stub().callsArgWithAsync( 36 | 3, 37 | testData.findOneAndUpdateError, 38 | testData.collection.findOneAndUpdateResult 39 | ); 40 | var collectionMock = { 41 | findOneAndUpdate: collectionFindOneAndUpdateMock 42 | }; 43 | 44 | return { 45 | Date: dateMock, 46 | _dynamic: { 47 | mongoStoreContext: { 48 | _getCollection: sinon.stub().callsArgWithAsync( 49 | 0, null, collectionMock 50 | ), 51 | errorHandler: sinon.stub().returns(), 52 | incr: sinon.stub().callsArgWithAsync(1) 53 | }, 54 | collection: collectionMock 55 | } 56 | }; 57 | }; 58 | -------------------------------------------------------------------------------- /test/mongoStore/incr/withFindOndAndUpdateDuplicateKeyError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype.incr with ' + 12 | 'findOneAndUpdate duplicate key error'; 13 | describe(describeTitle, function() { 14 | var testData = testUtils.getTestData(); 15 | testData.findOneAndUpdateError = new Error(); 16 | testData.findOneAndUpdateError.code = 11000; 17 | 18 | var mocks = testUtils.getMocks(testData); 19 | 20 | var revertMocks; 21 | 22 | before(function() { 23 | revertMocks = MongoStore.__set__( 24 | _(mocks).omit('_dynamic') 25 | ); 26 | }); 27 | 28 | it('should be ok', function(done) { 29 | Steppy( 30 | function() { 31 | MongoStore.prototype.incr.call( 32 | _({}).extend( 33 | testData.mongoStoreContext, 34 | mocks._dynamic.mongoStoreContext 35 | ), 36 | testData.key, 37 | this.slot() 38 | ); 39 | }, 40 | done 41 | ); 42 | }); 43 | 44 | it('_getCollection should be called', function() { 45 | expect( 46 | mocks._dynamic.mongoStoreContext._getCollection.callCount 47 | ).eql(1); 48 | 49 | var getCollectionArgs = mocks._dynamic.mongoStoreContext 50 | ._getCollection.args[0]; 51 | 52 | expect(getCollectionArgs).length(1); 53 | expect(getCollectionArgs[0]).a('function'); 54 | }); 55 | 56 | it('Date.now should be called', function() { 57 | expect(mocks.Date.now.callCount).eql(1); 58 | expect(mocks.Date.now.args[0]).eql([]); 59 | }); 60 | 61 | it('Date should be called to construct expirationDate', function() { 62 | expect(mocks.Date.callCount).eql(1); 63 | 64 | var dateArgs = mocks.Date.args[0]; 65 | 66 | expect(dateArgs).eql([ 67 | testData.mongoStoreContext.expireTimeMs + testData.Date.nowResult 68 | ]); 69 | }); 70 | 71 | it('Date should be called as constructor', function() { 72 | expect(mocks.Date.calledWithNew()).eql(true); 73 | }); 74 | 75 | it( 76 | 'collection.findOneAndUpdate should be called for incrementing counter', 77 | function() { 78 | expect( 79 | mocks._dynamic.collection.findOneAndUpdate.callCount 80 | ).eql(1); 81 | 82 | var findOneAndUpdateArgs = mocks._dynamic.collection 83 | .findOneAndUpdate.args[0]; 84 | 85 | expect( 86 | _(findOneAndUpdateArgs).initial() 87 | ).eql([ 88 | {_id: testData.key}, 89 | { 90 | $inc: {counter: 1}, 91 | $setOnInsert: { 92 | expirationDate: testData.DateResult 93 | } 94 | }, 95 | { 96 | upsert: true, 97 | returnDocument: 'after' 98 | } 99 | ]); 100 | 101 | expect( 102 | _(findOneAndUpdateArgs).last() 103 | ).a('function'); 104 | } 105 | ); 106 | 107 | it('self.incr should be called', function() { 108 | expect(mocks._dynamic.mongoStoreContext.incr.callCount).eql(1); 109 | 110 | var incrArgs = mocks._dynamic.mongoStoreContext.incr.args[0]; 111 | 112 | expect( 113 | _(incrArgs).initial() 114 | ).eql([ 115 | testData.key 116 | ]); 117 | 118 | expect( 119 | _(incrArgs).last() 120 | ).a('function'); 121 | }); 122 | 123 | it('errorHandler should not be called', function() { 124 | expect( 125 | mocks._dynamic.mongoStoreContext.errorHandler.callCount 126 | ).eql(0); 127 | }); 128 | 129 | after(function() { 130 | revertMocks(); 131 | }); 132 | }); 133 | -------------------------------------------------------------------------------- /test/mongoStore/incr/withFindOneAndUpdateError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype.incr with findOneAndUpdate error'; 12 | describe(describeTitle, function() { 13 | var testData = testUtils.getTestData(); 14 | testData.findOneAndUpdateError = new Error(); 15 | 16 | var mocks = testUtils.getMocks(testData); 17 | 18 | var revertMocks; 19 | 20 | before(function() { 21 | revertMocks = MongoStore.__set__( 22 | _(mocks).omit('_dynamic') 23 | ); 24 | }); 25 | 26 | it('should throw error', function(done) { 27 | Steppy( 28 | function() { 29 | MongoStore.prototype.incr.call( 30 | _({}).extend( 31 | testData.mongoStoreContext, 32 | mocks._dynamic.mongoStoreContext 33 | ), 34 | testData.key, 35 | this.slot() 36 | ); 37 | }, 38 | function(err) { 39 | revertMocks(); 40 | 41 | expect(err).ok(); 42 | expect(err).eql(testData.findOneAndUpdateError); 43 | 44 | done(); 45 | } 46 | ); 47 | }); 48 | 49 | it('_getCollection should be called', function() { 50 | expect( 51 | mocks._dynamic.mongoStoreContext._getCollection.callCount 52 | ).eql(1); 53 | 54 | var getCollectionArgs = mocks._dynamic.mongoStoreContext 55 | ._getCollection.args[0]; 56 | 57 | expect(getCollectionArgs).length(1); 58 | expect(getCollectionArgs[0]).a('function'); 59 | }); 60 | 61 | it('Date.now should be called', function() { 62 | expect(mocks.Date.now.callCount).eql(1); 63 | expect(mocks.Date.now.args[0]).eql([]); 64 | }); 65 | 66 | it('Date should be called to construct expirationDate', function() { 67 | expect(mocks.Date.callCount).eql(1); 68 | 69 | var dateArgs = mocks.Date.args[0]; 70 | 71 | expect(dateArgs).eql([ 72 | testData.mongoStoreContext.expireTimeMs + testData.Date.nowResult 73 | ]); 74 | }); 75 | 76 | it('Date should be called as constructor', function() { 77 | expect(mocks.Date.calledWithNew()).eql(true); 78 | }); 79 | 80 | it( 81 | 'collection.findOneAndUpdate should be called for incrementing counter', 82 | function() { 83 | expect( 84 | mocks._dynamic.collection.findOneAndUpdate.callCount 85 | ).eql(1); 86 | 87 | var findOneAndUpdateArgs = mocks._dynamic.collection 88 | .findOneAndUpdate.args[0]; 89 | 90 | expect( 91 | _(findOneAndUpdateArgs).initial() 92 | ).eql([ 93 | {_id: testData.key}, 94 | { 95 | $inc: {counter: 1}, 96 | $setOnInsert: { 97 | expirationDate: testData.DateResult 98 | } 99 | }, 100 | { 101 | upsert: true, 102 | returnDocument: 'after' 103 | } 104 | ]); 105 | 106 | expect( 107 | _(findOneAndUpdateArgs).last() 108 | ).a('function'); 109 | } 110 | ); 111 | 112 | it('self.incr should not be called', function() { 113 | expect( 114 | mocks._dynamic.mongoStoreContext.incr.callCount 115 | ).eql(0); 116 | }); 117 | 118 | it('errorHandler should be called with error', function() { 119 | expect( 120 | mocks._dynamic.mongoStoreContext.errorHandler.callCount 121 | ).eql(1); 122 | 123 | var errorHandlerArgs = mocks._dynamic.mongoStoreContext.errorHandler 124 | .args[0]; 125 | 126 | expect(errorHandlerArgs).eql([ 127 | testData.findOneAndUpdateError 128 | ]); 129 | }); 130 | 131 | after(function() { 132 | revertMocks(); 133 | }); 134 | }); 135 | -------------------------------------------------------------------------------- /test/mongoStore/incr/withResetExpireDateOnCange.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var rewire = require('rewire'); 5 | var _ = require('underscore'); 6 | var testUtils = require('./utils'); 7 | 8 | var MongoStore = rewire('../../../lib/mongoStore'); 9 | 10 | var describeTitle = 'MongoStore.prototype.incr with resetExpireDateOnChange'; 11 | describe(describeTitle, function() { 12 | var testData = testUtils.getTestData(); 13 | testData.mongoStoreContext.resetExpireDateOnChange = true; 14 | 15 | var mocks = testUtils.getMocks(testData); 16 | 17 | var revertMocks; 18 | 19 | before(function() { 20 | revertMocks = MongoStore.__set__( 21 | _(mocks).omit('_dynamic') 22 | ); 23 | }); 24 | 25 | it('should return counter and expirationDate', function(done) { 26 | MongoStore.prototype.incr.call( 27 | _({}).extend( 28 | testData.mongoStoreContext, 29 | mocks._dynamic.mongoStoreContext 30 | ), 31 | testData.key, 32 | function(err, counter, expirationDate) { 33 | revertMocks(); 34 | 35 | expect(counter).eql( 36 | testData.collection.findOneAndUpdateResult.value.counter 37 | ); 38 | expect(expirationDate).eql( 39 | testData.collection.findOneAndUpdateResult.value.expirationDate 40 | ); 41 | 42 | done(); 43 | } 44 | ); 45 | }); 46 | 47 | it('_getCollection should be called', function() { 48 | expect( 49 | mocks._dynamic.mongoStoreContext._getCollection.callCount 50 | ).eql(1); 51 | 52 | var getCollectionArgs = mocks._dynamic.mongoStoreContext 53 | ._getCollection.args[0]; 54 | 55 | expect(getCollectionArgs).length(1); 56 | expect(getCollectionArgs[0]).a('function'); 57 | }); 58 | 59 | it('Date.now should be called', function() { 60 | expect(mocks.Date.now.callCount).eql(1); 61 | expect(mocks.Date.now.args[0]).eql([]); 62 | }); 63 | 64 | it('Date should be called to construct expirationDate', function() { 65 | expect(mocks.Date.callCount).eql(1); 66 | 67 | var dateArgs = mocks.Date.args[0]; 68 | 69 | expect(dateArgs).eql([ 70 | testData.mongoStoreContext.expireTimeMs + testData.Date.nowResult 71 | ]); 72 | }); 73 | 74 | it('Date should be called as constructor', function() { 75 | expect(mocks.Date.calledWithNew()).eql(true); 76 | }); 77 | 78 | it( 79 | 'collection.findOneAndUpdate should be called for incrementing counter', 80 | function() { 81 | expect( 82 | mocks._dynamic.collection.findOneAndUpdate.callCount 83 | ).eql(1); 84 | 85 | var findOneAndUpdateArgs = mocks._dynamic.collection 86 | .findOneAndUpdate.args[0]; 87 | 88 | expect( 89 | _(findOneAndUpdateArgs).initial() 90 | ).eql([ 91 | {_id: testData.key}, 92 | { 93 | $inc: {counter: 1}, 94 | $set: { 95 | expirationDate: testData.DateResult 96 | } 97 | }, 98 | { 99 | upsert: true, 100 | returnDocument: 'after' 101 | } 102 | ]); 103 | 104 | expect( 105 | _(findOneAndUpdateArgs).last() 106 | ).a('function'); 107 | } 108 | ); 109 | 110 | it('self.incr should not be called', function() { 111 | expect( 112 | mocks._dynamic.mongoStoreContext.incr.callCount 113 | ).eql(0); 114 | }); 115 | 116 | it('errorHandler should not be called', function() { 117 | expect( 118 | mocks._dynamic.mongoStoreContext.errorHandler.callCount 119 | ).eql(0); 120 | }); 121 | 122 | after(function() { 123 | revertMocks(); 124 | }); 125 | }); 126 | -------------------------------------------------------------------------------- /test/mongoStore/incr/withoutResetExpireDateOnChange.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var rewire = require('rewire'); 5 | var _ = require('underscore'); 6 | var testUtils = require('./utils'); 7 | 8 | var MongoStore = rewire('../../../lib/mongoStore'); 9 | 10 | var describeTitle = 'MongoStore.prototype.incr without resetExpireDateOnChange'; 11 | describe(describeTitle, function() { 12 | var testData = testUtils.getTestData(); 13 | testData.mongoStoreContext.resetExpireDateOnChange = false; 14 | 15 | var mocks = testUtils.getMocks(testData); 16 | 17 | var revertMocks; 18 | 19 | before(function() { 20 | revertMocks = MongoStore.__set__( 21 | _(mocks).omit('_dynamic') 22 | ); 23 | }); 24 | 25 | it('should return counter and expirationDate', function(done) { 26 | MongoStore.prototype.incr.call( 27 | _({}).extend( 28 | testData.mongoStoreContext, 29 | mocks._dynamic.mongoStoreContext 30 | ), 31 | testData.key, 32 | function(err, counter, expirationDate) { 33 | revertMocks(); 34 | 35 | expect(counter).eql( 36 | testData.collection.findOneAndUpdateResult.value.counter 37 | ); 38 | expect(expirationDate).eql( 39 | testData.collection.findOneAndUpdateResult.value.expirationDate 40 | ); 41 | 42 | done(); 43 | } 44 | ); 45 | }); 46 | 47 | it('_getCollection should be called', function() { 48 | expect( 49 | mocks._dynamic.mongoStoreContext._getCollection.callCount 50 | ).eql(1); 51 | 52 | var getCollectionArgs = mocks._dynamic.mongoStoreContext 53 | ._getCollection.args[0]; 54 | 55 | expect(getCollectionArgs).length(1); 56 | expect(getCollectionArgs[0]).a('function'); 57 | }); 58 | 59 | it('Date.now should be called', function() { 60 | expect(mocks.Date.now.callCount).eql(1); 61 | expect(mocks.Date.now.args[0]).eql([]); 62 | }); 63 | 64 | it('Date should be called to construct expirationDate', function() { 65 | expect(mocks.Date.callCount).eql(1); 66 | 67 | var dateArgs = mocks.Date.args[0]; 68 | 69 | expect(dateArgs).eql([ 70 | testData.mongoStoreContext.expireTimeMs + testData.Date.nowResult 71 | ]); 72 | }); 73 | 74 | it('Date should be called as constructor', function() { 75 | expect(mocks.Date.calledWithNew()).eql(true); 76 | }); 77 | 78 | it( 79 | 'collection.findOneAndUpdate should be called for incrementing counter', 80 | function() { 81 | expect( 82 | mocks._dynamic.collection.findOneAndUpdate.callCount 83 | ).eql(1); 84 | 85 | var findOneAndUpdateArgs = mocks._dynamic.collection 86 | .findOneAndUpdate.args[0]; 87 | 88 | expect( 89 | _(findOneAndUpdateArgs).initial() 90 | ).eql([ 91 | {_id: testData.key}, 92 | { 93 | $inc: {counter: 1}, 94 | $setOnInsert: { 95 | expirationDate: testData.DateResult 96 | } 97 | }, 98 | { 99 | upsert: true, 100 | returnDocument: 'after' 101 | } 102 | ]); 103 | 104 | expect( 105 | _(findOneAndUpdateArgs).last() 106 | ).a('function'); 107 | } 108 | ); 109 | 110 | it('self.incr should not be called', function() { 111 | expect( 112 | mocks._dynamic.mongoStoreContext.incr.callCount 113 | ).eql(0); 114 | }); 115 | 116 | it('errorHandler should not be called', function() { 117 | expect( 118 | mocks._dynamic.mongoStoreContext.errorHandler.callCount 119 | ).eql(0); 120 | }); 121 | 122 | after(function() { 123 | revertMocks(); 124 | }); 125 | }); 126 | -------------------------------------------------------------------------------- /test/mongoStore/resetKey/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var sinon = require('sinon'); 4 | 5 | exports.getTestData = function() { 6 | return { 7 | key: 'testKey' 8 | }; 9 | }; 10 | 11 | exports.getMocks = function(testData) { 12 | var collectionMock = { 13 | deleteOne: sinon.stub().callsArgWithAsync( 14 | 1, testData.deleteOneError 15 | ) 16 | }; 17 | 18 | return { 19 | _dynamic: { 20 | mongoStoreContext: { 21 | _getCollection: sinon.stub().callsArgWithAsync( 22 | 0, null, collectionMock 23 | ), 24 | errorHandler: sinon.stub().returns() 25 | }, 26 | collection: collectionMock 27 | } 28 | }; 29 | }; 30 | -------------------------------------------------------------------------------- /test/mongoStore/resetKey/withDeleteOneError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype.resetKey ' + 12 | 'with deleteOne error'; 13 | describe(describeTitle, function() { 14 | var testData = testUtils.getTestData(); 15 | testData.deleteOneError = new Error(); 16 | 17 | var mocks = testUtils.getMocks(testData); 18 | 19 | it('should throw error', function(done) { 20 | Steppy( 21 | function() { 22 | MongoStore.prototype.resetKey.call( 23 | _({}).extend( 24 | testData.mongoStoreContext, 25 | mocks._dynamic.mongoStoreContext 26 | ), 27 | testData.key, 28 | this.slot() 29 | ); 30 | }, 31 | function(err) { 32 | expect(err).eql(testData.deleteOneError); 33 | 34 | done(); 35 | } 36 | ); 37 | }); 38 | 39 | it('_getCollection should be called', function() { 40 | expect( 41 | mocks._dynamic.mongoStoreContext._getCollection.callCount 42 | ).eql(1); 43 | 44 | var getCollectionArgs = mocks._dynamic.mongoStoreContext 45 | ._getCollection.args[0]; 46 | 47 | expect(getCollectionArgs).length(1); 48 | expect(getCollectionArgs[0]).a('function'); 49 | }); 50 | 51 | it( 52 | 'collection.deleteOne should be called for deleting record', 53 | function() { 54 | expect( 55 | mocks._dynamic.collection.deleteOne.callCount 56 | ).eql(1); 57 | 58 | var deleteOneArgs = mocks._dynamic.collection.deleteOne.args[0]; 59 | 60 | expect( 61 | _(deleteOneArgs).initial() 62 | ).eql([ 63 | {_id: testData.key} 64 | ]); 65 | 66 | expect( 67 | _(deleteOneArgs).last() 68 | ).a('function'); 69 | } 70 | ); 71 | 72 | it('errorHandler should be called with error', function() { 73 | expect( 74 | mocks._dynamic.mongoStoreContext.errorHandler.callCount 75 | ).eql(1); 76 | 77 | var errorHandlerArgs = mocks._dynamic.mongoStoreContext.errorHandler 78 | .args[0]; 79 | 80 | expect(errorHandlerArgs).eql([ 81 | testData.deleteOneError 82 | ]); 83 | }); 84 | }); 85 | -------------------------------------------------------------------------------- /test/mongoStore/resetKey/withSuitableParams.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var Steppy = require('twostep').Steppy; 5 | var rewire = require('rewire'); 6 | var _ = require('underscore'); 7 | var testUtils = require('./utils'); 8 | 9 | var MongoStore = rewire('../../../lib/mongoStore'); 10 | 11 | var describeTitle = 'MongoStore.prototype.resetKey with suitable params'; 12 | describe(describeTitle, function() { 13 | var testData = testUtils.getTestData(); 14 | 15 | var mocks = testUtils.getMocks(testData); 16 | 17 | it('should be ok', function(done) { 18 | Steppy( 19 | function() { 20 | MongoStore.prototype.resetKey.call( 21 | _({}).extend( 22 | testData.mongoStoreContext, 23 | mocks._dynamic.mongoStoreContext 24 | ), 25 | testData.key, 26 | this.slot() 27 | ); 28 | }, 29 | done 30 | ); 31 | }); 32 | 33 | it('_getCollection should be called', function() { 34 | expect( 35 | mocks._dynamic.mongoStoreContext._getCollection.callCount 36 | ).eql(1); 37 | 38 | var getCollectionArgs = mocks._dynamic.mongoStoreContext 39 | ._getCollection.args[0]; 40 | 41 | expect(getCollectionArgs).length(1); 42 | expect(getCollectionArgs[0]).a('function'); 43 | }); 44 | 45 | it( 46 | 'collection.deleteOne should be called for deleting record', 47 | function() { 48 | expect( 49 | mocks._dynamic.collection.deleteOne.callCount 50 | ).eql(1); 51 | 52 | var deleteOneArgs = mocks._dynamic.collection.deleteOne.args[0]; 53 | 54 | expect( 55 | _(deleteOneArgs).initial() 56 | ).eql([ 57 | {_id: testData.key} 58 | ]); 59 | 60 | expect( 61 | _(deleteOneArgs).last() 62 | ).a('function'); 63 | } 64 | ); 65 | 66 | it('errorHandler should not be called', function() { 67 | expect( 68 | mocks._dynamic.mongoStoreContext.errorHandler.callCount 69 | ).eql(0); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /test/utils/getCallbackFromArgs/withArgsWithOneItem.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var getCallbackFromArgs = require('../../../lib/utils/getCallbackFromArgs'); 5 | 6 | var describeTitle = 'lib/utils/getCallbackFromArgs with args with one item'; 7 | describe(describeTitle, function() { 8 | var args = [ 9 | function() {} 10 | ]; 11 | 12 | it('should return undefined', function() { 13 | var callback = getCallbackFromArgs(args); 14 | 15 | expect(callback).eql(undefined); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/utils/getCallbackFromArgs/withLastArgsItemFunction.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var getCallbackFromArgs = require('../../../lib/utils/getCallbackFromArgs'); 5 | 6 | var describeTitle = 'lib/utils/getCallbackFromArgs ' + 7 | 'with args with last item function'; 8 | describe(describeTitle, function() { 9 | var args = [ 10 | 'randomString1', 11 | function() {} 12 | ]; 13 | 14 | it('should return function', function() { 15 | var callback = getCallbackFromArgs(args); 16 | 17 | expect(callback).eql(args[1]); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/utils/getCallbackFromArgs/withLastArgsItemNotFunction.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'); 4 | var getCallbackFromArgs = require('../../../lib/utils/getCallbackFromArgs'); 5 | 6 | var describeTitle = 'lib/utils/getCallbackFromArgs ' + 7 | 'with args with last item not function'; 8 | describe(describeTitle, function() { 9 | var args = [ 10 | 'randomString1', 11 | 'randomString2' 12 | ]; 13 | 14 | it('should return undefined', function() { 15 | var callback = getCallbackFromArgs(args); 16 | 17 | expect(callback).eql(undefined); 18 | }); 19 | }); 20 | --------------------------------------------------------------------------------