├── .eslintrc ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── bin └── xkcd-password.js ├── index.js ├── lib └── cli.js ├── package-lock.json ├── package.json ├── test ├── cli.js ├── fixtures │ └── wordlist.txt └── index.js └── vendor └── mwords ├── 113809of.fic └── LICENSE /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["eslint:recommended", "prettier"], 3 | "env": { 4 | "es6": true, 5 | "node": true, 6 | "browser": true 7 | }, 8 | "rules": { 9 | "dot-notation": "error", 10 | "eqeqeq": "error", 11 | "no-loop-func": "error", 12 | "no-mixed-spaces-and-tabs": "error", 13 | "no-nested-ternary": "error", 14 | "no-shadow": "error", 15 | "no-throw-literal": "error", 16 | "prefer-const": "error" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_* 2 | lib-cov 3 | *.seed 4 | *.log 5 | *.csv 6 | *.dat 7 | *.out 8 | *.pid 9 | *.gz 10 | .sass-cache 11 | .tmp 12 | .env 13 | 14 | pids 15 | logs 16 | results 17 | 18 | npm-debug.log 19 | node_modules 20 | /working/ 21 | config.json 22 | 23 | bower_components 24 | www 25 | /datasets/ 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | - "8" 5 | - "10" 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Nathan Wittstock 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XKCD Password Generator 2 | 3 | [![Build Status](https://travis-ci.org/fardog/node-xkcd-password.svg)](https://travis-ci.org/fardog/node-xkcd-password) [![Dependency Status](https://gemnasium.com/fardog/node-xkcd-password.svg)](https://gemnasium.com/fardog/node-xkcd-password) 4 | 5 | Creates an [XKCD-style password](http://xkcd.com/936/) based on your parameters. 6 | Includes a CLI (`xkcd-password`) for your convenience, and a default wordlist. 7 | Supports both a callback-based API and [Promises/A+](http://promisesaplus.com/). 8 | 9 | > **Warning:** I am not a cryptographer, or any sort of password expert. An 10 | > audit would be greatly appreciated. 11 | 12 | ## Installation 13 | 14 | To install the module for use in your projects: 15 | 16 | ``` 17 | npm install xkcd-password 18 | ``` 19 | 20 | Or a global install to get the commandline client: 21 | 22 | ``` 23 | npm install xkcd-password -g 24 | ``` 25 | 26 | This will make the `xkcd-password` command available on your path. 27 | 28 | ## Usage 29 | 30 | This can be used both as a module in another application, or when installed 31 | globally, via a commandline application. 32 | 33 | ### CLI 34 | 35 | ``` 36 | $ xkcd-password --help 37 | 38 | Usage: xkcd-password [options] 39 | 40 | Options: 41 | -n, --numWords The number of words to generate for your password. [4] 42 | -m, --minLength Minimum lengh of words chosen for the generated password. [5] 43 | -x, --maxLength Maximum length of words chosen for the generated password. [8] 44 | -f, --wordFile The newline-delimited list of words to be used as the source. 45 | -s, --separator The separator character to use between words when output to the console. [ ] 46 | --version print version and exit 47 | ``` 48 | 49 | ### Module 50 | 51 | ```js 52 | var xkcdPassword = require('xkcd-password') 53 | var pw = new xkcdPassword() 54 | 55 | var options = { 56 | numWords: 4, 57 | minLength: 5, 58 | maxLength: 8 59 | } 60 | 61 | // using callbacks 62 | pw.generate(options, function (err, result) { 63 | console.log(result) // ['distome', 'pantries', 'sending', 'weiner'] 64 | }) 65 | 66 | 67 | // or, with promises 68 | pw.generate(options).then(function (result) { 69 | console.log(result) // [ 'crambo', 'piled', 'procural', 'plunk' ] 70 | }).catch(function(err) { 71 | if (!err) { 72 | console.log('No errors here!') 73 | } 74 | }) 75 | ``` 76 | 77 | ## Environment Variables 78 | 79 | - **DISABLE_LOOP_PREVENTION** 80 | It's possible for you to ask for a very specific list of words—say, 100 two 81 | character passwords—which would fail if you didn't have enough words of that 82 | size, but your wordlist was big enough—say 1000 words. As such, loop prevention 83 | was added in v1.1.0. If you'd like to disable this prevention, set 84 | `DISABLE_LOOP_PREVENTION` to a truth-y value. 85 | 86 | ## Notes 87 | 88 | - The CLI will set the minimum word length to 1 if the maximum word length 89 | requested is below the default minimum word length (5), and the minimum is not 90 | set. This is as of version 1.2.0. This is to simplify asking for very small 91 | words from the CLI. This does not apply to using the module in your 92 | applications, just the CLI. 93 | 94 | ## Known Bugs 95 | 96 | - Trying to generate more a large number of words in a single `generate()` call 97 | may overflow the call stack. You'll usually be fine up to 2500 words though so 98 | it's not much of a problem. 99 | 100 | ## Contributing 101 | 102 | Feel free to send pull requests! I'm not picky, but would like the following: 103 | 104 | 1. Write tests for any new features, and do not break existing tests. 105 | 2. Be sure to point out any changes that break API. 106 | 107 | ## History 108 | 109 | - **v2.0.0** 110 | Update all dependencies and require Node.js 4 and above. — _[@cabbiepete][]_ 111 | Updates to [standard](http://standardjs.com) style. — _[@fardog][]_ 112 | Move tests to [tape](https://www.npmjs.com/package/tape). — _[@fardog][]_ 113 | Allow use without the `new` keyword. — _[@fardog][]_ 114 | 115 | - **v1.2.0** 116 | Replaces [nomnom][nomnom] with [minimist][minimist], and adds a custom validator 117 | for CLI options. 118 | 119 | - **v1.1.1** 120 | Updates dependencies and internal documentation. Adds dependency badge. 121 | 122 | - **v1.1.0** 123 | Doesn't use promises unless you haven't specified a callback. Prevents the 124 | generator from entering an infinite loop. Adds additional checks on minimum and 125 | maximum word length options. 126 | 127 | - **v1.0.0** 128 | API now supports Promises as well as callbacks. 129 | 130 | - **v0.2.7** 131 | Updates to the latest version of [random-lib][randomlib] and debug. 132 | 133 | - **v0.2.6** 134 | Updates to the latest version of [async][async], so that xkcd-password 135 | and [random-lib][randomlib] use the same version. 136 | 137 | - **v0.2.5** 138 | Additional tests. 139 | 140 | - **v0.2.4** 141 | Avoids [releasing Zalgo][zalgo] on errors. 142 | 143 | - **v0.2.3** 144 | Smarter rewrite of word generation function based on additional functionality 145 | that [random-lib][randomlib] provides. Additional tests. 146 | 147 | - **v0.2.2** 148 | Now uses my [random-lib][randomlib] wrapper for `crypto.randomBytes()`. 149 | 150 | - **v0.2.1** 151 | Now uses Node's `crypto.randomBytes()` for its PRNG, rather than Math.random() 152 | in most cases. 153 | 154 | - **v0.2.0** 155 | Changes generation function to accept an "options" object rather than discrete 156 | parameters to the generate function. Provides defaults if options aren't given. 157 | 158 | [async]: http://github.com/caolan/async/ 159 | [randomlib]: http://www.npmjs.org/package/random-lib/ 160 | [nomnom]: https://www.npmjs.org/package/nomnom 161 | [minimist]: https://www.npmjs.org/package/minimist 162 | [zalgo]: http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony 163 | [@cabbiepete]: https://github.com/cabbiepete 164 | [@fardog]: https://github.com/fardog 165 | 166 | ## The MIT License (MIT) 167 | 168 | Copyright (c) 2014 Nathan Wittstock 169 | 170 | Permission is hereby granted, free of charge, to any person obtaining a copy of 171 | this software and associated documentation files (the "Software"), to deal in 172 | the Software without restriction, including without limitation the rights to 173 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 174 | the Software, and to permit persons to whom the Software is furnished to do so, 175 | subject to the following conditions: 176 | 177 | The above copyright notice and this permission notice shall be included in all 178 | copies or substantial portions of the Software. 179 | 180 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 181 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 182 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 183 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 184 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 185 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 186 | 187 | ## Grady Ward's Moby 188 | 189 | This project includes a wordlist taken from Grady Ward's Moby II, a list of 190 | words that has been placed in the public domain. 191 | 192 | ### License 193 | 194 | The Moby lexicon project is complete and has 195 | been place into the public domain. Use, sell, 196 | rework, excerpt and use in any way on any platform. 197 | 198 | Placing this material on internal or public servers is 199 | also encouraged. The compiler is not aware of any 200 | export restrictions so freely distribute world-wide. 201 | 202 | You can verify the public domain status by contacting 203 | 204 | Grady Ward 205 | 3449 Martha Ct. 206 | Arcata, CA 95521-4884 207 | -------------------------------------------------------------------------------- /bin/xkcd-password.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * xkcd-password commandline utility. 4 | * 5 | * @since 0.0.1 6 | */ 7 | var chalk = require("chalk") 8 | var error = chalk.bold.red 9 | var Cli = require("../lib/cli.js") 10 | 11 | var cli = new Cli() 12 | 13 | /* eslint-disable no-console */ 14 | cli.parse(process.argv.slice(2), function(err, message, options) { 15 | if (err) { 16 | console.error( 17 | error( 18 | "\nYou had errors in your syntax. Use --help for further information." 19 | ) 20 | ) 21 | err.forEach(function(e) { 22 | console.error(e.message) 23 | }) 24 | } else if (message) { 25 | console.log(message) 26 | } else { 27 | var XKCDPassword = require("../") 28 | var pw = null 29 | 30 | // use the word file if we were given one 31 | if (options.wordFile) { 32 | pw = new XKCDPassword().initWithWordFile(options.wordFile) 33 | } else { 34 | pw = new XKCDPassword() 35 | } 36 | 37 | // generate the password, output the result 38 | pw.generate(options) 39 | .then(function(result) { 40 | console.log(result.join(options.separator)) 41 | }) 42 | // eslint-disable-next-line no-shadow 43 | .catch(function(err) { 44 | console.error(error("\nThere was an error generating your password.")) 45 | console.error(err.message) 46 | process.exit(1) 47 | }) 48 | } 49 | }) 50 | /* eslint-enable no-console */ 51 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @overview An XKCD-style password generator for Node.js 3 | * 4 | * @author Nathan Wittstock 5 | * @copyright 2014 Nathan Wittstock 6 | * @license MIT - See the included 'LICENSE' for details. 7 | * @version 2.0.0 8 | * @extends EventEmitter 9 | */ 10 | var fs = require("fs") 11 | var path = require("path") 12 | var util = require("util") 13 | var events = require("events") 14 | var async = require("async") 15 | var rand = require("random-lib") 16 | var when = require("when") 17 | 18 | var DEFAULTS = { 19 | numWords: 4, 20 | minLength: 5, 21 | maxLength: 8 22 | } 23 | 24 | module.exports = XKCDPassword 25 | 26 | /** 27 | * Creates the password generator. 28 | * 29 | * @constructor 30 | * @since 0.0.1 31 | * 32 | * @returns {Generator} the word generator 33 | */ 34 | function XKCDPassword() { 35 | if (!(this instanceof XKCDPassword)) return new XKCDPassword() 36 | 37 | var self = this 38 | 39 | events.EventEmitter.call(self) 40 | 41 | self.wordlist = null 42 | self.wordfile = null 43 | 44 | // if we've got a wordlist at the ready 45 | self.ready = false 46 | self.initialized = false 47 | 48 | return this 49 | } 50 | 51 | // Extends EventEmitter 52 | util.inherits(XKCDPassword, events.EventEmitter) 53 | 54 | /** 55 | * Initializes the password generator with a pre-defined word list. 56 | * 57 | * @since 0.0.1 58 | * @param {array} wordlist - The array of words to use. 59 | * 60 | * @returns {Generator} the word generator 61 | */ 62 | XKCDPassword.prototype.initWithWordList = function(wordlist) { 63 | var self = this 64 | 65 | // verify that the wordlist is an appropriate object 66 | if (typeof wordlist === "object" && wordlist.length > 0) { 67 | self.wordlist = wordlist 68 | self.ready = true 69 | 70 | return self 71 | } else { 72 | throw new Error("Wordlist provided was not an array.") 73 | } 74 | } 75 | 76 | /** 77 | * Initializes the generator 78 | * 79 | * @since 0.2.0 80 | * @param {object} options 81 | * 82 | * @emits {Generator} 'ready' event 83 | */ 84 | XKCDPassword.prototype._initialize = function() { 85 | var self = this 86 | 87 | self.initialized = true 88 | 89 | // We don't have a wordlist yet, and need to get one 90 | if (!self.wordlist) { 91 | if (!self.wordfile) { 92 | // use internal wordlist 93 | self.wordfile = path.join(__dirname, "./vendor/mwords/113809of.fic") 94 | } 95 | 96 | // perform our file reading asynchronously, then call the _generate function 97 | self.wordlist = [] 98 | require("readline") 99 | .createInterface({ 100 | input: fs.createReadStream(self.wordfile), 101 | terminal: false 102 | }) 103 | .on("line", function readWordFileLine(line) { 104 | // append to internal wordlist 105 | self.wordlist.push(line) 106 | }) 107 | .on("close", function resolveReadOfWordFile() { 108 | // emit that we're ready, and call the next function 109 | self.ready = true 110 | self.emit("ready", self) 111 | }) 112 | } 113 | } 114 | 115 | /** 116 | * Initializes the password generator with a newline delimited word file. 117 | * 118 | * @since 0.0.1 119 | * @param {string} wordfile - Path to the word file to be used. 120 | * 121 | * @returns {Generator} the word generator 122 | */ 123 | XKCDPassword.prototype.initWithWordFile = function(wordfile) { 124 | var self = this 125 | 126 | if (typeof wordfile !== "string") { 127 | throw new Error("Wordfile provided was not a string.") 128 | } else { 129 | self.wordfile = wordfile 130 | 131 | return self 132 | } 133 | } 134 | 135 | /** 136 | * Parses the options and generates the password. 137 | * 138 | * @since 0.2.0 139 | * @param {object} options - The object containing options, or alternately a 140 | * number which is just the words to generate, everything else default. 141 | * @param {generateCallback} next - The callback function to call after 142 | * generation. 143 | * 144 | * @returns {Promise} the promise object 145 | */ 146 | XKCDPassword.prototype.generate = function(options, next) { 147 | var self = this 148 | 149 | var numWords = DEFAULTS.numWords 150 | var minLength = DEFAULTS.minLength 151 | var maxLength = DEFAULTS.maxLength 152 | 153 | var deferred = null 154 | 155 | if (typeof options === "number") { 156 | numWords = options 157 | } else if (typeof options === "function") { 158 | next = options 159 | options = DEFAULTS 160 | } else if (typeof options !== "undefined" && options) { 161 | if (typeof options.numWords === "number") { 162 | numWords = options.numWords 163 | } 164 | if (typeof options.minLength === "number") { 165 | minLength = options.minLength 166 | } 167 | if (typeof options.maxLength === "number") { 168 | maxLength = options.maxLength 169 | } 170 | } 171 | 172 | if (!next || typeof next !== "function") { 173 | next = function() {} 174 | deferred = when.defer() 175 | } 176 | 177 | if (self.ready) { 178 | self._generate(numWords, minLength, maxLength, next, deferred) 179 | } else { 180 | self.on("ready", function onReadyGenerate() { 181 | self._generate(numWords, minLength, maxLength, next, deferred) 182 | }) 183 | 184 | // run the init if we haven't already 185 | if (!self.initialized) { 186 | self._initialize() 187 | } 188 | } 189 | 190 | return deferred ? deferred.promise : null 191 | } 192 | 193 | /** 194 | * Callback executed after password is generated. 195 | * 196 | * @since 0.0.1 197 | * @callback {generateCallback} 198 | * @param {Error} err - Error if there was one, null if not. 199 | * @param {array} result - Resulting array of words. 200 | */ 201 | 202 | /** 203 | * Actual word generation function that is called after everything is 204 | * initialized. Should not be used directly. 205 | * 206 | * @since 0.0.1 207 | * @param {integer} numWords - Number of words to generate. 208 | * @param {integer} minLength - The minimum length of a word to use. 209 | * @param {integer} maxLength - The maximum length of a word to use. 210 | * @param {generateCallback} next - The callback function to call after or none 211 | * @param {Object} deferred - The promise to resolve, or none 212 | * generation. 213 | */ 214 | XKCDPassword.prototype._generate = function( 215 | numWords, 216 | minLength, 217 | maxLength, 218 | next, 219 | deferred 220 | ) { 221 | var self = this 222 | 223 | numWords = parseInt(numWords, 10) 224 | minLength = parseInt(minLength, 10) 225 | maxLength = parseInt(maxLength, 10) 226 | 227 | var err = null 228 | 229 | // ensure that required parameters have been set 230 | if (numWords <= 0 || minLength < 0 || maxLength < 2) { 231 | err = new Error("Parameters provided were not correct.") 232 | process.nextTick(function resolveParametersError() { 233 | next(err) 234 | if (deferred) { 235 | deferred.reject(err) 236 | } 237 | }) 238 | } else if (numWords > self.wordlist.length) { 239 | // make sure we're not asking for more unique words than we have available 240 | err = new Error( 241 | "More words than were available in the wordlist were requested." 242 | ) 243 | process.nextTick(function resolveTooManyWordsError() { 244 | next(err) 245 | if (deferred) { 246 | deferred.reject(err) 247 | } 248 | }) 249 | } else if (maxLength < minLength) { 250 | err = new Error( 251 | "Your maximum word length can't be less than your minimum length. " + 252 | "Try specifying a maximum length and minimum length directly." 253 | ) 254 | process.nextTick(function resolveMaxLengthIncorrectError() { 255 | next(err) 256 | if (deferred) { 257 | deferred.reject(err) 258 | } 259 | }) 260 | } else { 261 | // generate the numbers 262 | // because we want to generate unique numbers 263 | rand.randomInts( 264 | { unique: true, num: numWords, min: 0, max: self.wordlist.length }, 265 | // eslint-disable-next-line no-shadow 266 | function generateWords(err, ints) { 267 | if (err) { 268 | next(err) 269 | if (deferred) { 270 | deferred.reject(err) 271 | } 272 | return 273 | } 274 | var position = 0 275 | var numLoops = 0 276 | var words = [] 277 | 278 | async.doWhilst( 279 | function generateWord(callback) { 280 | // if the word is too short, we need a new random number 281 | if ( 282 | self.wordlist[ints[position]].length > maxLength || 283 | self.wordlist[ints[position]].length < minLength 284 | ) { 285 | rand.randomInt( 286 | { min: 0, max: self.wordlist.length - 1 }, 287 | // eslint-disable-next-line no-shadow 288 | function generateAnotherInt(err, int) { 289 | if (err) return callback(err) 290 | 291 | if (ints.indexOf(int) > -1) { 292 | // we already found that random number, run callback to make the loop again 293 | callback() 294 | } else { 295 | // replace the integer in that position and run the loop again 296 | ints[position] = int 297 | callback() 298 | } 299 | } 300 | ) 301 | } else { 302 | // it's a good word, push it onto the stack 303 | words.push(self.wordlist[ints[position]]) 304 | position++ 305 | callback() 306 | } 307 | }, 308 | function postCheckGeneration() { 309 | if (!process.env.DISABLE_LOOP_PREVENTION) { 310 | if ( 311 | numLoops > 312 | (numWords * 10000 > 850000 ? 850000 : numWords * 10000) 313 | ) { 314 | return false 315 | } 316 | numLoops++ 317 | } 318 | return words.length < numWords 319 | }, 320 | // eslint-disable-next-line no-shadow 321 | function resolveGeneration(err) { 322 | if (err) { 323 | next(err) 324 | if (deferred) { 325 | deferred.reject(err) 326 | } 327 | } else if (words.length < numWords) { 328 | var tooFewWordsError = new Error( 329 | "You asked for more words than could be generated. This may " + 330 | "because you're asking for too many words of a certain length." 331 | ) 332 | 333 | next(tooFewWordsError) 334 | if (deferred) { 335 | deferred.reject(tooFewWordsError) 336 | } 337 | } else { 338 | next(null, words) 339 | if (deferred) { 340 | deferred.resolve(words) 341 | } 342 | } 343 | } 344 | ) 345 | } 346 | ) 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /lib/cli.js: -------------------------------------------------------------------------------- 1 | var chalk = require("chalk") 2 | var parseArgs = require("minimist") 3 | 4 | // Number.isInteger() polyfill :: 5 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger 6 | if (!Number.isInteger) { 7 | Number.isInteger = function isInteger(nVal) { 8 | return ( 9 | typeof nVal === "number" && 10 | isFinite(nVal) && 11 | nVal > -9007199254740992 && 12 | nVal < 9007199254740992 && 13 | Math.floor(nVal) === nVal 14 | ) 15 | } 16 | } 17 | 18 | module.exports = CLI 19 | 20 | function CLI() { 21 | if (!(this instanceof CLI)) return new CLI() 22 | 23 | this.options = { 24 | alias: { 25 | numWords: "n", 26 | minLength: "m", 27 | maxLength: "x", 28 | wordFile: "f", 29 | separator: "s", 30 | version: "v", 31 | help: "h" 32 | }, 33 | default: { 34 | separator: " " 35 | }, 36 | boolean: ["version", "help"], 37 | string: ["wordFile", "separator"] 38 | } 39 | 40 | this.errors = [] 41 | this.message = null 42 | 43 | this.helpMessage = [ 44 | chalk.bold.blue("Usage: xkcd-password [options]"), 45 | "", 46 | "Options:", 47 | " -n, --numWords The number of words to generate for your password. [4]", 48 | " -m, --minLength Minimum lengh of words chosen for the generated password. [5]", 49 | " -x, --maxLength Maximum length of words chosen for the generated password. [8]", 50 | " -f, --wordFile Path to a newline-delimited list of words to be used as the source.", 51 | " -s, --separator The separator character to use between words when output to the console. [ ]", 52 | " --version print version and exit" 53 | ] 54 | 55 | return this 56 | } 57 | 58 | CLI.prototype.parse = function(argv, next) { 59 | var options = parseArgs(argv, this.options) 60 | 61 | if (options.version) { 62 | var pkg = require("../package.json") 63 | this.message = pkg.version 64 | } else if (options.help) { 65 | this.message = this.helpMessage.join("\n") 66 | } else { 67 | /* 68 | * Options are processed in a significant order; we only save the last error 69 | * message, so we'll want to make sure the most significant are last 70 | */ 71 | 72 | // ensure that parameter-expecting options have parameters 73 | ;["wordFile", "separator"].forEach( 74 | function(i) { 75 | if (typeof options[i] !== "undefined") { 76 | if (typeof options[i] !== "string" || options[i].length < 1) { 77 | this.errors.push(new Error(i + " expects a value.")) 78 | } 79 | } 80 | }.bind(this) 81 | ) 82 | 83 | // ensure that number-expecting options have parameters 84 | ;["numWords", "minLength", "maxLength"].forEach( 85 | function(i) { 86 | if (typeof options[i] !== "undefined") { 87 | if (!Number.isInteger(options[i])) { 88 | this.errors.push(new Error(i + " expects an integer value.")) 89 | } 90 | } 91 | }.bind(this) 92 | ) 93 | 94 | // now we mangle minLength to be maxLength or less, if maxLength is smaller 95 | // we only do this for the CLI, not for the module itself 96 | if (!options.minLength && options.maxLength && options.maxLength < 5) { 97 | options.minLength = 1 98 | } 99 | } 100 | 101 | this.parsedOptions = options 102 | 103 | if (typeof next === "function") { 104 | // we return the array of errors if there are any, otherwise null 105 | next(this.errors.length > 0 ? this.errors : null, this.message, options) 106 | } 107 | 108 | return this 109 | } 110 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xkcd-password", 3 | "version": "2.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "acorn": { 8 | "version": "5.7.1", 9 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", 10 | "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", 11 | "dev": true 12 | }, 13 | "acorn-jsx": { 14 | "version": "4.1.1", 15 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", 16 | "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", 17 | "dev": true, 18 | "requires": { 19 | "acorn": "5.7.1" 20 | } 21 | }, 22 | "ajv": { 23 | "version": "6.5.2", 24 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", 25 | "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", 26 | "dev": true, 27 | "requires": { 28 | "fast-deep-equal": "2.0.1", 29 | "fast-json-stable-stringify": "2.0.0", 30 | "json-schema-traverse": "0.4.1", 31 | "uri-js": "4.2.2" 32 | } 33 | }, 34 | "ajv-keywords": { 35 | "version": "3.2.0", 36 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", 37 | "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", 38 | "dev": true 39 | }, 40 | "ansi-escapes": { 41 | "version": "3.1.0", 42 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", 43 | "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", 44 | "dev": true 45 | }, 46 | "ansi-regex": { 47 | "version": "2.1.1", 48 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 49 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 50 | }, 51 | "ansi-styles": { 52 | "version": "2.2.1", 53 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 54 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 55 | }, 56 | "argparse": { 57 | "version": "1.0.10", 58 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 59 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 60 | "dev": true, 61 | "requires": { 62 | "sprintf-js": "1.0.3" 63 | } 64 | }, 65 | "array-union": { 66 | "version": "1.0.2", 67 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", 68 | "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", 69 | "dev": true, 70 | "requires": { 71 | "array-uniq": "1.0.3" 72 | } 73 | }, 74 | "array-uniq": { 75 | "version": "1.0.3", 76 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 77 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", 78 | "dev": true 79 | }, 80 | "arrify": { 81 | "version": "1.0.1", 82 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 83 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 84 | "dev": true 85 | }, 86 | "asap": { 87 | "version": "2.0.6", 88 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 89 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" 90 | }, 91 | "async": { 92 | "version": "2.6.1", 93 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", 94 | "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", 95 | "requires": { 96 | "lodash": "4.17.10" 97 | } 98 | }, 99 | "babel-code-frame": { 100 | "version": "6.26.0", 101 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", 102 | "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", 103 | "dev": true, 104 | "requires": { 105 | "chalk": "1.1.3", 106 | "esutils": "2.0.2", 107 | "js-tokens": "3.0.2" 108 | } 109 | }, 110 | "balanced-match": { 111 | "version": "1.0.0", 112 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 113 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 114 | "dev": true 115 | }, 116 | "brace-expansion": { 117 | "version": "1.1.11", 118 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 119 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 120 | "dev": true, 121 | "requires": { 122 | "balanced-match": "1.0.0", 123 | "concat-map": "0.0.1" 124 | } 125 | }, 126 | "caller-path": { 127 | "version": "0.1.0", 128 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", 129 | "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", 130 | "dev": true, 131 | "requires": { 132 | "callsites": "0.2.0" 133 | } 134 | }, 135 | "callsites": { 136 | "version": "0.2.0", 137 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", 138 | "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", 139 | "dev": true 140 | }, 141 | "chalk": { 142 | "version": "1.1.3", 143 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 144 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 145 | "requires": { 146 | "ansi-styles": "2.2.1", 147 | "escape-string-regexp": "1.0.5", 148 | "has-ansi": "2.0.0", 149 | "strip-ansi": "3.0.1", 150 | "supports-color": "2.0.0" 151 | } 152 | }, 153 | "chardet": { 154 | "version": "0.4.2", 155 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", 156 | "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", 157 | "dev": true 158 | }, 159 | "circular-json": { 160 | "version": "0.3.3", 161 | "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", 162 | "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", 163 | "dev": true 164 | }, 165 | "cli-cursor": { 166 | "version": "2.1.0", 167 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 168 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 169 | "dev": true, 170 | "requires": { 171 | "restore-cursor": "2.0.0" 172 | } 173 | }, 174 | "cli-width": { 175 | "version": "2.2.0", 176 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 177 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", 178 | "dev": true 179 | }, 180 | "color-convert": { 181 | "version": "1.9.2", 182 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", 183 | "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", 184 | "dev": true, 185 | "requires": { 186 | "color-name": "1.1.1" 187 | } 188 | }, 189 | "color-name": { 190 | "version": "1.1.1", 191 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", 192 | "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", 193 | "dev": true 194 | }, 195 | "concat-map": { 196 | "version": "0.0.1", 197 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 198 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 199 | "dev": true 200 | }, 201 | "cross-spawn": { 202 | "version": "6.0.5", 203 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", 204 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", 205 | "dev": true, 206 | "requires": { 207 | "nice-try": "1.0.4", 208 | "path-key": "2.0.1", 209 | "semver": "5.5.0", 210 | "shebang-command": "1.2.0", 211 | "which": "1.3.1" 212 | } 213 | }, 214 | "debug": { 215 | "version": "3.1.0", 216 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 217 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 218 | "dev": true, 219 | "requires": { 220 | "ms": "2.0.0" 221 | } 222 | }, 223 | "deep-equal": { 224 | "version": "1.0.1", 225 | "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", 226 | "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", 227 | "dev": true 228 | }, 229 | "deep-is": { 230 | "version": "0.1.3", 231 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 232 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 233 | "dev": true 234 | }, 235 | "define-properties": { 236 | "version": "1.1.2", 237 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", 238 | "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", 239 | "dev": true, 240 | "requires": { 241 | "foreach": "2.0.5", 242 | "object-keys": "1.0.12" 243 | } 244 | }, 245 | "defined": { 246 | "version": "1.0.0", 247 | "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", 248 | "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", 249 | "dev": true 250 | }, 251 | "del": { 252 | "version": "2.2.2", 253 | "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", 254 | "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", 255 | "dev": true, 256 | "requires": { 257 | "globby": "5.0.0", 258 | "is-path-cwd": "1.0.0", 259 | "is-path-in-cwd": "1.0.1", 260 | "object-assign": "4.1.1", 261 | "pify": "2.3.0", 262 | "pinkie-promise": "2.0.1", 263 | "rimraf": "2.6.2" 264 | } 265 | }, 266 | "dezalgo": { 267 | "version": "1.0.3", 268 | "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", 269 | "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", 270 | "requires": { 271 | "asap": "2.0.6", 272 | "wrappy": "1.0.2" 273 | } 274 | }, 275 | "doctrine": { 276 | "version": "2.1.0", 277 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 278 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 279 | "dev": true, 280 | "requires": { 281 | "esutils": "2.0.2" 282 | } 283 | }, 284 | "es-abstract": { 285 | "version": "1.12.0", 286 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", 287 | "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", 288 | "dev": true, 289 | "requires": { 290 | "es-to-primitive": "1.1.1", 291 | "function-bind": "1.1.1", 292 | "has": "1.0.3", 293 | "is-callable": "1.1.4", 294 | "is-regex": "1.0.4" 295 | } 296 | }, 297 | "es-to-primitive": { 298 | "version": "1.1.1", 299 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", 300 | "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", 301 | "dev": true, 302 | "requires": { 303 | "is-callable": "1.1.4", 304 | "is-date-object": "1.0.1", 305 | "is-symbol": "1.0.1" 306 | } 307 | }, 308 | "es6-promise": { 309 | "version": "3.3.1", 310 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", 311 | "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" 312 | }, 313 | "escape-string-regexp": { 314 | "version": "1.0.5", 315 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 316 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 317 | }, 318 | "eslint": { 319 | "version": "5.2.0", 320 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.2.0.tgz", 321 | "integrity": "sha512-zlggW1qp7/TBjwLfouRoY7eWXrXwJZFqCdIxxh0/LVB/QuuKuIMkzyUZEcDo6LBadsry5JcEMxIqd3H/66CXVg==", 322 | "dev": true, 323 | "requires": { 324 | "ajv": "6.5.2", 325 | "babel-code-frame": "6.26.0", 326 | "chalk": "2.4.1", 327 | "cross-spawn": "6.0.5", 328 | "debug": "3.1.0", 329 | "doctrine": "2.1.0", 330 | "eslint-scope": "4.0.0", 331 | "eslint-utils": "1.3.1", 332 | "eslint-visitor-keys": "1.0.0", 333 | "espree": "4.0.0", 334 | "esquery": "1.0.1", 335 | "esutils": "2.0.2", 336 | "file-entry-cache": "2.0.0", 337 | "functional-red-black-tree": "1.0.1", 338 | "glob": "7.1.2", 339 | "globals": "11.7.0", 340 | "ignore": "4.0.2", 341 | "imurmurhash": "0.1.4", 342 | "inquirer": "5.2.0", 343 | "is-resolvable": "1.1.0", 344 | "js-yaml": "3.12.0", 345 | "json-stable-stringify-without-jsonify": "1.0.1", 346 | "levn": "0.3.0", 347 | "lodash": "4.17.10", 348 | "minimatch": "3.0.4", 349 | "mkdirp": "0.5.1", 350 | "natural-compare": "1.4.0", 351 | "optionator": "0.8.2", 352 | "path-is-inside": "1.0.2", 353 | "pluralize": "7.0.0", 354 | "progress": "2.0.0", 355 | "regexpp": "1.1.0", 356 | "require-uncached": "1.0.3", 357 | "semver": "5.5.0", 358 | "string.prototype.matchall": "2.0.0", 359 | "strip-ansi": "4.0.0", 360 | "strip-json-comments": "2.0.1", 361 | "table": "4.0.3", 362 | "text-table": "0.2.0" 363 | }, 364 | "dependencies": { 365 | "ansi-regex": { 366 | "version": "3.0.0", 367 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 368 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 369 | "dev": true 370 | }, 371 | "ansi-styles": { 372 | "version": "3.2.1", 373 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 374 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 375 | "dev": true, 376 | "requires": { 377 | "color-convert": "1.9.2" 378 | } 379 | }, 380 | "chalk": { 381 | "version": "2.4.1", 382 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 383 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 384 | "dev": true, 385 | "requires": { 386 | "ansi-styles": "3.2.1", 387 | "escape-string-regexp": "1.0.5", 388 | "supports-color": "5.4.0" 389 | } 390 | }, 391 | "strip-ansi": { 392 | "version": "4.0.0", 393 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 394 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 395 | "dev": true, 396 | "requires": { 397 | "ansi-regex": "3.0.0" 398 | } 399 | }, 400 | "supports-color": { 401 | "version": "5.4.0", 402 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", 403 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", 404 | "dev": true, 405 | "requires": { 406 | "has-flag": "3.0.0" 407 | } 408 | } 409 | } 410 | }, 411 | "eslint-config-prettier": { 412 | "version": "2.9.0", 413 | "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz", 414 | "integrity": "sha512-ag8YEyBXsm3nmOv1Hz991VtNNDMRa+MNy8cY47Pl4bw6iuzqKbJajXdqUpiw13STdLLrznxgm1hj9NhxeOYq0A==", 415 | "dev": true, 416 | "requires": { 417 | "get-stdin": "5.0.1" 418 | } 419 | }, 420 | "eslint-scope": { 421 | "version": "4.0.0", 422 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", 423 | "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", 424 | "dev": true, 425 | "requires": { 426 | "esrecurse": "4.2.1", 427 | "estraverse": "4.2.0" 428 | } 429 | }, 430 | "eslint-utils": { 431 | "version": "1.3.1", 432 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", 433 | "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", 434 | "dev": true 435 | }, 436 | "eslint-visitor-keys": { 437 | "version": "1.0.0", 438 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", 439 | "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", 440 | "dev": true 441 | }, 442 | "espree": { 443 | "version": "4.0.0", 444 | "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", 445 | "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", 446 | "dev": true, 447 | "requires": { 448 | "acorn": "5.7.1", 449 | "acorn-jsx": "4.1.1" 450 | } 451 | }, 452 | "esprima": { 453 | "version": "4.0.1", 454 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 455 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 456 | "dev": true 457 | }, 458 | "esquery": { 459 | "version": "1.0.1", 460 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", 461 | "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", 462 | "dev": true, 463 | "requires": { 464 | "estraverse": "4.2.0" 465 | } 466 | }, 467 | "esrecurse": { 468 | "version": "4.2.1", 469 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", 470 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", 471 | "dev": true, 472 | "requires": { 473 | "estraverse": "4.2.0" 474 | } 475 | }, 476 | "estraverse": { 477 | "version": "4.2.0", 478 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", 479 | "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", 480 | "dev": true 481 | }, 482 | "esutils": { 483 | "version": "2.0.2", 484 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 485 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 486 | "dev": true 487 | }, 488 | "external-editor": { 489 | "version": "2.2.0", 490 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", 491 | "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", 492 | "dev": true, 493 | "requires": { 494 | "chardet": "0.4.2", 495 | "iconv-lite": "0.4.23", 496 | "tmp": "0.0.33" 497 | } 498 | }, 499 | "fast-deep-equal": { 500 | "version": "2.0.1", 501 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 502 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", 503 | "dev": true 504 | }, 505 | "fast-json-stable-stringify": { 506 | "version": "2.0.0", 507 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 508 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", 509 | "dev": true 510 | }, 511 | "fast-levenshtein": { 512 | "version": "2.0.6", 513 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 514 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 515 | "dev": true 516 | }, 517 | "figures": { 518 | "version": "2.0.0", 519 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 520 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 521 | "dev": true, 522 | "requires": { 523 | "escape-string-regexp": "1.0.5" 524 | } 525 | }, 526 | "file-entry-cache": { 527 | "version": "2.0.0", 528 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", 529 | "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", 530 | "dev": true, 531 | "requires": { 532 | "flat-cache": "1.3.0", 533 | "object-assign": "4.1.1" 534 | } 535 | }, 536 | "flat-cache": { 537 | "version": "1.3.0", 538 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", 539 | "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", 540 | "dev": true, 541 | "requires": { 542 | "circular-json": "0.3.3", 543 | "del": "2.2.2", 544 | "graceful-fs": "4.1.11", 545 | "write": "0.2.1" 546 | } 547 | }, 548 | "for-each": { 549 | "version": "0.3.3", 550 | "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", 551 | "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", 552 | "dev": true, 553 | "requires": { 554 | "is-callable": "1.1.4" 555 | } 556 | }, 557 | "foreach": { 558 | "version": "2.0.5", 559 | "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", 560 | "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", 561 | "dev": true 562 | }, 563 | "fs.realpath": { 564 | "version": "1.0.0", 565 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 566 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 567 | "dev": true 568 | }, 569 | "function-bind": { 570 | "version": "1.1.1", 571 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 572 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 573 | "dev": true 574 | }, 575 | "functional-red-black-tree": { 576 | "version": "1.0.1", 577 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 578 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 579 | "dev": true 580 | }, 581 | "get-stdin": { 582 | "version": "5.0.1", 583 | "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", 584 | "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", 585 | "dev": true 586 | }, 587 | "glob": { 588 | "version": "7.1.2", 589 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 590 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 591 | "dev": true, 592 | "requires": { 593 | "fs.realpath": "1.0.0", 594 | "inflight": "1.0.6", 595 | "inherits": "2.0.3", 596 | "minimatch": "3.0.4", 597 | "once": "1.4.0", 598 | "path-is-absolute": "1.0.1" 599 | } 600 | }, 601 | "globals": { 602 | "version": "11.7.0", 603 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", 604 | "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", 605 | "dev": true 606 | }, 607 | "globby": { 608 | "version": "5.0.0", 609 | "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", 610 | "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", 611 | "dev": true, 612 | "requires": { 613 | "array-union": "1.0.2", 614 | "arrify": "1.0.1", 615 | "glob": "7.1.2", 616 | "object-assign": "4.1.1", 617 | "pify": "2.3.0", 618 | "pinkie-promise": "2.0.1" 619 | } 620 | }, 621 | "graceful-fs": { 622 | "version": "4.1.11", 623 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 624 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", 625 | "dev": true 626 | }, 627 | "has": { 628 | "version": "1.0.3", 629 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 630 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 631 | "dev": true, 632 | "requires": { 633 | "function-bind": "1.1.1" 634 | } 635 | }, 636 | "has-ansi": { 637 | "version": "2.0.0", 638 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 639 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 640 | "requires": { 641 | "ansi-regex": "2.1.1" 642 | } 643 | }, 644 | "has-flag": { 645 | "version": "3.0.0", 646 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 647 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 648 | "dev": true 649 | }, 650 | "has-symbols": { 651 | "version": "1.0.0", 652 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", 653 | "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", 654 | "dev": true 655 | }, 656 | "iconv-lite": { 657 | "version": "0.4.23", 658 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 659 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 660 | "dev": true, 661 | "requires": { 662 | "safer-buffer": "2.1.2" 663 | } 664 | }, 665 | "ignore": { 666 | "version": "4.0.2", 667 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.2.tgz", 668 | "integrity": "sha512-uoxnT7PYpyEnsja+yX+7v49B7LXxmzDJ2JALqHH3oEGzpM2U1IGcbfnOr8Dt57z3B/UWs7/iAgPFbmye8m4I0g==", 669 | "dev": true 670 | }, 671 | "imurmurhash": { 672 | "version": "0.1.4", 673 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 674 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 675 | "dev": true 676 | }, 677 | "inflight": { 678 | "version": "1.0.6", 679 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 680 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 681 | "dev": true, 682 | "requires": { 683 | "once": "1.4.0", 684 | "wrappy": "1.0.2" 685 | } 686 | }, 687 | "inherits": { 688 | "version": "2.0.3", 689 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 690 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 691 | "dev": true 692 | }, 693 | "inquirer": { 694 | "version": "5.2.0", 695 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", 696 | "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", 697 | "dev": true, 698 | "requires": { 699 | "ansi-escapes": "3.1.0", 700 | "chalk": "2.4.1", 701 | "cli-cursor": "2.1.0", 702 | "cli-width": "2.2.0", 703 | "external-editor": "2.2.0", 704 | "figures": "2.0.0", 705 | "lodash": "4.17.10", 706 | "mute-stream": "0.0.7", 707 | "run-async": "2.3.0", 708 | "rxjs": "5.5.11", 709 | "string-width": "2.1.1", 710 | "strip-ansi": "4.0.0", 711 | "through": "2.3.8" 712 | }, 713 | "dependencies": { 714 | "ansi-regex": { 715 | "version": "3.0.0", 716 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 717 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 718 | "dev": true 719 | }, 720 | "ansi-styles": { 721 | "version": "3.2.1", 722 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 723 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 724 | "dev": true, 725 | "requires": { 726 | "color-convert": "1.9.2" 727 | } 728 | }, 729 | "chalk": { 730 | "version": "2.4.1", 731 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 732 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 733 | "dev": true, 734 | "requires": { 735 | "ansi-styles": "3.2.1", 736 | "escape-string-regexp": "1.0.5", 737 | "supports-color": "5.4.0" 738 | } 739 | }, 740 | "strip-ansi": { 741 | "version": "4.0.0", 742 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 743 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 744 | "dev": true, 745 | "requires": { 746 | "ansi-regex": "3.0.0" 747 | } 748 | }, 749 | "supports-color": { 750 | "version": "5.4.0", 751 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", 752 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", 753 | "dev": true, 754 | "requires": { 755 | "has-flag": "3.0.0" 756 | } 757 | } 758 | } 759 | }, 760 | "is-callable": { 761 | "version": "1.1.4", 762 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", 763 | "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", 764 | "dev": true 765 | }, 766 | "is-date-object": { 767 | "version": "1.0.1", 768 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", 769 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", 770 | "dev": true 771 | }, 772 | "is-fullwidth-code-point": { 773 | "version": "2.0.0", 774 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 775 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 776 | "dev": true 777 | }, 778 | "is-path-cwd": { 779 | "version": "1.0.0", 780 | "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", 781 | "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", 782 | "dev": true 783 | }, 784 | "is-path-in-cwd": { 785 | "version": "1.0.1", 786 | "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", 787 | "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", 788 | "dev": true, 789 | "requires": { 790 | "is-path-inside": "1.0.1" 791 | } 792 | }, 793 | "is-path-inside": { 794 | "version": "1.0.1", 795 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", 796 | "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", 797 | "dev": true, 798 | "requires": { 799 | "path-is-inside": "1.0.2" 800 | } 801 | }, 802 | "is-promise": { 803 | "version": "2.1.0", 804 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 805 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", 806 | "dev": true 807 | }, 808 | "is-regex": { 809 | "version": "1.0.4", 810 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 811 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 812 | "dev": true, 813 | "requires": { 814 | "has": "1.0.3" 815 | } 816 | }, 817 | "is-resolvable": { 818 | "version": "1.1.0", 819 | "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", 820 | "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", 821 | "dev": true 822 | }, 823 | "is-symbol": { 824 | "version": "1.0.1", 825 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", 826 | "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", 827 | "dev": true 828 | }, 829 | "isexe": { 830 | "version": "2.0.0", 831 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 832 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 833 | "dev": true 834 | }, 835 | "js-tokens": { 836 | "version": "3.0.2", 837 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 838 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", 839 | "dev": true 840 | }, 841 | "js-yaml": { 842 | "version": "3.12.0", 843 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", 844 | "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", 845 | "dev": true, 846 | "requires": { 847 | "argparse": "1.0.10", 848 | "esprima": "4.0.1" 849 | } 850 | }, 851 | "json-schema-traverse": { 852 | "version": "0.4.1", 853 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 854 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 855 | "dev": true 856 | }, 857 | "json-stable-stringify-without-jsonify": { 858 | "version": "1.0.1", 859 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 860 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 861 | "dev": true 862 | }, 863 | "levn": { 864 | "version": "0.3.0", 865 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 866 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 867 | "dev": true, 868 | "requires": { 869 | "prelude-ls": "1.1.2", 870 | "type-check": "0.3.2" 871 | } 872 | }, 873 | "lodash": { 874 | "version": "4.17.10", 875 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", 876 | "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" 877 | }, 878 | "mimic-fn": { 879 | "version": "1.2.0", 880 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 881 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", 882 | "dev": true 883 | }, 884 | "minimatch": { 885 | "version": "3.0.4", 886 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 887 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 888 | "dev": true, 889 | "requires": { 890 | "brace-expansion": "1.1.11" 891 | } 892 | }, 893 | "minimist": { 894 | "version": "1.2.0", 895 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 896 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 897 | }, 898 | "mkdirp": { 899 | "version": "0.5.1", 900 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 901 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 902 | "dev": true, 903 | "requires": { 904 | "minimist": "0.0.8" 905 | }, 906 | "dependencies": { 907 | "minimist": { 908 | "version": "0.0.8", 909 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 910 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 911 | "dev": true 912 | } 913 | } 914 | }, 915 | "ms": { 916 | "version": "2.0.0", 917 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 918 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 919 | "dev": true 920 | }, 921 | "mute-stream": { 922 | "version": "0.0.7", 923 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 924 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", 925 | "dev": true 926 | }, 927 | "natural-compare": { 928 | "version": "1.4.0", 929 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 930 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 931 | "dev": true 932 | }, 933 | "nice-try": { 934 | "version": "1.0.4", 935 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", 936 | "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", 937 | "dev": true 938 | }, 939 | "object-assign": { 940 | "version": "4.1.1", 941 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 942 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 943 | }, 944 | "object-inspect": { 945 | "version": "1.6.0", 946 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", 947 | "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", 948 | "dev": true 949 | }, 950 | "object-keys": { 951 | "version": "1.0.12", 952 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", 953 | "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", 954 | "dev": true 955 | }, 956 | "once": { 957 | "version": "1.4.0", 958 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 959 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 960 | "dev": true, 961 | "requires": { 962 | "wrappy": "1.0.2" 963 | } 964 | }, 965 | "onetime": { 966 | "version": "2.0.1", 967 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 968 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 969 | "dev": true, 970 | "requires": { 971 | "mimic-fn": "1.2.0" 972 | } 973 | }, 974 | "optionator": { 975 | "version": "0.8.2", 976 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 977 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 978 | "dev": true, 979 | "requires": { 980 | "deep-is": "0.1.3", 981 | "fast-levenshtein": "2.0.6", 982 | "levn": "0.3.0", 983 | "prelude-ls": "1.1.2", 984 | "type-check": "0.3.2", 985 | "wordwrap": "1.0.0" 986 | } 987 | }, 988 | "os-tmpdir": { 989 | "version": "1.0.2", 990 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 991 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 992 | "dev": true 993 | }, 994 | "path-is-absolute": { 995 | "version": "1.0.1", 996 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 997 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 998 | "dev": true 999 | }, 1000 | "path-is-inside": { 1001 | "version": "1.0.2", 1002 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 1003 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 1004 | "dev": true 1005 | }, 1006 | "path-key": { 1007 | "version": "2.0.1", 1008 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 1009 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", 1010 | "dev": true 1011 | }, 1012 | "path-parse": { 1013 | "version": "1.0.5", 1014 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", 1015 | "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", 1016 | "dev": true 1017 | }, 1018 | "pify": { 1019 | "version": "2.3.0", 1020 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1021 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 1022 | "dev": true 1023 | }, 1024 | "pinkie": { 1025 | "version": "2.0.4", 1026 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 1027 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 1028 | "dev": true 1029 | }, 1030 | "pinkie-promise": { 1031 | "version": "2.0.1", 1032 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 1033 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 1034 | "dev": true, 1035 | "requires": { 1036 | "pinkie": "2.0.4" 1037 | } 1038 | }, 1039 | "pluralize": { 1040 | "version": "7.0.0", 1041 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", 1042 | "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", 1043 | "dev": true 1044 | }, 1045 | "prelude-ls": { 1046 | "version": "1.1.2", 1047 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 1048 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 1049 | "dev": true 1050 | }, 1051 | "prettier": { 1052 | "version": "1.13.7", 1053 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.13.7.tgz", 1054 | "integrity": "sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w==", 1055 | "dev": true 1056 | }, 1057 | "progress": { 1058 | "version": "2.0.0", 1059 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", 1060 | "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", 1061 | "dev": true 1062 | }, 1063 | "punycode": { 1064 | "version": "2.1.1", 1065 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1066 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1067 | "dev": true 1068 | }, 1069 | "random-lib": { 1070 | "version": "2.1.0", 1071 | "resolved": "https://registry.npmjs.org/random-lib/-/random-lib-2.1.0.tgz", 1072 | "integrity": "sha1-PrOXD/J8Gvc8WIq5EHXY8KBDjfU=", 1073 | "requires": { 1074 | "dezalgo": "1.0.3", 1075 | "es6-promise": "3.3.1", 1076 | "object-assign": "4.1.1" 1077 | } 1078 | }, 1079 | "regexp.prototype.flags": { 1080 | "version": "1.2.0", 1081 | "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", 1082 | "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", 1083 | "dev": true, 1084 | "requires": { 1085 | "define-properties": "1.1.2" 1086 | } 1087 | }, 1088 | "regexpp": { 1089 | "version": "1.1.0", 1090 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", 1091 | "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", 1092 | "dev": true 1093 | }, 1094 | "require-uncached": { 1095 | "version": "1.0.3", 1096 | "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", 1097 | "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", 1098 | "dev": true, 1099 | "requires": { 1100 | "caller-path": "0.1.0", 1101 | "resolve-from": "1.0.1" 1102 | } 1103 | }, 1104 | "resolve-from": { 1105 | "version": "1.0.1", 1106 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", 1107 | "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", 1108 | "dev": true 1109 | }, 1110 | "restore-cursor": { 1111 | "version": "2.0.0", 1112 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 1113 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 1114 | "dev": true, 1115 | "requires": { 1116 | "onetime": "2.0.1", 1117 | "signal-exit": "3.0.2" 1118 | } 1119 | }, 1120 | "resumer": { 1121 | "version": "0.0.0", 1122 | "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", 1123 | "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", 1124 | "dev": true, 1125 | "requires": { 1126 | "through": "2.3.8" 1127 | } 1128 | }, 1129 | "rimraf": { 1130 | "version": "2.6.2", 1131 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", 1132 | "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", 1133 | "dev": true, 1134 | "requires": { 1135 | "glob": "7.1.2" 1136 | } 1137 | }, 1138 | "run-async": { 1139 | "version": "2.3.0", 1140 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 1141 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 1142 | "dev": true, 1143 | "requires": { 1144 | "is-promise": "2.1.0" 1145 | } 1146 | }, 1147 | "rxjs": { 1148 | "version": "5.5.11", 1149 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.11.tgz", 1150 | "integrity": "sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA==", 1151 | "dev": true, 1152 | "requires": { 1153 | "symbol-observable": "1.0.1" 1154 | } 1155 | }, 1156 | "safer-buffer": { 1157 | "version": "2.1.2", 1158 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1159 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1160 | "dev": true 1161 | }, 1162 | "semver": { 1163 | "version": "5.5.0", 1164 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", 1165 | "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", 1166 | "dev": true 1167 | }, 1168 | "shebang-command": { 1169 | "version": "1.2.0", 1170 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1171 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1172 | "dev": true, 1173 | "requires": { 1174 | "shebang-regex": "1.0.0" 1175 | } 1176 | }, 1177 | "shebang-regex": { 1178 | "version": "1.0.0", 1179 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1180 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 1181 | "dev": true 1182 | }, 1183 | "signal-exit": { 1184 | "version": "3.0.2", 1185 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1186 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 1187 | "dev": true 1188 | }, 1189 | "slice-ansi": { 1190 | "version": "1.0.0", 1191 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", 1192 | "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", 1193 | "dev": true, 1194 | "requires": { 1195 | "is-fullwidth-code-point": "2.0.0" 1196 | } 1197 | }, 1198 | "sprintf-js": { 1199 | "version": "1.0.3", 1200 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1201 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1202 | "dev": true 1203 | }, 1204 | "string-width": { 1205 | "version": "2.1.1", 1206 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1207 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1208 | "dev": true, 1209 | "requires": { 1210 | "is-fullwidth-code-point": "2.0.0", 1211 | "strip-ansi": "4.0.0" 1212 | }, 1213 | "dependencies": { 1214 | "ansi-regex": { 1215 | "version": "3.0.0", 1216 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 1217 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 1218 | "dev": true 1219 | }, 1220 | "strip-ansi": { 1221 | "version": "4.0.0", 1222 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1223 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1224 | "dev": true, 1225 | "requires": { 1226 | "ansi-regex": "3.0.0" 1227 | } 1228 | } 1229 | } 1230 | }, 1231 | "string.prototype.matchall": { 1232 | "version": "2.0.0", 1233 | "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz", 1234 | "integrity": "sha512-WoZ+B2ypng1dp4iFLF2kmZlwwlE19gmjgKuhL1FJfDgCREWb3ye3SDVHSzLH6bxfnvYmkCxbzkmWcQZHA4P//Q==", 1235 | "dev": true, 1236 | "requires": { 1237 | "define-properties": "1.1.2", 1238 | "es-abstract": "1.12.0", 1239 | "function-bind": "1.1.1", 1240 | "has-symbols": "1.0.0", 1241 | "regexp.prototype.flags": "1.2.0" 1242 | } 1243 | }, 1244 | "string.prototype.trim": { 1245 | "version": "1.1.2", 1246 | "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", 1247 | "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", 1248 | "dev": true, 1249 | "requires": { 1250 | "define-properties": "1.1.2", 1251 | "es-abstract": "1.12.0", 1252 | "function-bind": "1.1.1" 1253 | } 1254 | }, 1255 | "strip-ansi": { 1256 | "version": "3.0.1", 1257 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1258 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1259 | "requires": { 1260 | "ansi-regex": "2.1.1" 1261 | } 1262 | }, 1263 | "strip-json-comments": { 1264 | "version": "2.0.1", 1265 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1266 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1267 | "dev": true 1268 | }, 1269 | "supports-color": { 1270 | "version": "2.0.0", 1271 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1272 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 1273 | }, 1274 | "symbol-observable": { 1275 | "version": "1.0.1", 1276 | "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", 1277 | "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", 1278 | "dev": true 1279 | }, 1280 | "table": { 1281 | "version": "4.0.3", 1282 | "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", 1283 | "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", 1284 | "dev": true, 1285 | "requires": { 1286 | "ajv": "6.5.2", 1287 | "ajv-keywords": "3.2.0", 1288 | "chalk": "2.4.1", 1289 | "lodash": "4.17.10", 1290 | "slice-ansi": "1.0.0", 1291 | "string-width": "2.1.1" 1292 | }, 1293 | "dependencies": { 1294 | "ansi-styles": { 1295 | "version": "3.2.1", 1296 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 1297 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 1298 | "dev": true, 1299 | "requires": { 1300 | "color-convert": "1.9.2" 1301 | } 1302 | }, 1303 | "chalk": { 1304 | "version": "2.4.1", 1305 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 1306 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 1307 | "dev": true, 1308 | "requires": { 1309 | "ansi-styles": "3.2.1", 1310 | "escape-string-regexp": "1.0.5", 1311 | "supports-color": "5.4.0" 1312 | } 1313 | }, 1314 | "supports-color": { 1315 | "version": "5.4.0", 1316 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", 1317 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", 1318 | "dev": true, 1319 | "requires": { 1320 | "has-flag": "3.0.0" 1321 | } 1322 | } 1323 | } 1324 | }, 1325 | "tape": { 1326 | "version": "4.9.1", 1327 | "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz", 1328 | "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==", 1329 | "dev": true, 1330 | "requires": { 1331 | "deep-equal": "1.0.1", 1332 | "defined": "1.0.0", 1333 | "for-each": "0.3.3", 1334 | "function-bind": "1.1.1", 1335 | "glob": "7.1.2", 1336 | "has": "1.0.3", 1337 | "inherits": "2.0.3", 1338 | "minimist": "1.2.0", 1339 | "object-inspect": "1.6.0", 1340 | "resolve": "1.7.1", 1341 | "resumer": "0.0.0", 1342 | "string.prototype.trim": "1.1.2", 1343 | "through": "2.3.8" 1344 | }, 1345 | "dependencies": { 1346 | "resolve": { 1347 | "version": "1.7.1", 1348 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", 1349 | "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", 1350 | "dev": true, 1351 | "requires": { 1352 | "path-parse": "1.0.5" 1353 | } 1354 | } 1355 | } 1356 | }, 1357 | "text-table": { 1358 | "version": "0.2.0", 1359 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1360 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1361 | "dev": true 1362 | }, 1363 | "through": { 1364 | "version": "2.3.8", 1365 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1366 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 1367 | "dev": true 1368 | }, 1369 | "tmp": { 1370 | "version": "0.0.33", 1371 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1372 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1373 | "dev": true, 1374 | "requires": { 1375 | "os-tmpdir": "1.0.2" 1376 | } 1377 | }, 1378 | "type-check": { 1379 | "version": "0.3.2", 1380 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1381 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1382 | "dev": true, 1383 | "requires": { 1384 | "prelude-ls": "1.1.2" 1385 | } 1386 | }, 1387 | "underscore": { 1388 | "version": "1.9.1", 1389 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", 1390 | "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", 1391 | "dev": true 1392 | }, 1393 | "uri-js": { 1394 | "version": "4.2.2", 1395 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1396 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1397 | "dev": true, 1398 | "requires": { 1399 | "punycode": "2.1.1" 1400 | } 1401 | }, 1402 | "when": { 1403 | "version": "3.7.8", 1404 | "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", 1405 | "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=" 1406 | }, 1407 | "which": { 1408 | "version": "1.3.1", 1409 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1410 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1411 | "dev": true, 1412 | "requires": { 1413 | "isexe": "2.0.0" 1414 | } 1415 | }, 1416 | "wordwrap": { 1417 | "version": "1.0.0", 1418 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 1419 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 1420 | "dev": true 1421 | }, 1422 | "wrappy": { 1423 | "version": "1.0.2", 1424 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1425 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1426 | }, 1427 | "write": { 1428 | "version": "0.2.1", 1429 | "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", 1430 | "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", 1431 | "dev": true, 1432 | "requires": { 1433 | "mkdirp": "0.5.1" 1434 | } 1435 | } 1436 | } 1437 | } 1438 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xkcd-password", 3 | "version": "2.0.0", 4 | "description": "Creates an XKCD-style password based on your parameters. Includes a CLI (xkcd-password) for your convenience, and a default wordlist. Supports both a callback-based API and Promises/A+.", 5 | "main": "index.js", 6 | "bin": { 7 | "xkcd-password": "./bin/xkcd-password.js" 8 | }, 9 | "scripts": { 10 | "test": "tape test/*.js && npm run lint", 11 | "lint": "npm run prettier-validate && npm run eslint", 12 | "prettier-validate": "prettier --list-different **/*.js", 13 | "eslint": "eslint ." 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git://github.com/fardog/node-xkcd-password.git" 18 | }, 19 | "engines": { 20 | "node": ">=6" 21 | }, 22 | "keywords": [ 23 | "password", 24 | "xkcd", 25 | "words", 26 | "random" 27 | ], 28 | "author": "Nathan Wittstock ", 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/fardog/node-xkcd-password/issues" 32 | }, 33 | "homepage": "https://github.com/fardog/node-xkcd-password", 34 | "dependencies": { 35 | "async": "^2.1.4", 36 | "chalk": "^1.1.3", 37 | "minimist": "^1.1.0", 38 | "random-lib": "^2.1.0", 39 | "when": "^3.4.5" 40 | }, 41 | "devDependencies": { 42 | "eslint": "^5.2.0", 43 | "eslint-config-prettier": "^2.9.0", 44 | "prettier": "^1.13.7", 45 | "tape": "^4.6.3", 46 | "underscore": "^1.6.0" 47 | }, 48 | "prettier": { 49 | "semi": false 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/cli.js: -------------------------------------------------------------------------------- 1 | var test = require("tape") 2 | 3 | var CLI = require("../lib/cli") 4 | 5 | test("parse args", function(t) { 6 | t.plan(6) 7 | 8 | var argv = ["-n", "10", "-x", "20", "-m", "5", "-f", "/path.txt", "-s", "-"] 9 | var cli = new CLI().parse(argv) 10 | 11 | t.equal(10, cli.parsedOptions.numWords, "should have correct numWords") 12 | t.equal(20, cli.parsedOptions.maxLength, "should have correct maxLength") 13 | t.equal(5, cli.parsedOptions.minLength, "should have correct minLength") 14 | t.equal( 15 | "/path.txt", 16 | cli.parsedOptions.wordFile, 17 | "should have correct wordFile" 18 | ) 19 | t.equal("-", cli.parsedOptions.separator, "should have correct wordFile") 20 | t.ok(cli.errors.length === 0, "should have no errors") 21 | t.end() 22 | }) 23 | 24 | test("numeric values", function(t) { 25 | t.plan(1) 26 | 27 | var argv = ["-n", "ten"] 28 | var cli = new CLI().parse(argv) 29 | 30 | t.ok( 31 | cli.errors.length === 1, 32 | "should have an error when numWords is not numeric" 33 | ) 34 | t.end() 35 | }) 36 | 37 | test("string values", function(t) { 38 | t.plan(1) 39 | 40 | var argv = ["-s", ""] 41 | var cli = new CLI().parse(argv) 42 | 43 | t.ok(cli.errors.length === 1, "should have an error when separator is empty") 44 | t.end() 45 | }) 46 | 47 | test("default values", function(t) { 48 | t.plan(3) 49 | 50 | var argv = ["-n", "10"] 51 | var cli = new CLI().parse(argv) 52 | 53 | t.equal(" ", cli.parsedOptions.separator, "should have default separator") 54 | 55 | cli = null 56 | 57 | argv = ["-x", "3"] 58 | cli = new CLI().parse(argv) 59 | t.equal( 60 | 1, 61 | cli.parsedOptions.minLength, 62 | "should set minLenght on small maxLength" 63 | ) 64 | 65 | cli = null 66 | 67 | argv = ["-x", "5"] 68 | cli = new CLI().parse(argv) 69 | t.ok( 70 | !cli.parsedOptions.minLength, 71 | "should not set minLength on larger maxLength" 72 | ) 73 | 74 | t.end() 75 | }) 76 | 77 | test("help and version", function(t) { 78 | t.plan(2) 79 | 80 | var argv = ["-v"] 81 | 82 | var cli = new CLI().parse(argv) 83 | t.ok(cli.message.length > 0, "should have version message") 84 | 85 | cli = null 86 | 87 | argv = ["--help"] 88 | cli = new CLI().parse(argv) 89 | t.ok(cli.message.length > 150, "should have long help message") 90 | t.end() 91 | }) 92 | 93 | test("sync callback style", function(t) { 94 | t.plan(2) 95 | 96 | var argv = ["-x", "5"] 97 | 98 | new CLI().parse(argv, function(err, message, options) { 99 | t.equal(5, options.maxLength, "should have correct maxLength") 100 | t.ok(!err, "should not have an error") 101 | t.end() 102 | }) 103 | }) 104 | -------------------------------------------------------------------------------- /test/fixtures/wordlist.txt: -------------------------------------------------------------------------------- 1 | one 2 | two 3 | three 4 | four 5 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var test = require("tape") 2 | var async = require("async") 3 | var path = require("path") 4 | var _ = require("underscore") 5 | 6 | var XKCDPassword = require("../") 7 | 8 | test("tests generating four words", function(t) { 9 | t.plan(1) 10 | 11 | var pw = new XKCDPassword() 12 | var options = { 13 | numWords: 4, 14 | minLength: 5, 15 | maxLength: 8 16 | } 17 | 18 | pw.generate(options, function(err, result) { 19 | if (err) t.fail(err) 20 | t.equal(4, result.length, "should see four generated words") 21 | t.end() 22 | }) 23 | }) 24 | 25 | test("can use without new keyword", function(t) { 26 | t.plan(1) 27 | 28 | var pw = XKCDPassword() 29 | var options = { 30 | numWords: 4, 31 | minLength: 5, 32 | maxLength: 8 33 | } 34 | 35 | pw.generate(options, function(err, result) { 36 | if (err) t.fail(err) 37 | t.equal(4, result.length, "should see four generated words") 38 | t.end() 39 | }) 40 | }) 41 | 42 | test("(promise) tests generating four words", function(t) { 43 | t.plan(1) 44 | 45 | var pw = new XKCDPassword() 46 | var options = { 47 | numWords: 4, 48 | minLength: 5, 49 | maxLength: 8 50 | } 51 | 52 | pw.generate(options).then(function(result) { 53 | t.equal(4, result.length, "should see four generated words") 54 | t.end() 55 | }) 56 | }) 57 | 58 | test("tests running two consecutive generations", function(t) { 59 | t.plan(3) 60 | 61 | var pw = new XKCDPassword() 62 | var options = { 63 | numWords: 4, 64 | minLength: 5, 65 | maxLength: 8 66 | } 67 | 68 | pw.generate(options, function(err, result1) { 69 | if (err) t.fail(err) 70 | t.equal(4, result1.length, "should see four generated words from result1") 71 | pw.generate(options, function(err2, result2) { 72 | if (err2) t.fail(err2) 73 | t.equal(4, result2.length, "should see four generated words from result2") 74 | 75 | // tests if there's overlap in the two generated arrays, which is 76 | // not probable 77 | var difference = _.difference(result1, result2) 78 | t.ok( 79 | difference.length > 0, 80 | "should not have the same values in both arrays." 81 | ) 82 | t.end() 83 | }) 84 | }) 85 | }) 86 | 87 | test("(promise) tests running two consecutive generations", function(t) { 88 | t.plan(3) 89 | 90 | var pw = new XKCDPassword() 91 | var options = { 92 | numWords: 4, 93 | minLength: 5, 94 | maxLength: 8 95 | } 96 | 97 | pw.generate(options).then(function(result1) { 98 | t.equal(4, result1.length, "should see four generated words from result1") 99 | pw.generate(options).then(function(result2) { 100 | t.equal(4, result2.length, "should see four generated words from result2") 101 | 102 | // tests if there's overlap in the two generated arrays, which is 103 | // not probable 104 | var difference = _.difference(result1, result2) 105 | t.ok( 106 | difference.length > 0, 107 | "should not have the same values in both arrays." 108 | ) 109 | t.end() 110 | }) 111 | }) 112 | }) 113 | 114 | test("ensures we don't have any problems that only crop up rarely", function(t) { 115 | t.plan(2101) 116 | 117 | var pw = new XKCDPassword() 118 | var options = { 119 | numWords: 10, 120 | minLength: 6, 121 | maxLength: 10 122 | } 123 | 124 | var count = 0 125 | async.doWhilst( 126 | function(callback) { 127 | pw.generate(options, function(err, result) { 128 | if (err) t.fail(err) 129 | t.equal(options.numWords, result.length, "should get numWords words") 130 | for (var i = 0; i < result.length; i++) { 131 | t.equal( 132 | true, 133 | result[i].length <= options.maxLength, 134 | "word should be shorter than the max length" 135 | ) 136 | t.equal( 137 | true, 138 | result[i].length >= options.minLength, 139 | "word should be longer than the min length" 140 | ) 141 | } 142 | 143 | count++ 144 | callback() 145 | }) 146 | }, 147 | function() { 148 | return count < 100 149 | }, 150 | function(err) { 151 | if (err) t.fail(err) 152 | 153 | t.equal(100, count, "should have run 100 times") 154 | t.end() 155 | } 156 | ) 157 | }) 158 | 159 | test("generates too many small words, to ensure we don't hang on generation", function(t) { 160 | t.plan(2) 161 | 162 | var pw = new XKCDPassword() 163 | var options = { 164 | numWords: 86, 165 | minLength: 2, 166 | maxLength: 2 167 | } 168 | 169 | pw.generate(options, function(err) { 170 | t.ok(err, "should see an error") 171 | 172 | options = { 173 | numWords: 1000, 174 | minLength: 3, 175 | maxLength: 3 176 | } 177 | pw.generate(options, function(err2) { 178 | t.ok(err2, "should see an error") 179 | t.end() 180 | }) 181 | }) 182 | }) 183 | 184 | test("generates exactly enough words to see if we trip the too many words error falsely", function(t) { 185 | t.plan(1) 186 | 187 | var pw = new XKCDPassword() 188 | var options = { 189 | numWords: 85, 190 | minLength: 2, 191 | maxLength: 2 192 | } 193 | 194 | pw.generate(options, function(err, result) { 195 | if (err) t.fail(err) 196 | t.equal(85, result.length, "should see 85 words") 197 | t.end() 198 | }) 199 | }) 200 | 201 | test("tests generating two asynchronous runs of the generator", function(t) { 202 | t.plan(4) 203 | 204 | var pw = new XKCDPassword() 205 | var options = { 206 | numWords: 4, 207 | minLength: 5, 208 | maxLength: 8 209 | } 210 | 211 | async.parallel( 212 | [ 213 | function(callback) { 214 | pw.generate(options, function(err, result) { 215 | if (err) t.fail(err) 216 | callback(null, result) 217 | }) 218 | }, 219 | function(callback) { 220 | pw.generate(options, function(err, result) { 221 | if (err) t.fail(err) 222 | callback(null, result) 223 | }) 224 | } 225 | ], 226 | function(err, results) { 227 | if (err) t.fail(err) 228 | t.equal(2, results.length, "should see two results") 229 | t.equal( 230 | options.numWords, 231 | results[0].length, 232 | "should see four generated words from result[0]" 233 | ) 234 | t.equal( 235 | options.numWords, 236 | results[1].length, 237 | "should see four generated words from result[1]" 238 | ) 239 | 240 | var difference = _.difference(results[0], results[1]) 241 | t.ok( 242 | difference.length > 0, 243 | "should not have the same values in both arrays." 244 | ) 245 | t.end() 246 | } 247 | ) 248 | }) 249 | 250 | test("(promise) tests generating two asynchronous runs of the generator", function(t) { 251 | t.plan(4) 252 | 253 | var pw = new XKCDPassword() 254 | var options = { 255 | numWords: 4, 256 | minLength: 5, 257 | maxLength: 8 258 | } 259 | 260 | async.parallel( 261 | [ 262 | function(callback) { 263 | pw.generate(options).then(function(result) { 264 | callback(null, result) 265 | }) 266 | }, 267 | function(callback) { 268 | pw.generate(options).then(function(result) { 269 | callback(null, result) 270 | }) 271 | } 272 | ], 273 | function(err, results) { 274 | if (err) t.fail(err) 275 | t.equal(2, results.length, "should see two results") 276 | t.equal( 277 | options.numWords, 278 | results[0].length, 279 | "should see four generated words from result[0]" 280 | ) 281 | t.equal( 282 | options.numWords, 283 | results[1].length, 284 | "should see four generated words from result[1]" 285 | ) 286 | 287 | var difference = _.difference(results[0], results[1]) 288 | t.ok( 289 | difference.length > 0, 290 | "should not have the same values in both arrays." 291 | ) 292 | t.end() 293 | } 294 | ) 295 | }) 296 | 297 | test("use bad word list", function(t) { 298 | t.plan(2) 299 | 300 | var wordlist = "something" 301 | 302 | t.throws( 303 | function() { 304 | new XKCDPassword().initWithWordList(wordlist) 305 | }, 306 | Error, 307 | "should error on a bad wordlist" 308 | ) 309 | t.throws( 310 | function() { 311 | new XKCDPassword().initWithWordFile([]) 312 | }, 313 | Error, 314 | "should error on a bad wordfile" 315 | ) 316 | 317 | t.end() 318 | }) 319 | 320 | test("test errors", function(t) { 321 | t.plan(5) 322 | 323 | var wordList = ["one", "two", "three"] 324 | 325 | var pw = new XKCDPassword().initWithWordList(wordList) 326 | pw.generate({ numWords: 4 }, function(err) { 327 | t.ok(err, "should see an error message on asking for too many words.") 328 | 329 | pw.generate({ numWords: 0 }, function(err2) { 330 | t.ok(err2, "should see an error on asking for no words.") 331 | 332 | pw.generate({ numWords: 4, minLength: -1 }, function(err3) { 333 | t.ok(err3, "should see an error on asking for a negative length") 334 | 335 | pw.generate({ numWords: 4, maxLength: 1 }, function(err4) { 336 | t.ok(err4, "should see an error on a very small max length") 337 | 338 | pw.generate({ minLength: 10, maxLength: 9 }, function(err5) { 339 | t.ok(err5, "should see an error when max is less than min") 340 | t.end() 341 | }) 342 | }) 343 | }) 344 | }) 345 | }) 346 | }) 347 | 348 | test("(promise) test errors", function(t) { 349 | t.plan(5) 350 | 351 | var wordList = ["one", "two", "three"] 352 | 353 | var pw = new XKCDPassword().initWithWordList(wordList) 354 | pw.generate({ numWords: 4 }).catch(function(err) { 355 | t.ok(err, "should see an error message on asking for too many words.") 356 | 357 | pw.generate({ numWords: 0 }).catch(function(err2) { 358 | t.ok(err2, "should see an error on asking for no words.") 359 | 360 | pw.generate({ numWords: 4, minLength: -1 }).catch(function(err3) { 361 | t.ok(err3, "should see an error on asking for a negative length") 362 | 363 | pw.generate({ numWords: 4, maxLength: 1 }).catch(function(err4) { 364 | t.ok(err4, "should see an error on a very small max length") 365 | 366 | pw.generate({ minLength: 10, maxLength: 9 }).catch(function(err5) { 367 | t.ok(err5, "should see an error when max is less than min") 368 | t.end() 369 | }) 370 | }) 371 | }) 372 | }) 373 | }) 374 | }) 375 | 376 | test("generate from list", function(t) { 377 | t.plan(1) 378 | 379 | var wordlist = ["one", "two", "three", "four"] 380 | var options = { 381 | numWords: 4, 382 | minLength: 1, 383 | maxLength: 10 384 | } 385 | 386 | var pw = new XKCDPassword().initWithWordList(wordlist) 387 | pw.generate(options, function(err, result) { 388 | if (err) t.fail(err) 389 | 390 | var difference = _.difference(wordlist, result) 391 | t.ok(difference.length === 0, "should use all words from wordlist") 392 | t.end() 393 | }) 394 | }) 395 | 396 | test("use local word list", function(t) { 397 | t.plan(1) 398 | 399 | var wordlist = ["one", "two", "three", "four"] 400 | var options = { 401 | numWords: 4, 402 | minLength: 1, 403 | maxLength: 10 404 | } 405 | var wordfile = path.join(__dirname, "fixtures/wordlist.txt") 406 | 407 | var pw = new XKCDPassword().initWithWordFile(wordfile) 408 | pw.generate(options, function(err, result) { 409 | if (err) t.fail(err) 410 | 411 | var difference = _.difference(wordlist, result) 412 | t.ok(difference.length === 0, "should use local wordfile") 413 | t.end() 414 | }) 415 | }) 416 | 417 | test("chooses sane defaults", function(t) { 418 | t.plan(1) 419 | 420 | var pw = new XKCDPassword() 421 | pw.generate(function(err, result) { 422 | if (err) t.fail(err) 423 | 424 | t.equal(4, result.length, "should generate four words by default") 425 | t.end() 426 | }) 427 | }) 428 | 429 | test("(promise) chooses sane defaults", function(t) { 430 | t.plan(1) 431 | 432 | var pw = new XKCDPassword() 433 | pw.generate().then(function(result) { 434 | t.equal(4, result.length, "should generate four words by default") 435 | t.end() 436 | }) 437 | }) 438 | -------------------------------------------------------------------------------- /vendor/mwords/LICENSE: -------------------------------------------------------------------------------- 1 | The Moby lexicon project is complete and has 2 | been place into the public domain. Use, sell, 3 | rework, excerpt and use in any way on any platform. 4 | 5 | Placing this material on internal or public servers is 6 | also encouraged. The compiler is not aware of any 7 | export restrictions so freely distribute world-wide. 8 | 9 | You can verify the public domain status by contacting 10 | 11 | Grady Ward 12 | 3449 Martha Ct. 13 | Arcata, CA 95521-4884 14 | --------------------------------------------------------------------------------