├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── appveyor.yml ├── example-config.yml ├── package-lock.json ├── package.json ├── release.sh ├── src ├── connection.js └── message-connector.js └── test ├── message-connector-messagingSpec.js └── message-connectorSpec.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | build 22 | 23 | # Dependency directory 24 | # Commenting this out is preferred by some people, see 25 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 26 | node_modules 27 | 28 | # Users Environment Variables 29 | .lock-wscript 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi 3 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install redis ; fi 4 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then redis-server --daemonize yes ; fi 5 | 6 | env: 7 | global: 8 | - CXX=g++-4.8 9 | 10 | # Do not insert any code under here without making sures it's in publishingtest first 11 | language: node_js 12 | 13 | plugins: 14 | apt: 15 | sources: 16 | - ubuntu-toolchain-r-test 17 | packages: 18 | - g++-4.8 19 | 20 | services: 21 | - redis-server 22 | 23 | node_js: 24 | - "8" 25 | - "6.11" 26 | - "4" 27 | 28 | matrix: 29 | include: 30 | - node_js: "6.11" 31 | os: osx 32 | 33 | script: 34 | - npm run test 35 | - curl -o package.sh -L https://raw.githubusercontent.com/deepstreamIO/deepstream.io-connector-publishingtest/master/scripts/package.sh 36 | - chmod 555 package.sh 37 | - ./package.sh 38 | 39 | deploy: 40 | - provider: s3 41 | access_key_id: 42 | secure: "VHUgKYnZmNhBqTG986s8QQNVzBn/j7ln9C3nygXAIurJWUs2G3EhlHa6lWl0hNWBXbtrGibEOnkjzIBWySG+7/3UJtNRtfpzSkyE8RtqaJiuC8nitznwFspfX9XfR6Nn2AjYzOpey11Ma54ib5QwxEnRJcOx0wzlKwS0VwA+FOY=" 43 | secret_access_key: 44 | secure: "cwyf/PqJl2F9k2Jt8txbFvtDVQHg4t/ptGkQaW8hRGoO704Bcno9JWf5Zn8AKV9r1hBY9VrCfakfsxf3K9qjyqvKzPRdZifPTsGYLms3PCKJe8gNjV1go8Wb/K5nztKF60TL19ZjP8IEDGO7UsKBTR0vkRl6run0cToatXGJg/g=" 45 | bucket: ds-server-artifacts 46 | skip_cleanup: true 47 | acl: public_read 48 | local_dir: build 49 | upload-dir: $TRAVIS_REPO_SLUG 50 | - provider: releases 51 | skip_cleanup: true 52 | api_key: 53 | secure: "T6NHUqaqM55ip4K13+YwUavK7S4DhGXzfTIwlGaxsT6QV6+yXnu9yIfbaNjMIi3Zlq5swCoY4b24lTHq3h9xxIqQ9FbjAf8Mu8LxKiEExK7sZyKpO4bgeMe5NOXHRWNnhaZx/yeXJ57kFE8CaHkL5q4DSO1npGdtndHrhYLFvp0=" 54 | file_glob: true 55 | file: 56 | - "build/*.tar.gz" 57 | - "build/*.zip" 58 | on: 59 | tags: true 60 | 61 | after_deploy: 62 | - curl -o test.sh -L https://raw.githubusercontent.com/deepstreamIO/deepstream.io-connector-publishingtest/master/scripts/test.sh 63 | - chmod 555 test.sh 64 | - ./test.sh 65 | 66 | after_script: 67 | - "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js" 68 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.0.4] - 2017-02-15 2 | 3 | ### Fixes 4 | - Adding back node 4 compatibility 5 | 6 | ## [1.0.3] - 2017-02-12 7 | 8 | ### Enhancements 9 | - Updating ioredis to v3.0 10 | - Build artifacts against v6 of node 11 | 12 | ## [1.0.2] - 2016-09-13 13 | 14 | ### Enhancements 15 | - When Deepstream quits, gracefully closes the connection to Redis 16 | 17 | ### Miscellaneous 18 | - CI build no longer depends on external Redis 19 | 20 | ## [1.0.1] - 2016-08-11 21 | 22 | ### Enhancements 23 | - Updated example config 24 | 25 | ## [1.0.0] - 2016-06-29 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016 deepstreamHub GmbH 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | deepstream.io-msg-redis [![npm version](https://badge.fury.io/js/deepstream.io-msg-redis.svg)](http://badge.fury.io/js/deepstream.io-msg-redis) 2 | =================== 3 | 4 | [deepstream](http://deepstream.io) message connector for [redis](http://redis.io/) 5 | 6 | This connector uses [the npm ioredis package](https://www.npmjs.com/package/ioredis). Please have a look there for detailed options. 7 | 8 | ## Install via 9 | ```bash 10 | deepstream install message redis 11 | ``` 12 | 13 | ## Example configuration 14 | ```yaml 15 | plugins: 16 | cache: 17 | name: redis 18 | options: 19 | host: ${REDIS_HOST} 20 | port: ${REDIS_PORT} 21 | 22 | # Using with a cluster 23 | # plugins: 24 | # cache: 25 | # name: redis 26 | # options: 27 | # nodes: 28 | # - host: 29 | # port: 30 | # password: 31 | # - host: 32 | # port: 33 | # redisOptions: 34 | # password: 'fallback-password' 35 | # maxRedirections: 16 36 | ``` 37 | 38 | ## Usage in node 39 | ```javascript 40 | var Deepstream = require( 'deepstream.io' ), 41 | RedisMessageConnector = require( 'deepstream.io-msg-redis' ), 42 | server = new Deepstream(); 43 | 44 | server.set( 'messageConnector', new RedisMessageConnector( { 45 | port: 5672, 46 | host: 'localhost' 47 | })); 48 | 49 | server.start(); 50 | ``` 51 | 52 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # Do not insert any code under here without making sures it's in publishingtest first 2 | os: 3 | - Visual Studio 2015 4 | 5 | platform: 6 | - x64 7 | 8 | install: 9 | - ps: Install-Product node 6.11 10 | - npm install 11 | - nuget install redis-64 -excludeversion 12 | - redis-64\tools\redis-server.exe --service-install 13 | - redis-64\tools\redis-server.exe --service-start 14 | - '@ECHO Redis Started' 15 | 16 | test_script: 17 | - node --version 18 | - npm --version 19 | - npm test 20 | - curl -o package.sh -L https://raw.githubusercontent.com/deepstreamIO/deepstream.io-connector-publishingtest/master/scripts/package.sh 21 | - bash package.sh 22 | - For /d %%d in ( build\** ) do MOVE %%d %cd% 23 | 24 | artifacts: 25 | - path: 'build\*.zip' 26 | name: 'deepstream.io-connector' 27 | 28 | - path: '**\*.zip' 29 | 30 | deploy: 31 | - provider: S3 32 | access_key_id: 33 | secure: zIKwOEzh56IXWlpXWMDwjC9Dqz58ZifBBQUZ43wDQWs= 34 | secret_access_key: 35 | secure: br3dL6aFlkMBeqdXSeXfKeZmjyZl1OGD9STaUiGXsWic50DEqedx24C0LipYJqYI 36 | bucket: ds-server-artifacts 37 | folder: $(APPVEYOR_REPO_NAME) 38 | on: 39 | appveyor_repo_tag: false 40 | 41 | - provider: GitHub 42 | release: $(APPVEYOR_REPO_TAG_NAME) 43 | description: 'Release description' 44 | auth_token: 45 | secure: tZHuiZVCwkXRYMihVyoNrmDxAm6xPbXyop7Plg5uUWIIqA1EoUCrTYd/V+0D1I+Y 46 | artifact: 'deepstream.io-connector' 47 | draft: false 48 | on: 49 | appveyor_repo_tag: true 50 | 51 | after_deploy: 52 | - curl -o test.sh -L https://raw.githubusercontent.com/deepstreamIO/deepstream.io-connector-publishingtest/master/scripts/test.sh 53 | - chmod 555 test.sh 54 | - bash test.sh 55 | 56 | build: off 57 | -------------------------------------------------------------------------------- /example-config.yml: -------------------------------------------------------------------------------- 1 | plugins: 2 | message: 3 | name: redis 4 | options: 5 | host: ${REDIS_HOST} 6 | port: ${REDIS_PORT} 7 | 8 | # Using with a cluster 9 | # plugins: 10 | # message: 11 | # name: redis 12 | # options: 13 | # nodes: 14 | # - host: 15 | # port: 16 | # password: 17 | # - host: 18 | # port: 19 | # maxRedirections: 16 20 | # redisOptions: 21 | # password: 'fallback-password' 22 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "deepstream.io-msg-redis", 3 | "version": "1.0.5", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "abbrev": { 8 | "version": "1.0.9", 9 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", 10 | "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", 11 | "dev": true 12 | }, 13 | "acorn": { 14 | "version": "5.1.1", 15 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz", 16 | "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw==", 17 | "dev": true 18 | }, 19 | "acorn-jsx": { 20 | "version": "3.0.1", 21 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", 22 | "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", 23 | "dev": true, 24 | "requires": { 25 | "acorn": "3.3.0" 26 | }, 27 | "dependencies": { 28 | "acorn": { 29 | "version": "3.3.0", 30 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 31 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", 32 | "dev": true 33 | } 34 | } 35 | }, 36 | "ajv": { 37 | "version": "4.11.8", 38 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", 39 | "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", 40 | "dev": true, 41 | "requires": { 42 | "co": "4.6.0", 43 | "json-stable-stringify": "1.0.1" 44 | } 45 | }, 46 | "ajv-keywords": { 47 | "version": "1.5.1", 48 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", 49 | "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", 50 | "dev": true 51 | }, 52 | "align-text": { 53 | "version": "0.1.4", 54 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", 55 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", 56 | "dev": true, 57 | "requires": { 58 | "kind-of": "3.2.2", 59 | "longest": "1.0.1", 60 | "repeat-string": "1.6.1" 61 | } 62 | }, 63 | "amdefine": { 64 | "version": "1.0.1", 65 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 66 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", 67 | "dev": true 68 | }, 69 | "ansi-escapes": { 70 | "version": "1.4.0", 71 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", 72 | "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", 73 | "dev": true 74 | }, 75 | "ansi-regex": { 76 | "version": "2.1.1", 77 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 78 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 79 | "dev": true 80 | }, 81 | "ansi-styles": { 82 | "version": "2.2.1", 83 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 84 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", 85 | "dev": true 86 | }, 87 | "argparse": { 88 | "version": "1.0.9", 89 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", 90 | "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", 91 | "dev": true, 92 | "requires": { 93 | "sprintf-js": "1.0.3" 94 | } 95 | }, 96 | "array-union": { 97 | "version": "1.0.2", 98 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", 99 | "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", 100 | "dev": true, 101 | "requires": { 102 | "array-uniq": "1.0.3" 103 | } 104 | }, 105 | "array-uniq": { 106 | "version": "1.0.3", 107 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 108 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", 109 | "dev": true 110 | }, 111 | "array.prototype.find": { 112 | "version": "2.0.4", 113 | "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz", 114 | "integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=", 115 | "dev": true, 116 | "requires": { 117 | "define-properties": "1.1.2", 118 | "es-abstract": "1.7.0" 119 | } 120 | }, 121 | "arrify": { 122 | "version": "1.0.1", 123 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 124 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 125 | "dev": true 126 | }, 127 | "asn1": { 128 | "version": "0.2.3", 129 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", 130 | "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", 131 | "dev": true 132 | }, 133 | "assert-plus": { 134 | "version": "0.2.0", 135 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", 136 | "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", 137 | "dev": true 138 | }, 139 | "assertion-error": { 140 | "version": "1.0.2", 141 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", 142 | "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", 143 | "dev": true 144 | }, 145 | "async": { 146 | "version": "1.5.2", 147 | "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", 148 | "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", 149 | "dev": true 150 | }, 151 | "asynckit": { 152 | "version": "0.4.0", 153 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 154 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 155 | "dev": true 156 | }, 157 | "aws-sign2": { 158 | "version": "0.6.0", 159 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", 160 | "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", 161 | "dev": true 162 | }, 163 | "aws4": { 164 | "version": "1.6.0", 165 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", 166 | "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", 167 | "dev": true 168 | }, 169 | "babel-code-frame": { 170 | "version": "6.22.0", 171 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", 172 | "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", 173 | "dev": true, 174 | "requires": { 175 | "chalk": "1.1.3", 176 | "esutils": "2.0.2", 177 | "js-tokens": "3.0.2" 178 | } 179 | }, 180 | "balanced-match": { 181 | "version": "1.0.0", 182 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 183 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 184 | "dev": true 185 | }, 186 | "bcrypt-pbkdf": { 187 | "version": "1.0.1", 188 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", 189 | "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", 190 | "dev": true, 191 | "optional": true, 192 | "requires": { 193 | "tweetnacl": "0.14.5" 194 | } 195 | }, 196 | "bluebird": { 197 | "version": "3.5.0", 198 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", 199 | "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" 200 | }, 201 | "boom": { 202 | "version": "2.10.1", 203 | "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", 204 | "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", 205 | "dev": true, 206 | "requires": { 207 | "hoek": "2.16.3" 208 | } 209 | }, 210 | "brace-expansion": { 211 | "version": "1.1.8", 212 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 213 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 214 | "dev": true, 215 | "requires": { 216 | "balanced-match": "1.0.0", 217 | "concat-map": "0.0.1" 218 | } 219 | }, 220 | "browser-stdout": { 221 | "version": "1.3.0", 222 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", 223 | "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", 224 | "dev": true 225 | }, 226 | "builtin-modules": { 227 | "version": "1.1.1", 228 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 229 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", 230 | "dev": true 231 | }, 232 | "caller-path": { 233 | "version": "0.1.0", 234 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", 235 | "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", 236 | "dev": true, 237 | "requires": { 238 | "callsites": "0.2.0" 239 | } 240 | }, 241 | "callsites": { 242 | "version": "0.2.0", 243 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", 244 | "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", 245 | "dev": true 246 | }, 247 | "camelcase": { 248 | "version": "1.2.1", 249 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", 250 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", 251 | "dev": true, 252 | "optional": true 253 | }, 254 | "caseless": { 255 | "version": "0.11.0", 256 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", 257 | "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", 258 | "dev": true 259 | }, 260 | "center-align": { 261 | "version": "0.1.3", 262 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", 263 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", 264 | "dev": true, 265 | "optional": true, 266 | "requires": { 267 | "align-text": "0.1.4", 268 | "lazy-cache": "1.0.4" 269 | } 270 | }, 271 | "chai": { 272 | "version": "4.0.2", 273 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.0.2.tgz", 274 | "integrity": "sha1-L3MnxN5vOF3XeHmZ4qsCaXoyuDs=", 275 | "dev": true, 276 | "requires": { 277 | "assertion-error": "1.0.2", 278 | "check-error": "1.0.2", 279 | "deep-eql": "2.0.2", 280 | "get-func-name": "2.0.0", 281 | "pathval": "1.1.0", 282 | "type-detect": "4.0.3" 283 | } 284 | }, 285 | "chalk": { 286 | "version": "1.1.3", 287 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 288 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 289 | "dev": true, 290 | "requires": { 291 | "ansi-styles": "2.2.1", 292 | "escape-string-regexp": "1.0.5", 293 | "has-ansi": "2.0.0", 294 | "strip-ansi": "3.0.1", 295 | "supports-color": "2.0.0" 296 | } 297 | }, 298 | "check-error": { 299 | "version": "1.0.2", 300 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 301 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 302 | "dev": true 303 | }, 304 | "circular-json": { 305 | "version": "0.3.1", 306 | "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", 307 | "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=", 308 | "dev": true 309 | }, 310 | "cli-cursor": { 311 | "version": "1.0.2", 312 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", 313 | "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", 314 | "dev": true, 315 | "requires": { 316 | "restore-cursor": "1.0.1" 317 | } 318 | }, 319 | "cli-width": { 320 | "version": "2.1.0", 321 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", 322 | "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", 323 | "dev": true 324 | }, 325 | "cliui": { 326 | "version": "2.1.0", 327 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", 328 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", 329 | "dev": true, 330 | "optional": true, 331 | "requires": { 332 | "center-align": "0.1.3", 333 | "right-align": "0.1.3", 334 | "wordwrap": "0.0.2" 335 | }, 336 | "dependencies": { 337 | "wordwrap": { 338 | "version": "0.0.2", 339 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", 340 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", 341 | "dev": true, 342 | "optional": true 343 | } 344 | } 345 | }, 346 | "cluster-key-slot": { 347 | "version": "1.0.8", 348 | "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.0.8.tgz", 349 | "integrity": "sha1-dlRVYIWmUzCTKi6LWXb44tCz5BQ=" 350 | }, 351 | "co": { 352 | "version": "4.6.0", 353 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 354 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 355 | "dev": true 356 | }, 357 | "code-point-at": { 358 | "version": "1.1.0", 359 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 360 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", 361 | "dev": true 362 | }, 363 | "combined-stream": { 364 | "version": "1.0.5", 365 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", 366 | "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", 367 | "dev": true, 368 | "requires": { 369 | "delayed-stream": "1.0.0" 370 | } 371 | }, 372 | "commander": { 373 | "version": "2.11.0", 374 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", 375 | "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", 376 | "dev": true 377 | }, 378 | "concat-map": { 379 | "version": "0.0.1", 380 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 381 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 382 | "dev": true 383 | }, 384 | "concat-stream": { 385 | "version": "1.6.0", 386 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", 387 | "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", 388 | "dev": true, 389 | "requires": { 390 | "inherits": "2.0.3", 391 | "readable-stream": "2.3.3", 392 | "typedarray": "0.0.6" 393 | } 394 | }, 395 | "contains-path": { 396 | "version": "0.1.0", 397 | "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", 398 | "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", 399 | "dev": true 400 | }, 401 | "core-util-is": { 402 | "version": "1.0.2", 403 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 404 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 405 | "dev": true 406 | }, 407 | "coveralls": { 408 | "version": "2.13.1", 409 | "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.1.tgz", 410 | "integrity": "sha1-1wu5rMGDXsTwY/+drFQjwXsR8Xg=", 411 | "dev": true, 412 | "requires": { 413 | "js-yaml": "3.6.1", 414 | "lcov-parse": "0.0.10", 415 | "log-driver": "1.2.5", 416 | "minimist": "1.2.0", 417 | "request": "2.79.0" 418 | } 419 | }, 420 | "cryptiles": { 421 | "version": "2.0.5", 422 | "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", 423 | "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", 424 | "dev": true, 425 | "requires": { 426 | "boom": "2.10.1" 427 | } 428 | }, 429 | "d": { 430 | "version": "1.0.0", 431 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", 432 | "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", 433 | "dev": true, 434 | "requires": { 435 | "es5-ext": "0.10.24" 436 | } 437 | }, 438 | "damerau-levenshtein": { 439 | "version": "1.0.4", 440 | "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", 441 | "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=", 442 | "dev": true 443 | }, 444 | "dashdash": { 445 | "version": "1.14.1", 446 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 447 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 448 | "dev": true, 449 | "requires": { 450 | "assert-plus": "1.0.0" 451 | }, 452 | "dependencies": { 453 | "assert-plus": { 454 | "version": "1.0.0", 455 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 456 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 457 | "dev": true 458 | } 459 | } 460 | }, 461 | "debug": { 462 | "version": "2.6.8", 463 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", 464 | "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", 465 | "requires": { 466 | "ms": "2.0.0" 467 | } 468 | }, 469 | "decamelize": { 470 | "version": "1.2.0", 471 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 472 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 473 | "dev": true, 474 | "optional": true 475 | }, 476 | "deep-eql": { 477 | "version": "2.0.2", 478 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-2.0.2.tgz", 479 | "integrity": "sha1-sbrAblbwp2d3aG1Qyf63XC7XZ5o=", 480 | "dev": true, 481 | "requires": { 482 | "type-detect": "3.0.0" 483 | }, 484 | "dependencies": { 485 | "type-detect": { 486 | "version": "3.0.0", 487 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-3.0.0.tgz", 488 | "integrity": "sha1-RtDMhVOrt7E6NSsNbeov1Y8tm1U=", 489 | "dev": true 490 | } 491 | } 492 | }, 493 | "deep-is": { 494 | "version": "0.1.3", 495 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 496 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 497 | "dev": true 498 | }, 499 | "define-properties": { 500 | "version": "1.1.2", 501 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", 502 | "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", 503 | "dev": true, 504 | "requires": { 505 | "foreach": "2.0.5", 506 | "object-keys": "1.0.11" 507 | } 508 | }, 509 | "del": { 510 | "version": "2.2.2", 511 | "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", 512 | "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", 513 | "dev": true, 514 | "requires": { 515 | "globby": "5.0.0", 516 | "is-path-cwd": "1.0.0", 517 | "is-path-in-cwd": "1.0.0", 518 | "object-assign": "4.1.1", 519 | "pify": "2.3.0", 520 | "pinkie-promise": "2.0.1", 521 | "rimraf": "2.6.1" 522 | } 523 | }, 524 | "delayed-stream": { 525 | "version": "1.0.0", 526 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 527 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 528 | "dev": true 529 | }, 530 | "denque": { 531 | "version": "1.1.1", 532 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.1.1.tgz", 533 | "integrity": "sha1-ECKcK4juwb0V/4LF/eNW5762254=" 534 | }, 535 | "diff": { 536 | "version": "3.2.0", 537 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", 538 | "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", 539 | "dev": true 540 | }, 541 | "doctrine": { 542 | "version": "2.0.0", 543 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", 544 | "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", 545 | "dev": true, 546 | "requires": { 547 | "esutils": "2.0.2", 548 | "isarray": "1.0.0" 549 | } 550 | }, 551 | "ecc-jsbn": { 552 | "version": "0.1.1", 553 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", 554 | "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", 555 | "dev": true, 556 | "optional": true, 557 | "requires": { 558 | "jsbn": "0.1.1" 559 | } 560 | }, 561 | "es-abstract": { 562 | "version": "1.7.0", 563 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz", 564 | "integrity": "sha1-363ndOAb/Nl/lhgCmMRJyGI/uUw=", 565 | "dev": true, 566 | "requires": { 567 | "es-to-primitive": "1.1.1", 568 | "function-bind": "1.1.0", 569 | "is-callable": "1.1.3", 570 | "is-regex": "1.0.4" 571 | } 572 | }, 573 | "es-to-primitive": { 574 | "version": "1.1.1", 575 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", 576 | "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", 577 | "dev": true, 578 | "requires": { 579 | "is-callable": "1.1.3", 580 | "is-date-object": "1.0.1", 581 | "is-symbol": "1.0.1" 582 | } 583 | }, 584 | "es5-ext": { 585 | "version": "0.10.24", 586 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz", 587 | "integrity": "sha1-pVh3yZJLwMjZvTwsvhdJWsFwmxQ=", 588 | "dev": true, 589 | "requires": { 590 | "es6-iterator": "2.0.1", 591 | "es6-symbol": "3.1.1" 592 | } 593 | }, 594 | "es6-iterator": { 595 | "version": "2.0.1", 596 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", 597 | "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", 598 | "dev": true, 599 | "requires": { 600 | "d": "1.0.0", 601 | "es5-ext": "0.10.24", 602 | "es6-symbol": "3.1.1" 603 | } 604 | }, 605 | "es6-map": { 606 | "version": "0.1.5", 607 | "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", 608 | "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", 609 | "dev": true, 610 | "requires": { 611 | "d": "1.0.0", 612 | "es5-ext": "0.10.24", 613 | "es6-iterator": "2.0.1", 614 | "es6-set": "0.1.5", 615 | "es6-symbol": "3.1.1", 616 | "event-emitter": "0.3.5" 617 | } 618 | }, 619 | "es6-set": { 620 | "version": "0.1.5", 621 | "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", 622 | "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", 623 | "dev": true, 624 | "requires": { 625 | "d": "1.0.0", 626 | "es5-ext": "0.10.24", 627 | "es6-iterator": "2.0.1", 628 | "es6-symbol": "3.1.1", 629 | "event-emitter": "0.3.5" 630 | } 631 | }, 632 | "es6-symbol": { 633 | "version": "3.1.1", 634 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", 635 | "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", 636 | "dev": true, 637 | "requires": { 638 | "d": "1.0.0", 639 | "es5-ext": "0.10.24" 640 | } 641 | }, 642 | "es6-weak-map": { 643 | "version": "2.0.2", 644 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", 645 | "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", 646 | "dev": true, 647 | "requires": { 648 | "d": "1.0.0", 649 | "es5-ext": "0.10.24", 650 | "es6-iterator": "2.0.1", 651 | "es6-symbol": "3.1.1" 652 | } 653 | }, 654 | "escape-string-regexp": { 655 | "version": "1.0.5", 656 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 657 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 658 | "dev": true 659 | }, 660 | "escodegen": { 661 | "version": "1.8.1", 662 | "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", 663 | "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", 664 | "dev": true, 665 | "requires": { 666 | "esprima": "2.7.3", 667 | "estraverse": "1.9.3", 668 | "esutils": "2.0.2", 669 | "optionator": "0.8.2", 670 | "source-map": "0.2.0" 671 | }, 672 | "dependencies": { 673 | "estraverse": { 674 | "version": "1.9.3", 675 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", 676 | "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", 677 | "dev": true 678 | } 679 | } 680 | }, 681 | "escope": { 682 | "version": "3.6.0", 683 | "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", 684 | "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", 685 | "dev": true, 686 | "requires": { 687 | "es6-map": "0.1.5", 688 | "es6-weak-map": "2.0.2", 689 | "esrecurse": "4.2.0", 690 | "estraverse": "4.2.0" 691 | } 692 | }, 693 | "eslint": { 694 | "version": "3.19.0", 695 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", 696 | "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", 697 | "dev": true, 698 | "requires": { 699 | "babel-code-frame": "6.22.0", 700 | "chalk": "1.1.3", 701 | "concat-stream": "1.6.0", 702 | "debug": "2.6.8", 703 | "doctrine": "2.0.0", 704 | "escope": "3.6.0", 705 | "espree": "3.4.3", 706 | "esquery": "1.0.0", 707 | "estraverse": "4.2.0", 708 | "esutils": "2.0.2", 709 | "file-entry-cache": "2.0.0", 710 | "glob": "7.1.2", 711 | "globals": "9.18.0", 712 | "ignore": "3.3.3", 713 | "imurmurhash": "0.1.4", 714 | "inquirer": "0.12.0", 715 | "is-my-json-valid": "2.16.0", 716 | "is-resolvable": "1.0.0", 717 | "js-yaml": "3.6.1", 718 | "json-stable-stringify": "1.0.1", 719 | "levn": "0.3.0", 720 | "lodash": "4.17.4", 721 | "mkdirp": "0.5.1", 722 | "natural-compare": "1.4.0", 723 | "optionator": "0.8.2", 724 | "path-is-inside": "1.0.2", 725 | "pluralize": "1.2.1", 726 | "progress": "1.1.8", 727 | "require-uncached": "1.0.3", 728 | "shelljs": "0.7.8", 729 | "strip-bom": "3.0.0", 730 | "strip-json-comments": "2.0.1", 731 | "table": "3.8.3", 732 | "text-table": "0.2.0", 733 | "user-home": "2.0.0" 734 | } 735 | }, 736 | "eslint-config-airbnb": { 737 | "version": "11.2.0", 738 | "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-11.2.0.tgz", 739 | "integrity": "sha1-oJMO14kegk4bPkNs35dUyBWikgw=", 740 | "dev": true, 741 | "requires": { 742 | "eslint-config-airbnb-base": "7.2.0" 743 | } 744 | }, 745 | "eslint-config-airbnb-base": { 746 | "version": "7.2.0", 747 | "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-7.2.0.tgz", 748 | "integrity": "sha1-Gi/3fMXUq8Lhxdrr5BBvzpX/fCo=", 749 | "dev": true 750 | }, 751 | "eslint-config-deepstream": { 752 | "version": "2.2.1", 753 | "resolved": "https://registry.npmjs.org/eslint-config-deepstream/-/eslint-config-deepstream-2.2.1.tgz", 754 | "integrity": "sha1-W9i+d7Y17QZYVBkgfqb8wIK7imU=", 755 | "dev": true, 756 | "requires": { 757 | "eslint": "3.19.0", 758 | "eslint-config-airbnb": "11.2.0", 759 | "eslint-plugin-import": "1.16.0", 760 | "eslint-plugin-jsx-a11y": "2.2.3", 761 | "eslint-plugin-react": "6.10.3" 762 | } 763 | }, 764 | "eslint-import-resolver-node": { 765 | "version": "0.2.3", 766 | "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", 767 | "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", 768 | "dev": true, 769 | "requires": { 770 | "debug": "2.6.8", 771 | "object-assign": "4.1.1", 772 | "resolve": "1.3.3" 773 | } 774 | }, 775 | "eslint-plugin-import": { 776 | "version": "1.16.0", 777 | "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-1.16.0.tgz", 778 | "integrity": "sha1-svoH68xTUE0PKkR3WC7Iv/GHG58=", 779 | "dev": true, 780 | "requires": { 781 | "builtin-modules": "1.1.1", 782 | "contains-path": "0.1.0", 783 | "debug": "2.6.8", 784 | "doctrine": "1.3.0", 785 | "es6-map": "0.1.5", 786 | "es6-set": "0.1.5", 787 | "eslint-import-resolver-node": "0.2.3", 788 | "has": "1.0.1", 789 | "lodash.cond": "4.5.2", 790 | "lodash.endswith": "4.2.1", 791 | "lodash.find": "4.6.0", 792 | "lodash.findindex": "4.6.0", 793 | "minimatch": "3.0.4", 794 | "object-assign": "4.1.1", 795 | "pkg-dir": "1.0.0", 796 | "pkg-up": "1.0.0" 797 | }, 798 | "dependencies": { 799 | "doctrine": { 800 | "version": "1.3.0", 801 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.3.0.tgz", 802 | "integrity": "sha1-E+dWgrVVGEJCdvfBc3g0Vu+RPSY=", 803 | "dev": true, 804 | "requires": { 805 | "esutils": "2.0.2", 806 | "isarray": "1.0.0" 807 | } 808 | } 809 | } 810 | }, 811 | "eslint-plugin-jsx-a11y": { 812 | "version": "2.2.3", 813 | "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-2.2.3.tgz", 814 | "integrity": "sha1-TjXLcbin23AqxBXIBuuOjZ6mxl0=", 815 | "dev": true, 816 | "requires": { 817 | "damerau-levenshtein": "1.0.4", 818 | "jsx-ast-utils": "1.4.1", 819 | "object-assign": "4.1.1" 820 | } 821 | }, 822 | "eslint-plugin-react": { 823 | "version": "6.10.3", 824 | "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz", 825 | "integrity": "sha1-xUNb6wZ3ThLH2y9qut3L+QDNP3g=", 826 | "dev": true, 827 | "requires": { 828 | "array.prototype.find": "2.0.4", 829 | "doctrine": "1.5.0", 830 | "has": "1.0.1", 831 | "jsx-ast-utils": "1.4.1", 832 | "object.assign": "4.0.4" 833 | }, 834 | "dependencies": { 835 | "doctrine": { 836 | "version": "1.5.0", 837 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", 838 | "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", 839 | "dev": true, 840 | "requires": { 841 | "esutils": "2.0.2", 842 | "isarray": "1.0.0" 843 | } 844 | } 845 | } 846 | }, 847 | "espree": { 848 | "version": "3.4.3", 849 | "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", 850 | "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", 851 | "dev": true, 852 | "requires": { 853 | "acorn": "5.1.1", 854 | "acorn-jsx": "3.0.1" 855 | } 856 | }, 857 | "esprima": { 858 | "version": "2.7.3", 859 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", 860 | "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", 861 | "dev": true 862 | }, 863 | "esquery": { 864 | "version": "1.0.0", 865 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", 866 | "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", 867 | "dev": true, 868 | "requires": { 869 | "estraverse": "4.2.0" 870 | } 871 | }, 872 | "esrecurse": { 873 | "version": "4.2.0", 874 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", 875 | "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", 876 | "dev": true, 877 | "requires": { 878 | "estraverse": "4.2.0", 879 | "object-assign": "4.1.1" 880 | } 881 | }, 882 | "estraverse": { 883 | "version": "4.2.0", 884 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", 885 | "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", 886 | "dev": true 887 | }, 888 | "esutils": { 889 | "version": "2.0.2", 890 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 891 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 892 | "dev": true 893 | }, 894 | "event-emitter": { 895 | "version": "0.3.5", 896 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 897 | "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", 898 | "dev": true, 899 | "requires": { 900 | "d": "1.0.0", 901 | "es5-ext": "0.10.24" 902 | } 903 | }, 904 | "exit-hook": { 905 | "version": "1.1.1", 906 | "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", 907 | "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", 908 | "dev": true 909 | }, 910 | "extend": { 911 | "version": "3.0.1", 912 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", 913 | "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", 914 | "dev": true 915 | }, 916 | "extsprintf": { 917 | "version": "1.0.2", 918 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", 919 | "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", 920 | "dev": true 921 | }, 922 | "fast-levenshtein": { 923 | "version": "2.0.6", 924 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 925 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 926 | "dev": true 927 | }, 928 | "figures": { 929 | "version": "1.7.0", 930 | "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", 931 | "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", 932 | "dev": true, 933 | "requires": { 934 | "escape-string-regexp": "1.0.5", 935 | "object-assign": "4.1.1" 936 | } 937 | }, 938 | "file-entry-cache": { 939 | "version": "2.0.0", 940 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", 941 | "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", 942 | "dev": true, 943 | "requires": { 944 | "flat-cache": "1.2.2", 945 | "object-assign": "4.1.1" 946 | } 947 | }, 948 | "find-up": { 949 | "version": "1.1.2", 950 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", 951 | "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", 952 | "dev": true, 953 | "requires": { 954 | "path-exists": "2.1.0", 955 | "pinkie-promise": "2.0.1" 956 | } 957 | }, 958 | "flat-cache": { 959 | "version": "1.2.2", 960 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", 961 | "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", 962 | "dev": true, 963 | "requires": { 964 | "circular-json": "0.3.1", 965 | "del": "2.2.2", 966 | "graceful-fs": "4.1.11", 967 | "write": "0.2.1" 968 | } 969 | }, 970 | "flexbuffer": { 971 | "version": "0.0.6", 972 | "resolved": "https://registry.npmjs.org/flexbuffer/-/flexbuffer-0.0.6.tgz", 973 | "integrity": "sha1-A5/fI/iCPkQMOPMnfm/vEXQhWzA=" 974 | }, 975 | "foreach": { 976 | "version": "2.0.5", 977 | "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", 978 | "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", 979 | "dev": true 980 | }, 981 | "forever-agent": { 982 | "version": "0.6.1", 983 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 984 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 985 | "dev": true 986 | }, 987 | "form-data": { 988 | "version": "2.1.4", 989 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", 990 | "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", 991 | "dev": true, 992 | "requires": { 993 | "asynckit": "0.4.0", 994 | "combined-stream": "1.0.5", 995 | "mime-types": "2.1.15" 996 | } 997 | }, 998 | "formatio": { 999 | "version": "1.2.0", 1000 | "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", 1001 | "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", 1002 | "dev": true, 1003 | "requires": { 1004 | "samsam": "1.2.1" 1005 | } 1006 | }, 1007 | "fs.realpath": { 1008 | "version": "1.0.0", 1009 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1010 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 1011 | "dev": true 1012 | }, 1013 | "function-bind": { 1014 | "version": "1.1.0", 1015 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", 1016 | "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", 1017 | "dev": true 1018 | }, 1019 | "generate-function": { 1020 | "version": "2.0.0", 1021 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", 1022 | "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", 1023 | "dev": true 1024 | }, 1025 | "generate-object-property": { 1026 | "version": "1.2.0", 1027 | "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", 1028 | "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", 1029 | "dev": true, 1030 | "requires": { 1031 | "is-property": "1.0.2" 1032 | } 1033 | }, 1034 | "get-func-name": { 1035 | "version": "2.0.0", 1036 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 1037 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 1038 | "dev": true 1039 | }, 1040 | "getpass": { 1041 | "version": "0.1.7", 1042 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 1043 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 1044 | "dev": true, 1045 | "requires": { 1046 | "assert-plus": "1.0.0" 1047 | }, 1048 | "dependencies": { 1049 | "assert-plus": { 1050 | "version": "1.0.0", 1051 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 1052 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 1053 | "dev": true 1054 | } 1055 | } 1056 | }, 1057 | "glob": { 1058 | "version": "7.1.2", 1059 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 1060 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 1061 | "dev": true, 1062 | "requires": { 1063 | "fs.realpath": "1.0.0", 1064 | "inflight": "1.0.6", 1065 | "inherits": "2.0.3", 1066 | "minimatch": "3.0.4", 1067 | "once": "1.4.0", 1068 | "path-is-absolute": "1.0.1" 1069 | } 1070 | }, 1071 | "globals": { 1072 | "version": "9.18.0", 1073 | "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", 1074 | "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", 1075 | "dev": true 1076 | }, 1077 | "globby": { 1078 | "version": "5.0.0", 1079 | "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", 1080 | "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", 1081 | "dev": true, 1082 | "requires": { 1083 | "array-union": "1.0.2", 1084 | "arrify": "1.0.1", 1085 | "glob": "7.1.2", 1086 | "object-assign": "4.1.1", 1087 | "pify": "2.3.0", 1088 | "pinkie-promise": "2.0.1" 1089 | } 1090 | }, 1091 | "graceful-fs": { 1092 | "version": "4.1.11", 1093 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 1094 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", 1095 | "dev": true 1096 | }, 1097 | "graceful-readlink": { 1098 | "version": "1.0.1", 1099 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 1100 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", 1101 | "dev": true 1102 | }, 1103 | "growl": { 1104 | "version": "1.9.2", 1105 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 1106 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", 1107 | "dev": true 1108 | }, 1109 | "handlebars": { 1110 | "version": "4.0.10", 1111 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", 1112 | "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", 1113 | "dev": true, 1114 | "requires": { 1115 | "async": "1.5.2", 1116 | "optimist": "0.6.1", 1117 | "source-map": "0.4.4", 1118 | "uglify-js": "2.8.29" 1119 | }, 1120 | "dependencies": { 1121 | "source-map": { 1122 | "version": "0.4.4", 1123 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", 1124 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", 1125 | "dev": true, 1126 | "requires": { 1127 | "amdefine": "1.0.1" 1128 | } 1129 | } 1130 | } 1131 | }, 1132 | "har-validator": { 1133 | "version": "2.0.6", 1134 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", 1135 | "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", 1136 | "dev": true, 1137 | "requires": { 1138 | "chalk": "1.1.3", 1139 | "commander": "2.11.0", 1140 | "is-my-json-valid": "2.16.0", 1141 | "pinkie-promise": "2.0.1" 1142 | } 1143 | }, 1144 | "has": { 1145 | "version": "1.0.1", 1146 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", 1147 | "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", 1148 | "dev": true, 1149 | "requires": { 1150 | "function-bind": "1.1.0" 1151 | } 1152 | }, 1153 | "has-ansi": { 1154 | "version": "2.0.0", 1155 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 1156 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 1157 | "dev": true, 1158 | "requires": { 1159 | "ansi-regex": "2.1.1" 1160 | } 1161 | }, 1162 | "has-flag": { 1163 | "version": "1.0.0", 1164 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", 1165 | "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", 1166 | "dev": true 1167 | }, 1168 | "hawk": { 1169 | "version": "3.1.3", 1170 | "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", 1171 | "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", 1172 | "dev": true, 1173 | "requires": { 1174 | "boom": "2.10.1", 1175 | "cryptiles": "2.0.5", 1176 | "hoek": "2.16.3", 1177 | "sntp": "1.0.9" 1178 | } 1179 | }, 1180 | "hoek": { 1181 | "version": "2.16.3", 1182 | "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", 1183 | "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", 1184 | "dev": true 1185 | }, 1186 | "http-signature": { 1187 | "version": "1.1.1", 1188 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", 1189 | "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", 1190 | "dev": true, 1191 | "requires": { 1192 | "assert-plus": "0.2.0", 1193 | "jsprim": "1.4.0", 1194 | "sshpk": "1.13.1" 1195 | } 1196 | }, 1197 | "ignore": { 1198 | "version": "3.3.3", 1199 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", 1200 | "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", 1201 | "dev": true 1202 | }, 1203 | "imurmurhash": { 1204 | "version": "0.1.4", 1205 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1206 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1207 | "dev": true 1208 | }, 1209 | "inflight": { 1210 | "version": "1.0.6", 1211 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1212 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1213 | "dev": true, 1214 | "requires": { 1215 | "once": "1.4.0", 1216 | "wrappy": "1.0.2" 1217 | } 1218 | }, 1219 | "inherits": { 1220 | "version": "2.0.3", 1221 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1222 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 1223 | "dev": true 1224 | }, 1225 | "inquirer": { 1226 | "version": "0.12.0", 1227 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", 1228 | "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", 1229 | "dev": true, 1230 | "requires": { 1231 | "ansi-escapes": "1.4.0", 1232 | "ansi-regex": "2.1.1", 1233 | "chalk": "1.1.3", 1234 | "cli-cursor": "1.0.2", 1235 | "cli-width": "2.1.0", 1236 | "figures": "1.7.0", 1237 | "lodash": "4.17.4", 1238 | "readline2": "1.0.1", 1239 | "run-async": "0.1.0", 1240 | "rx-lite": "3.1.2", 1241 | "string-width": "1.0.2", 1242 | "strip-ansi": "3.0.1", 1243 | "through": "2.3.8" 1244 | } 1245 | }, 1246 | "interpret": { 1247 | "version": "1.0.3", 1248 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", 1249 | "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", 1250 | "dev": true 1251 | }, 1252 | "ioredis": { 1253 | "version": "3.1.1", 1254 | "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-3.1.1.tgz", 1255 | "integrity": "sha1-zC8dMjK4yVzBUwRrzhaPK6oRhug=", 1256 | "requires": { 1257 | "bluebird": "3.5.0", 1258 | "cluster-key-slot": "1.0.8", 1259 | "debug": "2.6.8", 1260 | "denque": "1.1.1", 1261 | "flexbuffer": "0.0.6", 1262 | "lodash": "4.17.4", 1263 | "redis-commands": "1.3.1", 1264 | "redis-parser": "2.6.0" 1265 | } 1266 | }, 1267 | "is-buffer": { 1268 | "version": "1.1.5", 1269 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", 1270 | "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", 1271 | "dev": true 1272 | }, 1273 | "is-callable": { 1274 | "version": "1.1.3", 1275 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", 1276 | "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", 1277 | "dev": true 1278 | }, 1279 | "is-date-object": { 1280 | "version": "1.0.1", 1281 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", 1282 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", 1283 | "dev": true 1284 | }, 1285 | "is-fullwidth-code-point": { 1286 | "version": "1.0.0", 1287 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 1288 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 1289 | "dev": true, 1290 | "requires": { 1291 | "number-is-nan": "1.0.1" 1292 | } 1293 | }, 1294 | "is-my-json-valid": { 1295 | "version": "2.16.0", 1296 | "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", 1297 | "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=", 1298 | "dev": true, 1299 | "requires": { 1300 | "generate-function": "2.0.0", 1301 | "generate-object-property": "1.2.0", 1302 | "jsonpointer": "4.0.1", 1303 | "xtend": "4.0.1" 1304 | } 1305 | }, 1306 | "is-path-cwd": { 1307 | "version": "1.0.0", 1308 | "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", 1309 | "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", 1310 | "dev": true 1311 | }, 1312 | "is-path-in-cwd": { 1313 | "version": "1.0.0", 1314 | "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", 1315 | "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", 1316 | "dev": true, 1317 | "requires": { 1318 | "is-path-inside": "1.0.0" 1319 | } 1320 | }, 1321 | "is-path-inside": { 1322 | "version": "1.0.0", 1323 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", 1324 | "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", 1325 | "dev": true, 1326 | "requires": { 1327 | "path-is-inside": "1.0.2" 1328 | } 1329 | }, 1330 | "is-property": { 1331 | "version": "1.0.2", 1332 | "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", 1333 | "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", 1334 | "dev": true 1335 | }, 1336 | "is-regex": { 1337 | "version": "1.0.4", 1338 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 1339 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 1340 | "dev": true, 1341 | "requires": { 1342 | "has": "1.0.1" 1343 | } 1344 | }, 1345 | "is-resolvable": { 1346 | "version": "1.0.0", 1347 | "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", 1348 | "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", 1349 | "dev": true, 1350 | "requires": { 1351 | "tryit": "1.0.3" 1352 | } 1353 | }, 1354 | "is-symbol": { 1355 | "version": "1.0.1", 1356 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", 1357 | "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", 1358 | "dev": true 1359 | }, 1360 | "is-typedarray": { 1361 | "version": "1.0.0", 1362 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1363 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 1364 | "dev": true 1365 | }, 1366 | "isarray": { 1367 | "version": "1.0.0", 1368 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1369 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 1370 | "dev": true 1371 | }, 1372 | "isexe": { 1373 | "version": "2.0.0", 1374 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1375 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1376 | "dev": true 1377 | }, 1378 | "isstream": { 1379 | "version": "0.1.2", 1380 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 1381 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", 1382 | "dev": true 1383 | }, 1384 | "istanbul": { 1385 | "version": "0.4.5", 1386 | "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", 1387 | "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", 1388 | "dev": true, 1389 | "requires": { 1390 | "abbrev": "1.0.9", 1391 | "async": "1.5.2", 1392 | "escodegen": "1.8.1", 1393 | "esprima": "2.7.3", 1394 | "glob": "5.0.15", 1395 | "handlebars": "4.0.10", 1396 | "js-yaml": "3.6.1", 1397 | "mkdirp": "0.5.1", 1398 | "nopt": "3.0.6", 1399 | "once": "1.4.0", 1400 | "resolve": "1.1.7", 1401 | "supports-color": "3.2.3", 1402 | "which": "1.2.14", 1403 | "wordwrap": "1.0.0" 1404 | }, 1405 | "dependencies": { 1406 | "glob": { 1407 | "version": "5.0.15", 1408 | "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", 1409 | "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", 1410 | "dev": true, 1411 | "requires": { 1412 | "inflight": "1.0.6", 1413 | "inherits": "2.0.3", 1414 | "minimatch": "3.0.4", 1415 | "once": "1.4.0", 1416 | "path-is-absolute": "1.0.1" 1417 | } 1418 | }, 1419 | "resolve": { 1420 | "version": "1.1.7", 1421 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", 1422 | "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", 1423 | "dev": true 1424 | }, 1425 | "supports-color": { 1426 | "version": "3.2.3", 1427 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", 1428 | "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", 1429 | "dev": true, 1430 | "requires": { 1431 | "has-flag": "1.0.0" 1432 | } 1433 | } 1434 | } 1435 | }, 1436 | "js-tokens": { 1437 | "version": "3.0.2", 1438 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 1439 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", 1440 | "dev": true 1441 | }, 1442 | "js-yaml": { 1443 | "version": "3.6.1", 1444 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", 1445 | "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", 1446 | "dev": true, 1447 | "requires": { 1448 | "argparse": "1.0.9", 1449 | "esprima": "2.7.3" 1450 | } 1451 | }, 1452 | "jsbn": { 1453 | "version": "0.1.1", 1454 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 1455 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 1456 | "dev": true, 1457 | "optional": true 1458 | }, 1459 | "json-schema": { 1460 | "version": "0.2.3", 1461 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 1462 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 1463 | "dev": true 1464 | }, 1465 | "json-stable-stringify": { 1466 | "version": "1.0.1", 1467 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", 1468 | "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", 1469 | "dev": true, 1470 | "requires": { 1471 | "jsonify": "0.0.0" 1472 | } 1473 | }, 1474 | "json-stringify-safe": { 1475 | "version": "5.0.1", 1476 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1477 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 1478 | "dev": true 1479 | }, 1480 | "json3": { 1481 | "version": "3.3.2", 1482 | "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", 1483 | "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", 1484 | "dev": true 1485 | }, 1486 | "jsonify": { 1487 | "version": "0.0.0", 1488 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", 1489 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", 1490 | "dev": true 1491 | }, 1492 | "jsonpointer": { 1493 | "version": "4.0.1", 1494 | "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", 1495 | "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", 1496 | "dev": true 1497 | }, 1498 | "jsprim": { 1499 | "version": "1.4.0", 1500 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", 1501 | "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", 1502 | "dev": true, 1503 | "requires": { 1504 | "assert-plus": "1.0.0", 1505 | "extsprintf": "1.0.2", 1506 | "json-schema": "0.2.3", 1507 | "verror": "1.3.6" 1508 | }, 1509 | "dependencies": { 1510 | "assert-plus": { 1511 | "version": "1.0.0", 1512 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 1513 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 1514 | "dev": true 1515 | } 1516 | } 1517 | }, 1518 | "jsx-ast-utils": { 1519 | "version": "1.4.1", 1520 | "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", 1521 | "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", 1522 | "dev": true 1523 | }, 1524 | "kind-of": { 1525 | "version": "3.2.2", 1526 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1527 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1528 | "dev": true, 1529 | "requires": { 1530 | "is-buffer": "1.1.5" 1531 | } 1532 | }, 1533 | "lazy-cache": { 1534 | "version": "1.0.4", 1535 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 1536 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", 1537 | "dev": true, 1538 | "optional": true 1539 | }, 1540 | "lcov-parse": { 1541 | "version": "0.0.10", 1542 | "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", 1543 | "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", 1544 | "dev": true 1545 | }, 1546 | "levn": { 1547 | "version": "0.3.0", 1548 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 1549 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 1550 | "dev": true, 1551 | "requires": { 1552 | "prelude-ls": "1.1.2", 1553 | "type-check": "0.3.2" 1554 | } 1555 | }, 1556 | "lodash": { 1557 | "version": "4.17.4", 1558 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 1559 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" 1560 | }, 1561 | "lodash._baseassign": { 1562 | "version": "3.2.0", 1563 | "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", 1564 | "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", 1565 | "dev": true, 1566 | "requires": { 1567 | "lodash._basecopy": "3.0.1", 1568 | "lodash.keys": "3.1.2" 1569 | } 1570 | }, 1571 | "lodash._basecopy": { 1572 | "version": "3.0.1", 1573 | "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", 1574 | "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", 1575 | "dev": true 1576 | }, 1577 | "lodash._basecreate": { 1578 | "version": "3.0.3", 1579 | "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", 1580 | "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", 1581 | "dev": true 1582 | }, 1583 | "lodash._getnative": { 1584 | "version": "3.9.1", 1585 | "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", 1586 | "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", 1587 | "dev": true 1588 | }, 1589 | "lodash._isiterateecall": { 1590 | "version": "3.0.9", 1591 | "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", 1592 | "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", 1593 | "dev": true 1594 | }, 1595 | "lodash.cond": { 1596 | "version": "4.5.2", 1597 | "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", 1598 | "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", 1599 | "dev": true 1600 | }, 1601 | "lodash.create": { 1602 | "version": "3.1.1", 1603 | "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", 1604 | "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", 1605 | "dev": true, 1606 | "requires": { 1607 | "lodash._baseassign": "3.2.0", 1608 | "lodash._basecreate": "3.0.3", 1609 | "lodash._isiterateecall": "3.0.9" 1610 | } 1611 | }, 1612 | "lodash.endswith": { 1613 | "version": "4.2.1", 1614 | "resolved": "https://registry.npmjs.org/lodash.endswith/-/lodash.endswith-4.2.1.tgz", 1615 | "integrity": "sha1-/tWawXOO0+I27dcGTsRWRIs3vAk=", 1616 | "dev": true 1617 | }, 1618 | "lodash.find": { 1619 | "version": "4.6.0", 1620 | "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", 1621 | "integrity": "sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E=", 1622 | "dev": true 1623 | }, 1624 | "lodash.findindex": { 1625 | "version": "4.6.0", 1626 | "resolved": "https://registry.npmjs.org/lodash.findindex/-/lodash.findindex-4.6.0.tgz", 1627 | "integrity": "sha1-oyRd7mH7m24GJLU1ElYku2nBEQY=", 1628 | "dev": true 1629 | }, 1630 | "lodash.isarguments": { 1631 | "version": "3.1.0", 1632 | "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", 1633 | "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", 1634 | "dev": true 1635 | }, 1636 | "lodash.isarray": { 1637 | "version": "3.0.4", 1638 | "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", 1639 | "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", 1640 | "dev": true 1641 | }, 1642 | "lodash.keys": { 1643 | "version": "3.1.2", 1644 | "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", 1645 | "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", 1646 | "dev": true, 1647 | "requires": { 1648 | "lodash._getnative": "3.9.1", 1649 | "lodash.isarguments": "3.1.0", 1650 | "lodash.isarray": "3.0.4" 1651 | } 1652 | }, 1653 | "log-driver": { 1654 | "version": "1.2.5", 1655 | "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", 1656 | "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", 1657 | "dev": true 1658 | }, 1659 | "lolex": { 1660 | "version": "1.6.0", 1661 | "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", 1662 | "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=", 1663 | "dev": true 1664 | }, 1665 | "longest": { 1666 | "version": "1.0.1", 1667 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", 1668 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", 1669 | "dev": true 1670 | }, 1671 | "mime-db": { 1672 | "version": "1.27.0", 1673 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", 1674 | "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", 1675 | "dev": true 1676 | }, 1677 | "mime-types": { 1678 | "version": "2.1.15", 1679 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", 1680 | "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", 1681 | "dev": true, 1682 | "requires": { 1683 | "mime-db": "1.27.0" 1684 | } 1685 | }, 1686 | "minimatch": { 1687 | "version": "3.0.4", 1688 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1689 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1690 | "dev": true, 1691 | "requires": { 1692 | "brace-expansion": "1.1.8" 1693 | } 1694 | }, 1695 | "minimist": { 1696 | "version": "1.2.0", 1697 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 1698 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", 1699 | "dev": true 1700 | }, 1701 | "mkdirp": { 1702 | "version": "0.5.1", 1703 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1704 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1705 | "dev": true, 1706 | "requires": { 1707 | "minimist": "0.0.8" 1708 | }, 1709 | "dependencies": { 1710 | "minimist": { 1711 | "version": "0.0.8", 1712 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1713 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 1714 | "dev": true 1715 | } 1716 | } 1717 | }, 1718 | "mocha": { 1719 | "version": "3.4.2", 1720 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.4.2.tgz", 1721 | "integrity": "sha1-0O9NMyEm2/GNDWQMmzgt1IvpdZQ=", 1722 | "dev": true, 1723 | "requires": { 1724 | "browser-stdout": "1.3.0", 1725 | "commander": "2.9.0", 1726 | "debug": "2.6.0", 1727 | "diff": "3.2.0", 1728 | "escape-string-regexp": "1.0.5", 1729 | "glob": "7.1.1", 1730 | "growl": "1.9.2", 1731 | "json3": "3.3.2", 1732 | "lodash.create": "3.1.1", 1733 | "mkdirp": "0.5.1", 1734 | "supports-color": "3.1.2" 1735 | }, 1736 | "dependencies": { 1737 | "commander": { 1738 | "version": "2.9.0", 1739 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", 1740 | "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", 1741 | "dev": true, 1742 | "requires": { 1743 | "graceful-readlink": "1.0.1" 1744 | } 1745 | }, 1746 | "debug": { 1747 | "version": "2.6.0", 1748 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", 1749 | "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=", 1750 | "dev": true, 1751 | "requires": { 1752 | "ms": "0.7.2" 1753 | } 1754 | }, 1755 | "glob": { 1756 | "version": "7.1.1", 1757 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", 1758 | "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", 1759 | "dev": true, 1760 | "requires": { 1761 | "fs.realpath": "1.0.0", 1762 | "inflight": "1.0.6", 1763 | "inherits": "2.0.3", 1764 | "minimatch": "3.0.4", 1765 | "once": "1.4.0", 1766 | "path-is-absolute": "1.0.1" 1767 | } 1768 | }, 1769 | "ms": { 1770 | "version": "0.7.2", 1771 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", 1772 | "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", 1773 | "dev": true 1774 | }, 1775 | "supports-color": { 1776 | "version": "3.1.2", 1777 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", 1778 | "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", 1779 | "dev": true, 1780 | "requires": { 1781 | "has-flag": "1.0.0" 1782 | } 1783 | } 1784 | } 1785 | }, 1786 | "ms": { 1787 | "version": "2.0.0", 1788 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1789 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1790 | }, 1791 | "mute-stream": { 1792 | "version": "0.0.5", 1793 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", 1794 | "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", 1795 | "dev": true 1796 | }, 1797 | "native-promise-only": { 1798 | "version": "0.8.1", 1799 | "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", 1800 | "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", 1801 | "dev": true 1802 | }, 1803 | "natural-compare": { 1804 | "version": "1.4.0", 1805 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1806 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1807 | "dev": true 1808 | }, 1809 | "nopt": { 1810 | "version": "3.0.6", 1811 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", 1812 | "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", 1813 | "dev": true, 1814 | "requires": { 1815 | "abbrev": "1.0.9" 1816 | } 1817 | }, 1818 | "number-is-nan": { 1819 | "version": "1.0.1", 1820 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 1821 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 1822 | "dev": true 1823 | }, 1824 | "oauth-sign": { 1825 | "version": "0.8.2", 1826 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", 1827 | "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", 1828 | "dev": true 1829 | }, 1830 | "object-assign": { 1831 | "version": "4.1.1", 1832 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1833 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 1834 | "dev": true 1835 | }, 1836 | "object-keys": { 1837 | "version": "1.0.11", 1838 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", 1839 | "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", 1840 | "dev": true 1841 | }, 1842 | "object.assign": { 1843 | "version": "4.0.4", 1844 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.0.4.tgz", 1845 | "integrity": "sha1-scnMBE7xuf5jYG/BQau7MuFHMMw=", 1846 | "dev": true, 1847 | "requires": { 1848 | "define-properties": "1.1.2", 1849 | "function-bind": "1.1.0", 1850 | "object-keys": "1.0.11" 1851 | } 1852 | }, 1853 | "once": { 1854 | "version": "1.4.0", 1855 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1856 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1857 | "dev": true, 1858 | "requires": { 1859 | "wrappy": "1.0.2" 1860 | } 1861 | }, 1862 | "onetime": { 1863 | "version": "1.1.0", 1864 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", 1865 | "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", 1866 | "dev": true 1867 | }, 1868 | "optimist": { 1869 | "version": "0.6.1", 1870 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 1871 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 1872 | "dev": true, 1873 | "requires": { 1874 | "minimist": "0.0.10", 1875 | "wordwrap": "0.0.3" 1876 | }, 1877 | "dependencies": { 1878 | "minimist": { 1879 | "version": "0.0.10", 1880 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", 1881 | "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", 1882 | "dev": true 1883 | }, 1884 | "wordwrap": { 1885 | "version": "0.0.3", 1886 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 1887 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", 1888 | "dev": true 1889 | } 1890 | } 1891 | }, 1892 | "optionator": { 1893 | "version": "0.8.2", 1894 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 1895 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 1896 | "dev": true, 1897 | "requires": { 1898 | "deep-is": "0.1.3", 1899 | "fast-levenshtein": "2.0.6", 1900 | "levn": "0.3.0", 1901 | "prelude-ls": "1.1.2", 1902 | "type-check": "0.3.2", 1903 | "wordwrap": "1.0.0" 1904 | } 1905 | }, 1906 | "os-homedir": { 1907 | "version": "1.0.2", 1908 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", 1909 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", 1910 | "dev": true 1911 | }, 1912 | "path-exists": { 1913 | "version": "2.1.0", 1914 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", 1915 | "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", 1916 | "dev": true, 1917 | "requires": { 1918 | "pinkie-promise": "2.0.1" 1919 | } 1920 | }, 1921 | "path-is-absolute": { 1922 | "version": "1.0.1", 1923 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1924 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1925 | "dev": true 1926 | }, 1927 | "path-is-inside": { 1928 | "version": "1.0.2", 1929 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 1930 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 1931 | "dev": true 1932 | }, 1933 | "path-parse": { 1934 | "version": "1.0.5", 1935 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", 1936 | "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", 1937 | "dev": true 1938 | }, 1939 | "path-to-regexp": { 1940 | "version": "1.7.0", 1941 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", 1942 | "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", 1943 | "dev": true, 1944 | "requires": { 1945 | "isarray": "0.0.1" 1946 | }, 1947 | "dependencies": { 1948 | "isarray": { 1949 | "version": "0.0.1", 1950 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 1951 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", 1952 | "dev": true 1953 | } 1954 | } 1955 | }, 1956 | "pathval": { 1957 | "version": "1.1.0", 1958 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", 1959 | "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", 1960 | "dev": true 1961 | }, 1962 | "pify": { 1963 | "version": "2.3.0", 1964 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1965 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 1966 | "dev": true 1967 | }, 1968 | "pinkie": { 1969 | "version": "2.0.4", 1970 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 1971 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 1972 | "dev": true 1973 | }, 1974 | "pinkie-promise": { 1975 | "version": "2.0.1", 1976 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 1977 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 1978 | "dev": true, 1979 | "requires": { 1980 | "pinkie": "2.0.4" 1981 | } 1982 | }, 1983 | "pkg-dir": { 1984 | "version": "1.0.0", 1985 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", 1986 | "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", 1987 | "dev": true, 1988 | "requires": { 1989 | "find-up": "1.1.2" 1990 | } 1991 | }, 1992 | "pkg-up": { 1993 | "version": "1.0.0", 1994 | "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", 1995 | "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", 1996 | "dev": true, 1997 | "requires": { 1998 | "find-up": "1.1.2" 1999 | } 2000 | }, 2001 | "pluralize": { 2002 | "version": "1.2.1", 2003 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", 2004 | "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", 2005 | "dev": true 2006 | }, 2007 | "prelude-ls": { 2008 | "version": "1.1.2", 2009 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 2010 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 2011 | "dev": true 2012 | }, 2013 | "process-nextick-args": { 2014 | "version": "1.0.7", 2015 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 2016 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", 2017 | "dev": true 2018 | }, 2019 | "progress": { 2020 | "version": "1.1.8", 2021 | "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", 2022 | "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", 2023 | "dev": true 2024 | }, 2025 | "punycode": { 2026 | "version": "1.4.1", 2027 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 2028 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", 2029 | "dev": true 2030 | }, 2031 | "qs": { 2032 | "version": "6.3.2", 2033 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", 2034 | "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", 2035 | "dev": true 2036 | }, 2037 | "readable-stream": { 2038 | "version": "2.3.3", 2039 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", 2040 | "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", 2041 | "dev": true, 2042 | "requires": { 2043 | "core-util-is": "1.0.2", 2044 | "inherits": "2.0.3", 2045 | "isarray": "1.0.0", 2046 | "process-nextick-args": "1.0.7", 2047 | "safe-buffer": "5.1.1", 2048 | "string_decoder": "1.0.3", 2049 | "util-deprecate": "1.0.2" 2050 | } 2051 | }, 2052 | "readline2": { 2053 | "version": "1.0.1", 2054 | "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", 2055 | "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", 2056 | "dev": true, 2057 | "requires": { 2058 | "code-point-at": "1.1.0", 2059 | "is-fullwidth-code-point": "1.0.0", 2060 | "mute-stream": "0.0.5" 2061 | } 2062 | }, 2063 | "rechoir": { 2064 | "version": "0.6.2", 2065 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", 2066 | "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", 2067 | "dev": true, 2068 | "requires": { 2069 | "resolve": "1.3.3" 2070 | } 2071 | }, 2072 | "redis-commands": { 2073 | "version": "1.3.1", 2074 | "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.1.tgz", 2075 | "integrity": "sha1-gdgm9F+pyLIBH0zXoP5ZfSQdRCs=" 2076 | }, 2077 | "redis-parser": { 2078 | "version": "2.6.0", 2079 | "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", 2080 | "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" 2081 | }, 2082 | "repeat-string": { 2083 | "version": "1.6.1", 2084 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 2085 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", 2086 | "dev": true 2087 | }, 2088 | "request": { 2089 | "version": "2.79.0", 2090 | "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", 2091 | "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", 2092 | "dev": true, 2093 | "requires": { 2094 | "aws-sign2": "0.6.0", 2095 | "aws4": "1.6.0", 2096 | "caseless": "0.11.0", 2097 | "combined-stream": "1.0.5", 2098 | "extend": "3.0.1", 2099 | "forever-agent": "0.6.1", 2100 | "form-data": "2.1.4", 2101 | "har-validator": "2.0.6", 2102 | "hawk": "3.1.3", 2103 | "http-signature": "1.1.1", 2104 | "is-typedarray": "1.0.0", 2105 | "isstream": "0.1.2", 2106 | "json-stringify-safe": "5.0.1", 2107 | "mime-types": "2.1.15", 2108 | "oauth-sign": "0.8.2", 2109 | "qs": "6.3.2", 2110 | "stringstream": "0.0.5", 2111 | "tough-cookie": "2.3.2", 2112 | "tunnel-agent": "0.4.3", 2113 | "uuid": "3.1.0" 2114 | } 2115 | }, 2116 | "require-uncached": { 2117 | "version": "1.0.3", 2118 | "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", 2119 | "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", 2120 | "dev": true, 2121 | "requires": { 2122 | "caller-path": "0.1.0", 2123 | "resolve-from": "1.0.1" 2124 | } 2125 | }, 2126 | "resolve": { 2127 | "version": "1.3.3", 2128 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", 2129 | "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", 2130 | "dev": true, 2131 | "requires": { 2132 | "path-parse": "1.0.5" 2133 | } 2134 | }, 2135 | "resolve-from": { 2136 | "version": "1.0.1", 2137 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", 2138 | "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", 2139 | "dev": true 2140 | }, 2141 | "restore-cursor": { 2142 | "version": "1.0.1", 2143 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", 2144 | "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", 2145 | "dev": true, 2146 | "requires": { 2147 | "exit-hook": "1.1.1", 2148 | "onetime": "1.1.0" 2149 | } 2150 | }, 2151 | "right-align": { 2152 | "version": "0.1.3", 2153 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", 2154 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", 2155 | "dev": true, 2156 | "optional": true, 2157 | "requires": { 2158 | "align-text": "0.1.4" 2159 | } 2160 | }, 2161 | "rimraf": { 2162 | "version": "2.6.1", 2163 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", 2164 | "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", 2165 | "dev": true, 2166 | "requires": { 2167 | "glob": "7.1.2" 2168 | } 2169 | }, 2170 | "run-async": { 2171 | "version": "0.1.0", 2172 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", 2173 | "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", 2174 | "dev": true, 2175 | "requires": { 2176 | "once": "1.4.0" 2177 | } 2178 | }, 2179 | "rx-lite": { 2180 | "version": "3.1.2", 2181 | "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", 2182 | "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", 2183 | "dev": true 2184 | }, 2185 | "safe-buffer": { 2186 | "version": "5.1.1", 2187 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 2188 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", 2189 | "dev": true 2190 | }, 2191 | "samsam": { 2192 | "version": "1.2.1", 2193 | "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.2.1.tgz", 2194 | "integrity": "sha1-7dOQk6MYQ3DLhZJDsr3yVefY6mc=", 2195 | "dev": true 2196 | }, 2197 | "shelljs": { 2198 | "version": "0.7.8", 2199 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", 2200 | "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", 2201 | "dev": true, 2202 | "requires": { 2203 | "glob": "7.1.2", 2204 | "interpret": "1.0.3", 2205 | "rechoir": "0.6.2" 2206 | } 2207 | }, 2208 | "sinon": { 2209 | "version": "2.3.7", 2210 | "resolved": "https://registry.npmjs.org/sinon/-/sinon-2.3.7.tgz", 2211 | "integrity": "sha1-FFFhSi6qsFu02HbBM1zUATLsUSc=", 2212 | "dev": true, 2213 | "requires": { 2214 | "diff": "3.2.0", 2215 | "formatio": "1.2.0", 2216 | "lolex": "1.6.0", 2217 | "native-promise-only": "0.8.1", 2218 | "path-to-regexp": "1.7.0", 2219 | "samsam": "1.2.1", 2220 | "text-encoding": "0.6.4", 2221 | "type-detect": "4.0.3" 2222 | } 2223 | }, 2224 | "sinon-chai": { 2225 | "version": "2.11.0", 2226 | "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.11.0.tgz", 2227 | "integrity": "sha512-3kbzpr2q8N+M4CWkcym349ifwkXorsbw2YyVpEIvB3AKC/ebrLHXj3DySt8epKGA49zJBSgn1OvWHZ+O+aR0dA==", 2228 | "dev": true 2229 | }, 2230 | "slice-ansi": { 2231 | "version": "0.0.4", 2232 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", 2233 | "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", 2234 | "dev": true 2235 | }, 2236 | "sntp": { 2237 | "version": "1.0.9", 2238 | "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", 2239 | "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", 2240 | "dev": true, 2241 | "requires": { 2242 | "hoek": "2.16.3" 2243 | } 2244 | }, 2245 | "source-map": { 2246 | "version": "0.2.0", 2247 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", 2248 | "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", 2249 | "dev": true, 2250 | "optional": true, 2251 | "requires": { 2252 | "amdefine": "1.0.1" 2253 | } 2254 | }, 2255 | "sprintf-js": { 2256 | "version": "1.0.3", 2257 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2258 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 2259 | "dev": true 2260 | }, 2261 | "sshpk": { 2262 | "version": "1.13.1", 2263 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", 2264 | "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", 2265 | "dev": true, 2266 | "requires": { 2267 | "asn1": "0.2.3", 2268 | "assert-plus": "1.0.0", 2269 | "bcrypt-pbkdf": "1.0.1", 2270 | "dashdash": "1.14.1", 2271 | "ecc-jsbn": "0.1.1", 2272 | "getpass": "0.1.7", 2273 | "jsbn": "0.1.1", 2274 | "tweetnacl": "0.14.5" 2275 | }, 2276 | "dependencies": { 2277 | "assert-plus": { 2278 | "version": "1.0.0", 2279 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 2280 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 2281 | "dev": true 2282 | } 2283 | } 2284 | }, 2285 | "string_decoder": { 2286 | "version": "1.0.3", 2287 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 2288 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 2289 | "dev": true, 2290 | "requires": { 2291 | "safe-buffer": "5.1.1" 2292 | } 2293 | }, 2294 | "string-width": { 2295 | "version": "1.0.2", 2296 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 2297 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 2298 | "dev": true, 2299 | "requires": { 2300 | "code-point-at": "1.1.0", 2301 | "is-fullwidth-code-point": "1.0.0", 2302 | "strip-ansi": "3.0.1" 2303 | } 2304 | }, 2305 | "stringstream": { 2306 | "version": "0.0.5", 2307 | "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", 2308 | "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", 2309 | "dev": true 2310 | }, 2311 | "strip-ansi": { 2312 | "version": "3.0.1", 2313 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 2314 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 2315 | "dev": true, 2316 | "requires": { 2317 | "ansi-regex": "2.1.1" 2318 | } 2319 | }, 2320 | "strip-bom": { 2321 | "version": "3.0.0", 2322 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 2323 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", 2324 | "dev": true 2325 | }, 2326 | "strip-json-comments": { 2327 | "version": "2.0.1", 2328 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 2329 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 2330 | "dev": true 2331 | }, 2332 | "supports-color": { 2333 | "version": "2.0.0", 2334 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 2335 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", 2336 | "dev": true 2337 | }, 2338 | "table": { 2339 | "version": "3.8.3", 2340 | "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", 2341 | "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", 2342 | "dev": true, 2343 | "requires": { 2344 | "ajv": "4.11.8", 2345 | "ajv-keywords": "1.5.1", 2346 | "chalk": "1.1.3", 2347 | "lodash": "4.17.4", 2348 | "slice-ansi": "0.0.4", 2349 | "string-width": "2.1.0" 2350 | }, 2351 | "dependencies": { 2352 | "ansi-regex": { 2353 | "version": "3.0.0", 2354 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 2355 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 2356 | "dev": true 2357 | }, 2358 | "is-fullwidth-code-point": { 2359 | "version": "2.0.0", 2360 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 2361 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 2362 | "dev": true 2363 | }, 2364 | "string-width": { 2365 | "version": "2.1.0", 2366 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.0.tgz", 2367 | "integrity": "sha1-AwZkVh/BRslCPsfZeP4kV0N/5tA=", 2368 | "dev": true, 2369 | "requires": { 2370 | "is-fullwidth-code-point": "2.0.0", 2371 | "strip-ansi": "4.0.0" 2372 | } 2373 | }, 2374 | "strip-ansi": { 2375 | "version": "4.0.0", 2376 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 2377 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 2378 | "dev": true, 2379 | "requires": { 2380 | "ansi-regex": "3.0.0" 2381 | } 2382 | } 2383 | } 2384 | }, 2385 | "text-encoding": { 2386 | "version": "0.6.4", 2387 | "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", 2388 | "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", 2389 | "dev": true 2390 | }, 2391 | "text-table": { 2392 | "version": "0.2.0", 2393 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2394 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 2395 | "dev": true 2396 | }, 2397 | "through": { 2398 | "version": "2.3.8", 2399 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 2400 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 2401 | "dev": true 2402 | }, 2403 | "tough-cookie": { 2404 | "version": "2.3.2", 2405 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", 2406 | "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", 2407 | "dev": true, 2408 | "requires": { 2409 | "punycode": "1.4.1" 2410 | } 2411 | }, 2412 | "tryit": { 2413 | "version": "1.0.3", 2414 | "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", 2415 | "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", 2416 | "dev": true 2417 | }, 2418 | "tunnel-agent": { 2419 | "version": "0.4.3", 2420 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", 2421 | "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", 2422 | "dev": true 2423 | }, 2424 | "tweetnacl": { 2425 | "version": "0.14.5", 2426 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 2427 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 2428 | "dev": true, 2429 | "optional": true 2430 | }, 2431 | "type-check": { 2432 | "version": "0.3.2", 2433 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 2434 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 2435 | "dev": true, 2436 | "requires": { 2437 | "prelude-ls": "1.1.2" 2438 | } 2439 | }, 2440 | "type-detect": { 2441 | "version": "4.0.3", 2442 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz", 2443 | "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo=", 2444 | "dev": true 2445 | }, 2446 | "typedarray": { 2447 | "version": "0.0.6", 2448 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 2449 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 2450 | "dev": true 2451 | }, 2452 | "uglify-js": { 2453 | "version": "2.8.29", 2454 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", 2455 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", 2456 | "dev": true, 2457 | "optional": true, 2458 | "requires": { 2459 | "source-map": "0.5.6", 2460 | "uglify-to-browserify": "1.0.2", 2461 | "yargs": "3.10.0" 2462 | }, 2463 | "dependencies": { 2464 | "source-map": { 2465 | "version": "0.5.6", 2466 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", 2467 | "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", 2468 | "dev": true, 2469 | "optional": true 2470 | } 2471 | } 2472 | }, 2473 | "uglify-to-browserify": { 2474 | "version": "1.0.2", 2475 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", 2476 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", 2477 | "dev": true, 2478 | "optional": true 2479 | }, 2480 | "user-home": { 2481 | "version": "2.0.0", 2482 | "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", 2483 | "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", 2484 | "dev": true, 2485 | "requires": { 2486 | "os-homedir": "1.0.2" 2487 | } 2488 | }, 2489 | "util-deprecate": { 2490 | "version": "1.0.2", 2491 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2492 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 2493 | "dev": true 2494 | }, 2495 | "uuid": { 2496 | "version": "3.1.0", 2497 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", 2498 | "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", 2499 | "dev": true 2500 | }, 2501 | "verror": { 2502 | "version": "1.3.6", 2503 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", 2504 | "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", 2505 | "dev": true, 2506 | "requires": { 2507 | "extsprintf": "1.0.2" 2508 | } 2509 | }, 2510 | "which": { 2511 | "version": "1.2.14", 2512 | "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", 2513 | "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", 2514 | "dev": true, 2515 | "requires": { 2516 | "isexe": "2.0.0" 2517 | } 2518 | }, 2519 | "window-size": { 2520 | "version": "0.1.0", 2521 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", 2522 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", 2523 | "dev": true, 2524 | "optional": true 2525 | }, 2526 | "wordwrap": { 2527 | "version": "1.0.0", 2528 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 2529 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 2530 | "dev": true 2531 | }, 2532 | "wrappy": { 2533 | "version": "1.0.2", 2534 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2535 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2536 | "dev": true 2537 | }, 2538 | "write": { 2539 | "version": "0.2.1", 2540 | "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", 2541 | "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", 2542 | "dev": true, 2543 | "requires": { 2544 | "mkdirp": "0.5.1" 2545 | } 2546 | }, 2547 | "xtend": { 2548 | "version": "4.0.1", 2549 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 2550 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", 2551 | "dev": true 2552 | }, 2553 | "yargs": { 2554 | "version": "3.10.0", 2555 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", 2556 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", 2557 | "dev": true, 2558 | "optional": true, 2559 | "requires": { 2560 | "camelcase": "1.2.1", 2561 | "cliui": "2.1.0", 2562 | "decamelize": "1.2.0", 2563 | "window-size": "0.1.0" 2564 | } 2565 | } 2566 | } 2567 | } 2568 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "deepstream.io-msg-redis", 3 | "version": "1.0.5", 4 | "description": "[deepstream](http://deepstream.io) message connector for [redis](http://redis.io/)", 5 | "main": "src/message-connector.js", 6 | "scripts": { 7 | "test": "mocha", 8 | "coverage": "istanbul cover node_modules/mocha/bin/_mocha", 9 | "lint": "eslint \"src/**/*.js\" \"test/**/*.js\"", 10 | "ci": "npm run coverage" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/deepstreamIO/deepstream.io-msg-redis.git" 15 | }, 16 | "author": "deepstreamHub GmbH", 17 | "license": "Apache-2.0", 18 | "bugs": { 19 | "url": "https://github.com/deepstreamIO/deepstream.io-msg-redis/issues" 20 | }, 21 | "homepage": "http://deepstream.io", 22 | "dependencies": { 23 | "ioredis": "^3.1.1" 24 | }, 25 | "devDependencies": { 26 | "chai": "^4.0.2", 27 | "coveralls": "^2.13.1", 28 | "istanbul": "^0.4.5", 29 | "mocha": "^3.4.2", 30 | "sinon": "^2.3.7", 31 | "sinon-chai": "^2.11.0", 32 | "eslint-config-deepstream": ">=2.2.1" 33 | }, 34 | "eslintConfig": { 35 | "extends": "deepstream" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [ -z $1 ]; then 5 | echo "Please provide a release version: patch, minor or major" 6 | exit 7 | fi 8 | 9 | if [ $( npm whoami ) != "deepstreamio" ]; then 10 | echo "Please verify you can log into npm as deepstreamio before trying to release" 11 | exit 12 | fi 13 | 14 | echo 'Starting release' 15 | npm version $1 16 | 17 | echo 'Pushing to github' 18 | git push --follow-tags 19 | 20 | echo 'Publishing to npm' 21 | npm publish 22 | 23 | echo "Now we wait for the CI to build and upload artifacts to release" -------------------------------------------------------------------------------- /src/connection.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Redis = require('ioredis') 4 | const EventEmitter = require('events').EventEmitter 5 | const utils = require('util') 6 | 7 | /** 8 | * Generic connection to Redis. Can be extended or 9 | * instantiated. 10 | * 11 | * @param {Object} options A map of connection parameters 12 | * To connect to a single redis node you can use: 13 | * 14 | * { 15 | * host: 16 | * port: 17 | * [serverName]: //optional 18 | * [password]: //optional 19 | * [db]: //optional 20 | * } 21 | * 22 | * To connect to a cluster you can use: 23 | * 24 | * { 25 | * nodes: [ 26 | * // Use password "password-for-30001" for 30001 27 | * { port: , password: }, 28 | * // Don't use password when accessing 30002 29 | * { port: , password: null } 30 | * // Other nodes will use "fallback-password" 31 | * ], 32 | * redisOptions: { 33 | * password: 'fallback-password' 34 | * } 35 | * } 36 | * 37 | * For more details and options see https://github.com/luin/ioredis 38 | * @constructor 39 | */ 40 | const Connection = function (options) { 41 | this.isReady = false 42 | 43 | this._validateOptions(options) 44 | // See https://github.com/luin/ioredis/wiki/Improve-Performance 45 | if (options.nodes instanceof Array) { 46 | options.redisOptions.dropBufferSupport = true 47 | const nodes = options.nodes 48 | this.client = new Redis.Cluster(nodes, options) 49 | } else { 50 | options.dropBufferSupport = true 51 | this.client = new Redis(options) 52 | } 53 | 54 | this.client.on('ready', this._onReady.bind(this)) 55 | this.client.on('error', this._onError.bind(this)) 56 | this.client.on('end', this._onDisconnect.bind(this)) 57 | } 58 | 59 | utils.inherits(Connection, EventEmitter) 60 | 61 | /** 62 | * Callback for authentication responses 63 | * 64 | * @param {String} error Error message or null 65 | * 66 | * @void 67 | * @returns {void} 68 | */ 69 | Connection.prototype._onAuthResult = function (error) { 70 | if (error) { 71 | this._onError(`Failed to authenticate connection: ${error.toString()}`) 72 | } 73 | } 74 | 75 | /** 76 | * Callback for established connections 77 | * 78 | * @ready 79 | * @returns {void} 80 | */ 81 | Connection.prototype._onReady = function () { 82 | this.isReady = true 83 | this.emit('ready') 84 | } 85 | 86 | /** 87 | * Generic error callback 88 | * 89 | * @param {String} error 90 | * 91 | * @ready 92 | * @returns {void} 93 | */ 94 | Connection.prototype._onError = function (error) { 95 | this.emit('error', error) 96 | } 97 | 98 | /** 99 | * Callback for disconnection events 100 | * 101 | * @param {String} error reason for disconnect 102 | * 103 | * @ready 104 | * @returns {void} 105 | */ 106 | Connection.prototype._onDisconnect = function () { 107 | this._onError('disconnected') 108 | } 109 | 110 | /** 111 | * Checks if all required parameters are present 112 | * 113 | * @param {Object} options 114 | * 115 | * @ready 116 | * @returns {void} 117 | */ 118 | Connection.prototype._validateOptions = function (options) { 119 | if (!options) { 120 | throw new Error('Missing option \'host\' for redis-connector') 121 | } 122 | if (options.nodes && !(options.nodes instanceof Array)) { 123 | throw new Error('Option nodes must be an array of connection parameters for cluster') 124 | } 125 | } 126 | 127 | module.exports = Connection 128 | -------------------------------------------------------------------------------- /src/message-connector.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Connection = require('./connection') 4 | const events = require('events') 5 | const pckg = require('../package.json') 6 | const util = require('util') 7 | 8 | /** 9 | * MessageConnector that uses Redis' pub-sub capabilities for deepstream 10 | * messaging. 11 | * 12 | * Due to the forever blocking "subscriber only" nature of Redis this 13 | * establishes two connections to the redis server, one for up and one for 14 | * downstream 15 | * 16 | * @param {Object} options Redis connection options. See connection.js for details 17 | * 18 | * @constructor 19 | */ 20 | const MessageConnector = function (options) { 21 | Connection.call(this, options) 22 | 23 | this.name = pckg.name 24 | this.version = pckg.version 25 | 26 | this._senderId = options.serverName || (Math.random() * 10000000000000000000).toString(36) 27 | this._eventEmitter = new events.EventEmitter() 28 | this._publishConnection = new Connection(options) 29 | this.client.on('message', this._onMessage.bind(this)) 30 | } 31 | 32 | util.inherits(MessageConnector, Connection) 33 | 34 | /** 35 | * Gracefully close the connection to redis 36 | * 37 | * Called when deepstream.close() is invoked. 38 | * Emits 'close' event to notify deepstream of clean closure. 39 | * 40 | * @public 41 | * @returns {void} 42 | */ 43 | MessageConnector.prototype.close = function () { 44 | this.client.removeAllListeners('end') 45 | this.client.once('end', this.emit.bind(this, 'close')) 46 | this.client.quit() 47 | } 48 | 49 | /** 50 | * Removes as a listener and notifies the server 51 | * that the client is no longer interested in messages for 52 | * 53 | * @param {String} topic 54 | * @param {Function} callback 55 | * 56 | * @public 57 | * @returns {void} 58 | */ 59 | MessageConnector.prototype.unsubscribe = function (topic, callback) { 60 | this._eventEmitter.removeListener(topic, callback) 61 | if (this._hasNoListeners(topic)) { 62 | this.client.unsubscribe(topic) 63 | } 64 | } 65 | 66 | /** 67 | * Subscribe as a listener to . Multiple subscriptions 68 | * to the same topic are allowed. It's up to this class 69 | * to ensure that won't receive any messages published 70 | * by itself 71 | * 72 | * @param {String} topic 73 | * @param {Function} callback 74 | * 75 | * @public 76 | * @returns {void} 77 | */ 78 | MessageConnector.prototype.subscribe = function (topic, callback) { 79 | if (this._hasNoListeners(topic)) { 80 | this.client.subscribe(topic) 81 | } 82 | this._eventEmitter.on(topic, callback) 83 | } 84 | 85 | /** 86 | * Publish messages on a topic. 87 | * 88 | * This implementation will add the server name to the message to make sure 89 | * that the client doesn't receive messages that where send by itself 90 | * 91 | * @param {String} topic 92 | * @param {Function} callback 93 | * 94 | * @public 95 | * @returns {void} 96 | */ 97 | MessageConnector.prototype.publish = function (topic, message) { 98 | message._s = this._senderId 99 | this._publishConnection.client.publish(topic, JSON.stringify(message)) 100 | } 101 | 102 | /** 103 | * Makes sure that no listeners are left for a given topic. 104 | * This might be replaced by the more performant listenerCount(topic) in the near 105 | * future (listeners() creates a copy of the listeners array), but for the moment 106 | * we prefer to maintain backwards compatibility with Node 0.x versions. 107 | * 108 | * @param {String} topic [description] 109 | * 110 | * @returns {Boolean} hasNoListeners 111 | */ 112 | MessageConnector.prototype._hasNoListeners = function (topic) { 113 | return this._eventEmitter.listeners(topic).length === 0 114 | } 115 | 116 | /** 117 | * Callback for incoming messages. Parses the JSON stringified message, 118 | * checks that it hasn't been send by itself and is meant for a topic 119 | * that the client is subscribed to and - if so - notifies the callbacks 120 | * 121 | * @param {String} topic 122 | * @param {Function} callback 123 | * 124 | * @private 125 | * @returns {void} 126 | */ 127 | MessageConnector.prototype._onMessage = function (topic, message) { 128 | let parsedMessage 129 | 130 | try { 131 | parsedMessage = JSON.parse(message) 132 | } catch (e) { 133 | this._onError(`Error parsing message ${e.toString()}`) 134 | return 135 | } 136 | 137 | if (parsedMessage._s === this._senderId) { 138 | return 139 | } 140 | 141 | delete parsedMessage._s 142 | 143 | if (this._hasNoListeners(topic)) { 144 | this._onError(`Received message for unknown topic ${topic}`) 145 | return 146 | } 147 | 148 | this._eventEmitter.emit(topic, parsedMessage) 149 | } 150 | 151 | module.exports = MessageConnector 152 | -------------------------------------------------------------------------------- /test/message-connector-messagingSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /* global describe, xdescribe, it, expect, jasmine */ 4 | const MessageConnector = require('../src/message-connector') 5 | const expect = require('chai').expect 6 | const sinon = require('sinon') 7 | const sinonChai = require('sinon-chai') 8 | require('chai').use(sinonChai) 9 | 10 | const settings = { 11 | port: process.env.REDIS_PORT || 6379, 12 | host: process.env.REDIS_HOST || 'localhost' 13 | } 14 | const MESSAGE_TIME = 500 15 | 16 | describe('Messages are send between multiple instances', () => { 17 | let connectorA 18 | let connectorB 19 | let connectorC 20 | const callbackA1 = sinon.spy() 21 | const callbackB1 = sinon.spy() 22 | const callbackC1 = sinon.spy() 23 | 24 | it('creates connectorA', (done) => { 25 | connectorA = new MessageConnector(settings) 26 | expect(connectorA.isReady).to.equal(false) 27 | connectorA.on('ready', done) 28 | }) 29 | 30 | it('creates connectorB', (done) => { 31 | connectorB = new MessageConnector(settings) 32 | expect(connectorB.isReady).to.equal(false) 33 | connectorB.on('ready', done) 34 | }) 35 | 36 | it('creates connectorC', (done) => { 37 | connectorC = new MessageConnector(settings) 38 | expect(connectorC.isReady).to.equal(false) 39 | connectorC.on('ready', done) 40 | }) 41 | 42 | it('initialised all three connectors', () => { 43 | expect(connectorA.isReady).to.equal(true) 44 | expect(connectorB.isReady).to.equal(true) 45 | expect(connectorC.isReady).to.equal(true) 46 | }) 47 | 48 | it('subscribes to a topic', () => { 49 | connectorA.subscribe('topic1', callbackA1) 50 | connectorB.subscribe('topic1', callbackB1) 51 | connectorC.subscribe('topic1', callbackC1) 52 | expect(callbackA1).to.not.have.been.called 53 | }) 54 | 55 | it('connectorB sends a message', (done) => { 56 | connectorB.publish('topic1', { some: 'data' }) 57 | setTimeout(done, MESSAGE_TIME) 58 | }) 59 | 60 | it('connectorA and connectorC have received the message', () => { 61 | expect(callbackA1).to.have.been.calledWith({ some: 'data' }) 62 | expect(callbackB1).to.not.have.been.called 63 | expect(callbackC1).to.have.been.calledWith({ some: 'data' }) 64 | }) 65 | 66 | it('connectorC sends a message', (done) => { 67 | connectorC.publish('topic1', { other: 'value' }) 68 | setTimeout(done, MESSAGE_TIME) 69 | }) 70 | 71 | it('connectorA and connectorB have received the message', () => { 72 | expect(callbackA1).to.have.been.calledWith({ other: 'value' }) 73 | expect(callbackB1).to.have.been.calledWith({ other: 'value' }) 74 | expect(callbackC1).to.have.been.calledWith({ some: 'data' }) 75 | }) 76 | 77 | it('connectorA and connectorC send messages at the same time', (done) => { 78 | connectorA.publish('topic1', { val: 'x' }) 79 | connectorC.publish('topic1', { val: 'y' }) 80 | setTimeout(done, MESSAGE_TIME) 81 | }) 82 | 83 | it('connectorA and connectorB have received the message', () => { 84 | expect(callbackA1).to.have.been.calledWith({ val: 'y' }) 85 | expect(callbackB1).to.have.been.calledWith({ val: 'x' }) 86 | expect(callbackB1).to.have.been.calledWith({ val: 'y' }) 87 | expect(callbackC1).to.have.been.calledWith({ val: 'x' }) 88 | }) 89 | 90 | it('connectorB unsubscribes', () => { 91 | connectorB.unsubscribe('topic1', callbackB1) 92 | }) 93 | 94 | it('connectorA sends a message', (done) => { 95 | connectorA.publish('topic1', { notFor: 'B' }) 96 | setTimeout(done, MESSAGE_TIME) 97 | }) 98 | 99 | it('only connector c has received the message', () => { 100 | expect(callbackA1).to.not.have.been.calledWith({ notFor: 'B' }) 101 | expect(callbackB1).to.not.have.been.calledWith({ notFor: 'B' }) 102 | expect(callbackC1).to.have.been.calledWith({ notFor: 'B' }) 103 | }) 104 | }) 105 | 106 | // ioredis API does not have on('subscribe') and on('unsubscribe') 107 | xdescribe('Channels are subscribed and unsubscribed when neccessary', () => { 108 | // provide some setup before test 109 | let connectorA 110 | it('subscribes to a channel only once', (done) => { 111 | connectorA = new MessageConnector(settings) 112 | // check subscription only happens once when subscribing 113 | connectorA.client.on('subscribe', (channel, count) => { 114 | expect(count).to.equal(1) 115 | }) 116 | connectorA.on('ready', () => { 117 | // subscribe once 118 | connectorA.subscribe('testtopic1', () => {}) 119 | // subscribe twice 120 | connectorA.subscribe('testtopic1', () => {}) 121 | // wait for any 'subscribe' even to fire, then mark as done 122 | setTimeout(() => { 123 | connectorA.client.end(true) 124 | done() 125 | }, MESSAGE_TIME) 126 | }) 127 | }) 128 | 129 | it('does not unsubscribe from a channel when still has subscriber', (done) => { 130 | // check subscription only happens once when subscribing 131 | connectorA = new MessageConnector(settings) 132 | connectorA.client.on('unsubscribe', () => { 133 | throw new Error('Should not have unsubscribed') 134 | }) 135 | connectorA.on('ready', () => { 136 | const fn1 = () => {} 137 | // if this function gets called then test is successful as it was still subscribed 138 | const fn2 = () => { 139 | connectorA.client.end(true) 140 | done() 141 | } 142 | // subscribe once 143 | connectorA.subscribe('testtopic1', fn1) 144 | // subscribe twice 145 | connectorA.subscribe('testtopic1', fn2) 146 | // unsubscribe once 147 | connectorA.unsubscribe('testtopic1', fn1) 148 | // publish a topic to test subscription is still held 149 | connectorA.publish('testtopic1', 'test') 150 | }) 151 | }) 152 | it('does unsubscribe from a channel when it has no more subscribers', (done) => { 153 | // check subscription only happens once when subscribing 154 | connectorA = new MessageConnector(settings) 155 | // when client is unsubscribed then we have success 156 | connectorA.client.on('unsubscribe', () => { 157 | connectorA.client.end(true) 158 | done() 159 | }) 160 | connectorA.on('ready', () => { 161 | const fn1 = () => {} 162 | // if this function gets called then test is successful as it was still subscribed 163 | const fn2 = () => {} 164 | // subscribe once 165 | connectorA.subscribe('testtopic1', fn1) 166 | // subscribe twice 167 | connectorA.subscribe('testtopic1', fn2) 168 | // unsubscribe once 169 | connectorA.unsubscribe('testtopic1', fn1) 170 | // unsubscribe twice 171 | connectorA.unsubscribe('testtopic1', fn2) 172 | }) 173 | }) 174 | }) 175 | -------------------------------------------------------------------------------- /test/message-connectorSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /* global describe, it, expect, jasmine */ 4 | const MessageConnector = require('../src/message-connector') 5 | const expect = require('chai').expect 6 | const sinon = require('sinon') 7 | const sinonChai = require('sinon-chai') 8 | const EventEmitter = require('events').EventEmitter 9 | require('chai').use(sinonChai) 10 | 11 | const settings = { 12 | port: process.env.REDIS_PORT || 6379, 13 | host: process.env.REDIS_HOST || 'localhost' 14 | } 15 | 16 | describe('the message connector has the correct structure', () => { 17 | 18 | let messageConnector 19 | const errorCallback = sinon.spy() 20 | 21 | it('creates a messageConnector', (done) => { 22 | messageConnector = new MessageConnector(settings) 23 | expect(messageConnector.isReady).to.equal(false) 24 | messageConnector.on('error', errorCallback) 25 | messageConnector.on('ready', done) 26 | }) 27 | 28 | it('implements the messageConnector interface', () => { 29 | expect(typeof messageConnector.subscribe).to.equal('function') 30 | expect(typeof messageConnector.unsubscribe).to.equal('function') 31 | expect(typeof messageConnector.publish).to.equal('function') 32 | expect(typeof messageConnector.isReady).to.equal('boolean') 33 | expect(typeof messageConnector.name).to.equal('string') 34 | expect(typeof messageConnector.version).to.equal('string') 35 | expect(messageConnector instanceof EventEmitter).to.equal(true) 36 | }) 37 | 38 | it('subscribes to a topic', () => { 39 | messageConnector.subscribe('someTopic', () => {}) 40 | }) 41 | 42 | it('emits an error event when an unparsable message is received', () => { 43 | expect(errorCallback).to.not.have.been.called 44 | messageConnector._onMessage('someTopic', 'gibberish') 45 | expect(errorCallback).to.have.been.calledOnce 46 | }) 47 | 48 | it('emits an error event when a message is received for a topic the messageConnector isn\'t subscribed to', () => { 49 | messageConnector._onMessage('otherTopic', '{}') 50 | expect(errorCallback).to.have.been.calledTwice 51 | }) 52 | }) 53 | --------------------------------------------------------------------------------