├── .gitignore ├── .perf.yml ├── .travis.yml ├── LICENSE ├── README.md ├── build-status.png ├── index.js ├── logo.png ├── mock ├── lighthouse.js └── results.json ├── package-lock.json ├── package.json ├── src ├── api.js ├── build.js ├── config.json ├── lighthouse.js ├── properties.js ├── reporter.js ├── settings.js ├── setup.js └── token.js └── store ├── .env.sample ├── dummy.js ├── firebase.js ├── github.js ├── index.js ├── package-lock.json ├── package.json ├── static └── styles.css └── views ├── auth.pug └── build.pug /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | debug.json 6 | 7 | # Coverage directory used by tools like istanbul 8 | coverage 9 | 10 | # Dependency directories 11 | node_modules 12 | 13 | # OS specific files 14 | .DS_Store 15 | store/.env 16 | -------------------------------------------------------------------------------- /.perf.yml: -------------------------------------------------------------------------------- 1 | runs: 2 2 | fail: false 3 | url: https://siddharthkp.github.io 4 | thresholds: 5 | - time-to-interactive: 500 6 | - page-ready: 1500 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: node_js 3 | node_js: 4 | - "6" 5 | cache: 6 | directories: 7 | - node_modules 8 | notifications: 9 | email: false 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Siddharth Kshetrapal 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | Continuous integration for performance monitoring 5 |
6 |

7 | 8 |   9 | 10 | [![Build Status](https://travis-ci.org/siddharthkp/perfbench.svg?branch=master)](https://travis-ci.org/siddharthkp/perfbench) 11 | 12 |   13 | 14 | #### install 15 | ``` 16 | npm install perfbench --save 17 | ``` 18 | 19 |   20 | 21 | #### usage 22 | 23 | Build and run your application in your CI and then invoke perfbench 24 | 25 | `package.json`: 26 | 27 | ```json 28 | "name": "my-awesome-app", 29 | "scripts": { 30 | "pretest": "npm run build && pm2 start server.js", 31 | "test": "perfbench" 32 | } 33 | ``` 34 | 35 | #### metrics measured 36 | 37 | - First meaningful paint 38 | - Speed index metric 39 | - Time to interactive 40 | - Total byte weight 41 | 42 |   43 | 44 | #### test conditions 45 | 46 | - Network: Fast 3G (150ms RTT, 1.6Mbps down, 0.7Mbps up) 47 | - Device emulation: Nexus 5X 48 | - CPU: 5x slowdown 49 | 50 |   51 | 52 | #### setup 53 | 54 | 1. configuration 55 | 56 | Drop a YAML file `.perf.yml` in the root of your repository. 57 | 58 | ```yaml 59 | url: http://localhost:3000 # the url you want to test 60 | fail: false # optional, default: true. false will only show a warning 61 | thresholds: # all rows are optional. add to customize the threshold 62 | - first-meaningful-paint: 1600 # optional, default: 1600, value in ms 63 | - speed-index-metric: 1250 # optional, default: 1250 64 | - time-to-interactive: 2500 # optional, default: 2500, value in ms 65 | - total-byte-weight: 1600 # optional, default: 1600, value in Kb 66 | ``` 67 | 68 |   69 | 70 | #### custom properties 71 | 72 | You can also add custom properties. 73 | 74 | Send a user timing performance event from your javascript. 75 | ```js 76 | performance.mark('Page ready') 77 | ``` 78 | 79 | And add the kebabcased key to `.perf.yml` 80 | 81 | ```yaml 82 | thresholds: 83 | - page-ready: 1500 84 | ``` 85 | 86 | ##### event-type 87 | 88 | For travis users, if you would like to run perfbench in `pull_request` instead of `push`, 89 | set `event-type: pull_request` 90 | 91 | ```yaml 92 | event-type: pull_request 93 | ``` 94 | 95 |   96 | 97 | 2) github token for status 98 | 99 | ![build status](https://raw.githubusercontent.com/siddharthkp/perfbench/master/build-status.png) 100 | 101 | Currently works for [Travis CI](https://travis-ci.org), [CircleCI](https://circleci.com/), [Wercker](wercker.com), and [Drone](http://readme.drone.io/). 102 | 103 | - [Authorize `perfbench` for status access](https://github.com/login/oauth/authorize?scope=repo%3Astatus&client_id=5be3b09eacb8977c79e6), copy the generated token. 104 | 105 | - Add this token as `PERFBENCH_GITHUB_TOKEN` as environment parameter in your CIs project settings. 106 | 107 | (Ask me for help if you're stuck) 108 | 109 | 110 | #### like it? 111 | 112 | :star: this repo 113 | 114 |   115 | 116 | #### todo 117 | 118 | - support multiple urls 119 | 120 |   121 | 122 | #### license 123 | 124 | MIT © [siddharthkp](https://github.com/siddharthkp) 125 | -------------------------------------------------------------------------------- /build-status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siddharthkp/perfbench/007df5249132de1e1c18deae761e4d2e9b37fbad/build-status.png -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const setup = require('./src/setup') 4 | const lighthouse = require('./src/lighthouse') 5 | const reporter = require('./src/reporter') 6 | let settings = require('./src/settings') 7 | const build = require('./src/build') 8 | const { event, branch } = require('ci-env') 9 | const { warn } = require('prettycli') 10 | 11 | const WAIT_BETWEEN_RUNS = 2500 12 | 13 | const results = [] 14 | let runs = settings.runs 15 | 16 | const run = () => { 17 | runs = runs - 1 18 | lighthouse 19 | .run(settings.url) 20 | .then(result => { 21 | results.push(result) 22 | if (runs > 0) setTimeout(run, WAIT_BETWEEN_RUNS) 23 | else reporter.print(results) 24 | }) 25 | .catch(err => { 26 | throw err 27 | }) 28 | } 29 | 30 | const start = () => { 31 | run() 32 | } 33 | 34 | process.on('unhandledRejection', function(reason, p) { 35 | console.log('Unhandled Promise: ', p, ' reason: ', reason) 36 | build.error() 37 | }) 38 | 39 | if (process.env.CI) { 40 | if (branch === 'master' || event === settings.event) { 41 | setup().then(start).catch(error => console.log('Setup failed', error)) 42 | } else if (event === 'pull_request') { 43 | warn( 44 | `perfbench does not run on travis:pull_request 45 | 46 | If you would like to run this in travis:pull_request instead of travis:push, 47 | check configuration options: https://siddharthkp/perfbench#event 48 | ` 49 | ) 50 | } 51 | } else start() 52 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siddharthkp/perfbench/007df5249132de1e1c18deae761e4d2e9b37fbad/logo.png -------------------------------------------------------------------------------- /mock/lighthouse.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const run = () => 4 | new Promise(resolve => { 5 | const results = fs.readFileSync("./results.json", "utf8"); 6 | resolve(JSON.parse(results)); 7 | }); 8 | 9 | module.exports = { run }; 10 | -------------------------------------------------------------------------------- /mock/results.json: -------------------------------------------------------------------------------- 1 | { 2 | "lighthouseVersion": "1.6.3", 3 | "generatedTime": "2017-04-20T11:17:47.016Z", 4 | "initialUrl": "https://www.practo.com/tests/bangalore/pregnancy-test-stick-random-urine", 5 | "url": "https://www.practo.com/tests/bangalore/pregnancy-test-stick-random-urine", 6 | "audits": { 7 | "first-meaningful-paint": { 8 | "score": 52, 9 | "displayValue": "3892.2ms", 10 | "rawValue": 3892.2, 11 | "optimalValue": "1,600ms", 12 | "extendedInfo": { 13 | "value": { 14 | "timestamps": { 15 | "navStart": 17792594079, 16 | "fCP": 17794792290, 17 | "fMP": 17796486232 18 | }, 19 | "timings": { 20 | "navStart": 0, 21 | "fCP": 2198.211, 22 | "fMP": 3892.153 23 | } 24 | }, 25 | "formatter": "null" 26 | }, 27 | "name": "first-meaningful-paint", 28 | "category": "Performance", 29 | "description": "First meaningful paint", 30 | "helpText": "First meaningful paint measures when the primary content of a page is visible. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint)." 31 | }, 32 | "speed-index-metric": { 33 | "score": 18, 34 | "displayValue": "10569", 35 | "rawValue": 10569, 36 | "optimalValue": "1,250", 37 | "extendedInfo": { 38 | "formatter": "speedline", 39 | "value": { 40 | "timings": { 41 | "firstVisualChange": 2336, 42 | "visuallyComplete": 11148, 43 | "speedIndex": 10972.417849997617, 44 | "perceptualSpeedIndex": 10569.103989511119 45 | }, 46 | "timestamps": { 47 | "firstVisualChange": 17794922324, 48 | "visuallyComplete": 17803734324, 49 | "speedIndex": 17803558741.85, 50 | "perceptualSpeedIndex": 17803155427.989513 51 | }, 52 | "frames": [ 53 | { 54 | "timestamp": 17792586.324, 55 | "progress": 0 56 | }, 57 | { 58 | "timestamp": 17794922.596, 59 | "progress": 4.632249349660438 60 | }, 61 | { 62 | "timestamp": 17795126.564, 63 | "progress": 4.638469205268419 64 | }, 65 | { 66 | "timestamp": 17795142.727, 67 | "progress": 4.639162153739748 68 | }, 69 | { 70 | "timestamp": 17795159.005, 71 | "progress": 4.639162153739748 72 | }, 73 | { 74 | "timestamp": 17795175.597, 75 | "progress": 4.6383741780565035 76 | }, 77 | { 78 | "timestamp": 17795192.217, 79 | "progress": 4.638587482913058 80 | }, 81 | { 82 | "timestamp": 17795210.542, 83 | "progress": 4.637244992051461 84 | }, 85 | { 86 | "timestamp": 17795225.995, 87 | "progress": 4.637244992051461 88 | }, 89 | { 90 | "timestamp": 17795243.533, 91 | "progress": 4.637953967463672 92 | }, 93 | { 94 | "timestamp": 17795259.447, 95 | "progress": 4.6370528900459895 96 | }, 97 | { 98 | "timestamp": 17795275.711, 99 | "progress": 4.636640133487143 100 | }, 101 | { 102 | "timestamp": 17795292.433, 103 | "progress": 4.636618346846205 104 | }, 105 | { 106 | "timestamp": 17795309.134, 107 | "progress": 4.636011510211239 108 | }, 109 | { 110 | "timestamp": 17795325.872, 111 | "progress": 4.636011510211239 112 | }, 113 | { 114 | "timestamp": 17795359.179, 115 | "progress": 4.636618346846205 116 | }, 117 | { 118 | "timestamp": 17795375.957, 119 | "progress": 4.636618346846205 120 | }, 121 | { 122 | "timestamp": 17795392.592, 123 | "progress": 4.636527245341333 124 | }, 125 | { 126 | "timestamp": 17795409.451, 127 | "progress": 4.637116350915429 128 | }, 129 | { 130 | "timestamp": 17795426.061, 131 | "progress": 4.636885746263546 132 | }, 133 | { 134 | "timestamp": 17795442.423, 135 | "progress": 4.638401735049216 136 | }, 137 | { 138 | "timestamp": 17795459.172, 139 | "progress": 4.6335601902197 140 | }, 141 | { 142 | "timestamp": 17795475.751, 143 | "progress": 4.635364693172085 144 | }, 145 | { 146 | "timestamp": 17795493.111, 147 | "progress": 4.6398566089640445 148 | }, 149 | { 150 | "timestamp": 17795509.452, 151 | "progress": 4.638880754657769 152 | }, 153 | { 154 | "timestamp": 17795526.141, 155 | "progress": 4.637390129200676 156 | }, 157 | { 158 | "timestamp": 17795543.42, 159 | "progress": 4.638401735049216 160 | }, 161 | { 162 | "timestamp": 17795559.622, 163 | "progress": 4.638392666163962 164 | }, 165 | { 166 | "timestamp": 17795575.855, 167 | "progress": 4.637996589584445 168 | }, 169 | { 170 | "timestamp": 17795592.921, 171 | "progress": 4.63732150328746 172 | }, 173 | { 174 | "timestamp": 17795609.26, 175 | "progress": 4.637440730119833 176 | }, 177 | { 178 | "timestamp": 17795628.902, 179 | "progress": 4.63732150328746 180 | }, 181 | { 182 | "timestamp": 17795643.117, 183 | "progress": 4.63732150328746 184 | }, 185 | { 186 | "timestamp": 17795661.901, 187 | "progress": 4.6379907697333005 188 | }, 189 | { 190 | "timestamp": 17795675.243, 191 | "progress": 4.581219930990162 192 | }, 193 | { 194 | "timestamp": 17795690.956, 195 | "progress": 4.580643695618719 196 | }, 197 | { 198 | "timestamp": 17795711.454, 199 | "progress": 4.577274207347641 200 | }, 201 | { 202 | "timestamp": 17795729.208, 203 | "progress": 4.576147537400308 204 | }, 205 | { 206 | "timestamp": 17795744.569, 207 | "progress": 4.577795075216585 208 | }, 209 | { 210 | "timestamp": 17795761.263, 211 | "progress": 4.578494761805252 212 | }, 213 | { 214 | "timestamp": 17795779.165, 215 | "progress": 4.578494761805252 216 | }, 217 | { 218 | "timestamp": 17795796.153, 219 | "progress": 4.578494761805252 220 | }, 221 | { 222 | "timestamp": 17795812.536, 223 | "progress": 4.574407482535909 224 | }, 225 | { 226 | "timestamp": 17795827.969, 227 | "progress": 4.577221331204453 228 | }, 229 | { 230 | "timestamp": 17795845.406, 231 | "progress": 4.577010120031013 232 | }, 233 | { 234 | "timestamp": 17795861.113, 235 | "progress": 4.576269619845564 236 | }, 237 | { 238 | "timestamp": 17795885.176, 239 | "progress": 4.57558772301686 240 | }, 241 | { 242 | "timestamp": 17795901.519, 243 | "progress": 4.575993357688476 244 | }, 245 | { 246 | "timestamp": 17795915.508, 247 | "progress": 4.575993357688476 248 | }, 249 | { 250 | "timestamp": 17796498.284, 251 | "progress": 6.179595809749249 252 | }, 253 | { 254 | "timestamp": 17796746.562, 255 | "progress": 6.111114320815328 256 | }, 257 | { 258 | "timestamp": 17802215.577, 259 | "progress": 6.111114320815328 260 | }, 261 | { 262 | "timestamp": 17802222.034, 263 | "progress": 10.013069352260459 264 | }, 265 | { 266 | "timestamp": 17802249.022, 267 | "progress": 10.015132176729548 268 | }, 269 | { 270 | "timestamp": 17802267.02, 271 | "progress": 10.016492849422198 272 | }, 273 | { 274 | "timestamp": 17802282.475, 275 | "progress": 10.017086329389011 276 | }, 277 | { 278 | "timestamp": 17802299.472, 279 | "progress": 10.016891902669332 280 | }, 281 | { 282 | "timestamp": 17802316.071, 283 | "progress": 10.017006942727388 284 | }, 285 | { 286 | "timestamp": 17802332.541, 287 | "progress": 10.017058225941424 288 | }, 289 | { 290 | "timestamp": 17802818.936, 291 | "progress": 10.246347440889462 292 | }, 293 | { 294 | "timestamp": 17803584.603, 295 | "progress": 12.126349602182376 296 | }, 297 | { 298 | "timestamp": 17803734.343, 299 | "progress": 100 300 | } 301 | ] 302 | } 303 | }, 304 | "name": "speed-index-metric", 305 | "category": "Performance", 306 | "description": "Perceptual Speed Index", 307 | "helpText": "Speed Index shows how quickly the contents of a page are visibly populated. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/speed-index)." 308 | }, 309 | "time-to-interactive": { 310 | "score": 8, 311 | "displayValue": "11140.3ms", 312 | "rawValue": 11140.3, 313 | "optimalValue": "5,000ms", 314 | "extendedInfo": { 315 | "value": { 316 | "timings": { 317 | "fMP": 3892.2, 318 | "visuallyReady": 11140.264, 319 | "timeToInteractive": 11140.264 320 | }, 321 | "timestamps": { 322 | "fMP": 17796486232, 323 | "visuallyReady": 17803734343, 324 | "timeToInteractive": 17803734343 325 | }, 326 | "expectedLatencyAtTTI": 26.834, 327 | "foundLatencies": [ 328 | { 329 | "estLatency": 26.834000000000003, 330 | "startTime": "11140.3" 331 | } 332 | ] 333 | }, 334 | "formatter": "null" 335 | }, 336 | "name": "time-to-interactive", 337 | "category": "Performance", 338 | "description": "Time To Interactive (alpha)", 339 | "helpText": "Time to Interactive identifies the time at which your app appears to be ready enough to interact with. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive)." 340 | }, 341 | "total-byte-weight": { 342 | "score": 100, 343 | "displayValue": "Total size was 649 KB", 344 | "rawValue": 665062, 345 | "optimalValue": "1,600 KB", 346 | "extendedInfo": { 347 | "formatter": "table", 348 | "value": { 349 | "results": [ 350 | { 351 | "url": "…dist/main.fc52823….bundle.js", 352 | "totalBytes": 158755, 353 | "totalKb": "155 KB", 354 | "totalMs": "1,670ms" 355 | }, 356 | { 357 | "url": "…dist/CityTestListingPage.9011acf….bundle.js", 358 | "totalBytes": 120354, 359 | "totalKb": "118 KB", 360 | "totalMs": "1,270ms" 361 | }, 362 | { 363 | "url": "…dist/vendor.d87444f….bundle.js", 364 | "totalBytes": 63479, 365 | "totalKb": "62 KB", 366 | "totalMs": "670ms" 367 | }, 368 | { 369 | "url": "…v6/practicon.woff2", 370 | "totalBytes": 49882, 371 | "totalKb": "49 KB", 372 | "totalMs": "530ms" 373 | }, 374 | { 375 | "url": "…camphor/677b110e-fe2c-4af7-b50b-3e8f00c371ce.woff2", 376 | "totalBytes": 37494, 377 | "totalKb": "37 KB", 378 | "totalMs": "400ms" 379 | }, 380 | { 381 | "url": "…camphor/c96be38e-ea64-418f-ae54-e757ed92b069.woff2", 382 | "totalBytes": 37452, 383 | "totalKb": "37 KB", 384 | "totalMs": "390ms" 385 | }, 386 | { 387 | "url": "…bangalore/pregnancy-test-stick-random-urine", 388 | "totalBytes": 30671, 389 | "totalKb": "30 KB", 390 | "totalMs": "320ms" 391 | }, 392 | { 393 | "url": "…dist/main.fc52823….css", 394 | "totalBytes": 30141, 395 | "totalKb": "29 KB", 396 | "totalMs": "320ms" 397 | }, 398 | { 399 | "url": "…js/practonav.js", 400 | "totalBytes": 18651, 401 | "totalKb": "18 KB", 402 | "totalMs": "200ms" 403 | }, 404 | { 405 | "url": "/nr-spa-974.min.js", 406 | "totalBytes": 12354, 407 | "totalKb": "12 KB", 408 | "totalMs": "130ms" 409 | } 410 | ], 411 | "tableHeadings": { 412 | "url": "URL", 413 | "totalKb": "Total Size", 414 | "totalMs": "Transfer Time" 415 | } 416 | } 417 | }, 418 | "informative": true, 419 | "name": "total-byte-weight", 420 | "category": "Network", 421 | "description": "Avoids enormous network payloads", 422 | "helpText": "Network transfer size [costs users real dollars](https://whatdoesmysitecost.com/) and is [highly correlated](http://httparchive.org/interesting.php#onLoad) with long load times. Try to find ways to reduce the size of required files." 423 | }, 424 | "user-timings": { 425 | "score": true, 426 | "displayValue": "0", 427 | "rawValue": true, 428 | "extendedInfo": { 429 | "formatter": "userTimings", 430 | "value": [] 431 | }, 432 | "informative": true, 433 | "name": "user-timings", 434 | "category": "Performance", 435 | "description": "User Timing marks and measures", 436 | "helpText": "Consider instrumenting your app with the User Timing API to create custom, real-world measurements of key user experiences. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/user-timing)." 437 | } 438 | }, 439 | "runtimeConfig": { 440 | "environment": [ 441 | { 442 | "name": "Device Emulation", 443 | "enabled": false, 444 | "description": "Nexus 5X" 445 | }, 446 | { 447 | "name": "Network Throttling", 448 | "enabled": true, 449 | "description": "150ms RTT, 0.7Mbps down, 0.2Mbps up" 450 | }, 451 | { 452 | "name": "CPU Throttling", 453 | "enabled": true, 454 | "description": "5x slowdown" 455 | } 456 | ], 457 | "blockedUrlPatterns": [] 458 | }, 459 | "aggregations": [] 460 | } 461 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "perfbench", 3 | "version": "1.8.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "adm-zip": { 8 | "version": "0.4.7", 9 | "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.7.tgz", 10 | "integrity": "sha1-hgbCy/HEJs6MjsABdER/1Jtur8E=" 11 | }, 12 | "agent-base": { 13 | "version": "2.1.1", 14 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", 15 | "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", 16 | "requires": { 17 | "extend": "3.0.1", 18 | "semver": "5.0.3" 19 | }, 20 | "dependencies": { 21 | "semver": { 22 | "version": "5.0.3", 23 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", 24 | "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=" 25 | } 26 | } 27 | }, 28 | "ajv": { 29 | "version": "4.11.8", 30 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", 31 | "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", 32 | "requires": { 33 | "co": "4.6.0", 34 | "json-stable-stringify": "1.0.1" 35 | } 36 | }, 37 | "amdefine": { 38 | "version": "1.0.1", 39 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 40 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" 41 | }, 42 | "ansi-escapes": { 43 | "version": "1.4.0", 44 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", 45 | "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", 46 | "dev": true 47 | }, 48 | "ansi-regex": { 49 | "version": "2.1.1", 50 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 51 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 52 | }, 53 | "ansi-styles": { 54 | "version": "2.2.1", 55 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 56 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 57 | }, 58 | "app-root-path": { 59 | "version": "2.0.1", 60 | "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz", 61 | "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=", 62 | "dev": true 63 | }, 64 | "argparse": { 65 | "version": "1.0.9", 66 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", 67 | "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", 68 | "requires": { 69 | "sprintf-js": "1.0.3" 70 | } 71 | }, 72 | "array-find-index": { 73 | "version": "1.0.2", 74 | "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", 75 | "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" 76 | }, 77 | "array-union": { 78 | "version": "1.0.2", 79 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", 80 | "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", 81 | "requires": { 82 | "array-uniq": "1.0.3" 83 | } 84 | }, 85 | "array-uniq": { 86 | "version": "1.0.3", 87 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 88 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" 89 | }, 90 | "arrify": { 91 | "version": "1.0.1", 92 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 93 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" 94 | }, 95 | "asn1": { 96 | "version": "0.2.3", 97 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", 98 | "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" 99 | }, 100 | "assert-plus": { 101 | "version": "0.2.0", 102 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", 103 | "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" 104 | }, 105 | "ast-types": { 106 | "version": "0.9.8", 107 | "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.8.tgz", 108 | "integrity": "sha1-bLakC+ujH0nyCSjihDn8FKPasHg=", 109 | "dev": true 110 | }, 111 | "async": { 112 | "version": "1.5.2", 113 | "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", 114 | "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" 115 | }, 116 | "asynckit": { 117 | "version": "0.4.0", 118 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 119 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 120 | }, 121 | "aws-sign2": { 122 | "version": "0.6.0", 123 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", 124 | "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" 125 | }, 126 | "aws4": { 127 | "version": "1.6.0", 128 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", 129 | "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" 130 | }, 131 | "axe-core": { 132 | "version": "2.1.7", 133 | "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-2.1.7.tgz", 134 | "integrity": "sha1-T2bys+47WOwtPbQzndEkxbM7ecM=" 135 | }, 136 | "axios": { 137 | "version": "0.15.3", 138 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", 139 | "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", 140 | "requires": { 141 | "follow-redirects": "1.0.0" 142 | } 143 | }, 144 | "babar": { 145 | "version": "0.0.3", 146 | "resolved": "https://registry.npmjs.org/babar/-/babar-0.0.3.tgz", 147 | "integrity": "sha1-LzlNSlkY9+GunlQI6alvP5Ne4eI=", 148 | "requires": { 149 | "colors": "0.6.2" 150 | }, 151 | "dependencies": { 152 | "colors": { 153 | "version": "0.6.2", 154 | "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", 155 | "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" 156 | } 157 | } 158 | }, 159 | "babel-code-frame": { 160 | "version": "6.22.0", 161 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", 162 | "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", 163 | "dev": true, 164 | "requires": { 165 | "chalk": "1.1.3", 166 | "esutils": "2.0.2", 167 | "js-tokens": "3.0.1" 168 | } 169 | }, 170 | "babylon": { 171 | "version": "7.0.0-beta.8", 172 | "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.8.tgz", 173 | "integrity": "sha1-K9xa42YEFELCfgaMzm8NfAbqmUk=", 174 | "dev": true 175 | }, 176 | "balanced-match": { 177 | "version": "0.4.2", 178 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", 179 | "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" 180 | }, 181 | "bcrypt-pbkdf": { 182 | "version": "1.0.1", 183 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", 184 | "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", 185 | "optional": true, 186 | "requires": { 187 | "tweetnacl": "0.14.5" 188 | } 189 | }, 190 | "boom": { 191 | "version": "2.10.1", 192 | "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", 193 | "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", 194 | "requires": { 195 | "hoek": "2.16.3" 196 | } 197 | }, 198 | "brace-expansion": { 199 | "version": "1.1.7", 200 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", 201 | "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", 202 | "requires": { 203 | "balanced-match": "0.4.2", 204 | "concat-map": "0.0.1" 205 | } 206 | }, 207 | "buffer-crc32": { 208 | "version": "0.2.13", 209 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 210 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" 211 | }, 212 | "builtin-modules": { 213 | "version": "1.1.1", 214 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 215 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" 216 | }, 217 | "camelcase-keys": { 218 | "version": "2.1.0", 219 | "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", 220 | "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", 221 | "requires": { 222 | "camelcase": "2.1.1", 223 | "map-obj": "1.0.1" 224 | }, 225 | "dependencies": { 226 | "camelcase": { 227 | "version": "2.1.1", 228 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", 229 | "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" 230 | } 231 | } 232 | }, 233 | "caseless": { 234 | "version": "0.12.0", 235 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 236 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 237 | }, 238 | "chalk": { 239 | "version": "1.1.3", 240 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 241 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 242 | "requires": { 243 | "ansi-styles": "2.2.1", 244 | "escape-string-regexp": "1.0.5", 245 | "has-ansi": "2.0.0", 246 | "strip-ansi": "3.0.1", 247 | "supports-color": "2.0.0" 248 | } 249 | }, 250 | "chrome-devtools-frontend": { 251 | "version": "1.0.422034", 252 | "resolved": "https://registry.npmjs.org/chrome-devtools-frontend/-/chrome-devtools-frontend-1.0.422034.tgz", 253 | "integrity": "sha1-BxyM4URmt2UwMvzRrRpKaNXjy9k=" 254 | }, 255 | "ci-env": { 256 | "version": "1.4.0", 257 | "resolved": "https://registry.npmjs.org/ci-env/-/ci-env-1.4.0.tgz", 258 | "integrity": "sha512-IRvBrZSkdlsHgGZtaM41WBHJKEHpheqMO6B8lHN452zHiKN0imDcDjI9rIqIA4Y5/2uOAxnA8yYqWBzoYqxMMQ==" 259 | }, 260 | "ci-info": { 261 | "version": "1.0.0", 262 | "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.0.0.tgz", 263 | "integrity": "sha1-3FKF8rTiUYIWg2gcOBwziPRuxTQ=", 264 | "dev": true 265 | }, 266 | "cli-cursor": { 267 | "version": "1.0.2", 268 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", 269 | "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", 270 | "dev": true, 271 | "requires": { 272 | "restore-cursor": "1.0.1" 273 | } 274 | }, 275 | "cli-spinners": { 276 | "version": "0.1.2", 277 | "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", 278 | "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", 279 | "dev": true 280 | }, 281 | "cli-table2": { 282 | "version": "0.2.0", 283 | "resolved": "https://registry.npmjs.org/cli-table2/-/cli-table2-0.2.0.tgz", 284 | "integrity": "sha1-LR738hig54biFFQFYtS9F3/jLZc=", 285 | "requires": { 286 | "colors": "1.1.2", 287 | "lodash": "3.10.1", 288 | "string-width": "1.0.2" 289 | } 290 | }, 291 | "cli-truncate": { 292 | "version": "0.2.1", 293 | "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", 294 | "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", 295 | "dev": true, 296 | "requires": { 297 | "slice-ansi": "0.0.4", 298 | "string-width": "1.0.2" 299 | } 300 | }, 301 | "co": { 302 | "version": "4.6.0", 303 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 304 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" 305 | }, 306 | "code-point-at": { 307 | "version": "1.1.0", 308 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 309 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" 310 | }, 311 | "color-convert": { 312 | "version": "1.9.0", 313 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", 314 | "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", 315 | "dev": true, 316 | "requires": { 317 | "color-name": "1.1.2" 318 | } 319 | }, 320 | "color-name": { 321 | "version": "1.1.2", 322 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.2.tgz", 323 | "integrity": "sha1-XIq3K2S9IhXWF66VWeuxSEdc+Y0=", 324 | "dev": true 325 | }, 326 | "colors": { 327 | "version": "1.1.2", 328 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", 329 | "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" 330 | }, 331 | "combined-stream": { 332 | "version": "1.0.5", 333 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", 334 | "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", 335 | "requires": { 336 | "delayed-stream": "1.0.0" 337 | } 338 | }, 339 | "commander": { 340 | "version": "2.9.0", 341 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", 342 | "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", 343 | "dev": true, 344 | "requires": { 345 | "graceful-readlink": "1.0.1" 346 | } 347 | }, 348 | "concat-map": { 349 | "version": "0.0.1", 350 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 351 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 352 | }, 353 | "cosmiconfig": { 354 | "version": "1.1.0", 355 | "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-1.1.0.tgz", 356 | "integrity": "sha1-DeoPmATv37kp+7GxiOJVU+oFPTc=", 357 | "dev": true, 358 | "requires": { 359 | "graceful-fs": "4.1.11", 360 | "js-yaml": "3.8.4", 361 | "minimist": "1.2.0", 362 | "object-assign": "4.1.1", 363 | "os-homedir": "1.0.2", 364 | "parse-json": "2.2.0", 365 | "pinkie-promise": "2.0.1", 366 | "require-from-string": "1.2.1" 367 | }, 368 | "dependencies": { 369 | "minimist": { 370 | "version": "1.2.0", 371 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 372 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", 373 | "dev": true 374 | } 375 | } 376 | }, 377 | "cross-spawn": { 378 | "version": "5.1.0", 379 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", 380 | "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", 381 | "dev": true, 382 | "requires": { 383 | "lru-cache": "4.0.2", 384 | "shebang-command": "1.2.0", 385 | "which": "1.2.14" 386 | } 387 | }, 388 | "cryptiles": { 389 | "version": "2.0.5", 390 | "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", 391 | "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", 392 | "requires": { 393 | "boom": "2.10.1" 394 | } 395 | }, 396 | "currently-unhandled": { 397 | "version": "0.4.1", 398 | "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", 399 | "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", 400 | "requires": { 401 | "array-find-index": "1.0.2" 402 | } 403 | }, 404 | "dashdash": { 405 | "version": "1.14.1", 406 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 407 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 408 | "requires": { 409 | "assert-plus": "1.0.0" 410 | }, 411 | "dependencies": { 412 | "assert-plus": { 413 | "version": "1.0.0", 414 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 415 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 416 | } 417 | } 418 | }, 419 | "date-fns": { 420 | "version": "1.28.4", 421 | "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.28.4.tgz", 422 | "integrity": "sha1-eTiuw0ujH8i9E00jRLwuC7/ZUWU=", 423 | "dev": true 424 | }, 425 | "debug": { 426 | "version": "2.2.0", 427 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 428 | "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", 429 | "requires": { 430 | "ms": "0.7.1" 431 | } 432 | }, 433 | "decamelize": { 434 | "version": "1.2.0", 435 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 436 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 437 | }, 438 | "del": { 439 | "version": "2.2.2", 440 | "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", 441 | "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", 442 | "requires": { 443 | "globby": "5.0.0", 444 | "is-path-cwd": "1.0.0", 445 | "is-path-in-cwd": "1.0.0", 446 | "object-assign": "4.1.1", 447 | "pify": "2.3.0", 448 | "pinkie-promise": "2.0.1", 449 | "rimraf": "2.2.8" 450 | } 451 | }, 452 | "delayed-stream": { 453 | "version": "1.0.0", 454 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 455 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 456 | }, 457 | "devtools-timeline-model": { 458 | "version": "1.1.6", 459 | "resolved": "https://registry.npmjs.org/devtools-timeline-model/-/devtools-timeline-model-1.1.6.tgz", 460 | "integrity": "sha1-e+Uac7VdcntZe7MN0e0ujiEGOaU=", 461 | "requires": { 462 | "chrome-devtools-frontend": "1.0.401423", 463 | "resolve": "1.1.7" 464 | }, 465 | "dependencies": { 466 | "chrome-devtools-frontend": { 467 | "version": "1.0.401423", 468 | "resolved": "https://registry.npmjs.org/chrome-devtools-frontend/-/chrome-devtools-frontend-1.0.401423.tgz", 469 | "integrity": "sha1-MqibjQTjeKSUvjyNYycXA74cBOo=" 470 | } 471 | } 472 | }, 473 | "dmg": { 474 | "version": "0.1.0", 475 | "resolved": "https://registry.npmjs.org/dmg/-/dmg-0.1.0.tgz", 476 | "integrity": "sha1-s46iEH9vCwcEQrv3mb/E8q7apfg=" 477 | }, 478 | "ecc-jsbn": { 479 | "version": "0.1.1", 480 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", 481 | "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", 482 | "optional": true, 483 | "requires": { 484 | "jsbn": "0.1.1" 485 | } 486 | }, 487 | "elegant-spinner": { 488 | "version": "1.0.1", 489 | "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", 490 | "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", 491 | "dev": true 492 | }, 493 | "error-ex": { 494 | "version": "1.3.1", 495 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", 496 | "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", 497 | "requires": { 498 | "is-arrayish": "0.2.1" 499 | } 500 | }, 501 | "escape-string-regexp": { 502 | "version": "1.0.5", 503 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 504 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 505 | }, 506 | "esprima": { 507 | "version": "3.1.3", 508 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", 509 | "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" 510 | }, 511 | "esutils": { 512 | "version": "2.0.2", 513 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 514 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 515 | "dev": true 516 | }, 517 | "execa": { 518 | "version": "0.6.3", 519 | "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", 520 | "integrity": "sha1-V7aaWU8IF1nGnlNw8NF7nLEWWP4=", 521 | "dev": true, 522 | "requires": { 523 | "cross-spawn": "5.1.0", 524 | "get-stream": "3.0.0", 525 | "is-stream": "1.1.0", 526 | "npm-run-path": "2.0.2", 527 | "p-finally": "1.0.0", 528 | "signal-exit": "3.0.2", 529 | "strip-eof": "1.0.0" 530 | } 531 | }, 532 | "exit-hook": { 533 | "version": "1.1.1", 534 | "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", 535 | "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", 536 | "dev": true 537 | }, 538 | "extend": { 539 | "version": "3.0.1", 540 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", 541 | "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" 542 | }, 543 | "extsprintf": { 544 | "version": "1.0.2", 545 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", 546 | "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" 547 | }, 548 | "fd-slicer": { 549 | "version": "1.0.1", 550 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", 551 | "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", 552 | "requires": { 553 | "pend": "1.2.0" 554 | } 555 | }, 556 | "figures": { 557 | "version": "1.7.0", 558 | "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", 559 | "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", 560 | "dev": true, 561 | "requires": { 562 | "escape-string-regexp": "1.0.5", 563 | "object-assign": "4.1.1" 564 | } 565 | }, 566 | "find-parent-dir": { 567 | "version": "0.3.0", 568 | "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", 569 | "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", 570 | "dev": true 571 | }, 572 | "find-up": { 573 | "version": "1.1.2", 574 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", 575 | "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", 576 | "requires": { 577 | "path-exists": "2.1.0", 578 | "pinkie-promise": "2.0.1" 579 | } 580 | }, 581 | "flow-parser": { 582 | "version": "0.43.0", 583 | "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.43.0.tgz", 584 | "integrity": "sha1-4rjrGsg91T97awSnw1tqUsM0ebc=", 585 | "dev": true 586 | }, 587 | "follow-redirects": { 588 | "version": "1.0.0", 589 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", 590 | "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", 591 | "requires": { 592 | "debug": "2.2.0" 593 | } 594 | }, 595 | "forever-agent": { 596 | "version": "0.6.1", 597 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 598 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 599 | }, 600 | "form-data": { 601 | "version": "2.1.4", 602 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", 603 | "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", 604 | "requires": { 605 | "asynckit": "0.4.0", 606 | "combined-stream": "1.0.5", 607 | "mime-types": "2.1.15" 608 | } 609 | }, 610 | "fs-extra": { 611 | "version": "2.1.2", 612 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", 613 | "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", 614 | "requires": { 615 | "graceful-fs": "4.1.11", 616 | "jsonfile": "2.4.0" 617 | } 618 | }, 619 | "fs.realpath": { 620 | "version": "1.0.0", 621 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 622 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 623 | }, 624 | "get-stdin": { 625 | "version": "4.0.1", 626 | "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", 627 | "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" 628 | }, 629 | "get-stream": { 630 | "version": "3.0.0", 631 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", 632 | "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", 633 | "dev": true 634 | }, 635 | "getpass": { 636 | "version": "0.1.7", 637 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 638 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 639 | "requires": { 640 | "assert-plus": "1.0.0" 641 | }, 642 | "dependencies": { 643 | "assert-plus": { 644 | "version": "1.0.0", 645 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 646 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 647 | } 648 | } 649 | }, 650 | "github-build": { 651 | "version": "1.2.0", 652 | "resolved": "https://registry.npmjs.org/github-build/-/github-build-1.2.0.tgz", 653 | "integrity": "sha512-Iq7NialLYz5yRZDkiX8zaOWd+N3BssJJfUvG7wd8r4MeLCN88SdxEYo2esseMLpLtP4vNXhgamg1eRm7hw59qw==", 654 | "requires": { 655 | "axios": "0.15.3" 656 | } 657 | }, 658 | "gl-matrix": { 659 | "version": "2.3.2", 660 | "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-2.3.2.tgz", 661 | "integrity": "sha1-qsgIx0r31dsF/gTLYMoaD8sXTXQ=" 662 | }, 663 | "glob": { 664 | "version": "7.1.1", 665 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", 666 | "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", 667 | "requires": { 668 | "fs.realpath": "1.0.0", 669 | "inflight": "1.0.6", 670 | "inherits": "2.0.3", 671 | "minimatch": "3.0.4", 672 | "once": "1.4.0", 673 | "path-is-absolute": "1.0.1" 674 | } 675 | }, 676 | "globby": { 677 | "version": "5.0.0", 678 | "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", 679 | "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", 680 | "requires": { 681 | "array-union": "1.0.2", 682 | "arrify": "1.0.1", 683 | "glob": "7.1.1", 684 | "object-assign": "4.1.1", 685 | "pify": "2.3.0", 686 | "pinkie-promise": "2.0.1" 687 | } 688 | }, 689 | "graceful-fs": { 690 | "version": "4.1.11", 691 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 692 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" 693 | }, 694 | "graceful-readlink": { 695 | "version": "1.0.1", 696 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 697 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", 698 | "dev": true 699 | }, 700 | "handlebars": { 701 | "version": "4.0.5", 702 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.5.tgz", 703 | "integrity": "sha1-ksbta7FkEQxQ1NjQ+93HCAbG+Oc=", 704 | "requires": { 705 | "async": "1.5.2", 706 | "optimist": "0.6.1", 707 | "source-map": "0.4.4", 708 | "uglify-js": "2.8.27" 709 | } 710 | }, 711 | "har-schema": { 712 | "version": "1.0.5", 713 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", 714 | "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" 715 | }, 716 | "har-validator": { 717 | "version": "4.2.1", 718 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", 719 | "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", 720 | "requires": { 721 | "ajv": "4.11.8", 722 | "har-schema": "1.0.5" 723 | } 724 | }, 725 | "has-ansi": { 726 | "version": "2.0.0", 727 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 728 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 729 | "requires": { 730 | "ansi-regex": "2.1.1" 731 | } 732 | }, 733 | "hawk": { 734 | "version": "3.1.3", 735 | "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", 736 | "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", 737 | "requires": { 738 | "boom": "2.10.1", 739 | "cryptiles": "2.0.5", 740 | "hoek": "2.16.3", 741 | "sntp": "1.0.9" 742 | } 743 | }, 744 | "hoek": { 745 | "version": "2.16.3", 746 | "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", 747 | "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" 748 | }, 749 | "hosted-git-info": { 750 | "version": "2.4.2", 751 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz", 752 | "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=" 753 | }, 754 | "http-signature": { 755 | "version": "1.1.1", 756 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", 757 | "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", 758 | "requires": { 759 | "assert-plus": "0.2.0", 760 | "jsprim": "1.4.0", 761 | "sshpk": "1.13.0" 762 | } 763 | }, 764 | "https-proxy-agent": { 765 | "version": "1.0.0", 766 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", 767 | "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", 768 | "requires": { 769 | "agent-base": "2.1.1", 770 | "debug": "2.2.0", 771 | "extend": "3.0.1" 772 | } 773 | }, 774 | "husky": { 775 | "version": "0.13.3", 776 | "resolved": "https://registry.npmjs.org/husky/-/husky-0.13.3.tgz", 777 | "integrity": "sha1-vCBmCAutyLj+NRbogfW8aKVwUv8=", 778 | "dev": true, 779 | "requires": { 780 | "chalk": "1.1.3", 781 | "find-parent-dir": "0.3.0", 782 | "is-ci": "1.0.10", 783 | "normalize-path": "1.0.0" 784 | } 785 | }, 786 | "image-ssim": { 787 | "version": "0.2.0", 788 | "resolved": "https://registry.npmjs.org/image-ssim/-/image-ssim-0.2.0.tgz", 789 | "integrity": "sha1-g7Qsei5uS4VQVHf+aRf128VkIOU=" 790 | }, 791 | "imurmurhash": { 792 | "version": "0.1.4", 793 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 794 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" 795 | }, 796 | "indent-string": { 797 | "version": "2.1.0", 798 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", 799 | "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", 800 | "requires": { 801 | "repeating": "2.0.1" 802 | } 803 | }, 804 | "inflight": { 805 | "version": "1.0.6", 806 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 807 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 808 | "requires": { 809 | "once": "1.4.0", 810 | "wrappy": "1.0.2" 811 | } 812 | }, 813 | "inherits": { 814 | "version": "2.0.3", 815 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 816 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 817 | }, 818 | "invert-kv": { 819 | "version": "1.0.0", 820 | "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", 821 | "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" 822 | }, 823 | "is-arrayish": { 824 | "version": "0.2.1", 825 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 826 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" 827 | }, 828 | "is-builtin-module": { 829 | "version": "1.0.0", 830 | "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", 831 | "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", 832 | "requires": { 833 | "builtin-modules": "1.1.1" 834 | } 835 | }, 836 | "is-ci": { 837 | "version": "1.0.10", 838 | "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", 839 | "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=", 840 | "dev": true, 841 | "requires": { 842 | "ci-info": "1.0.0" 843 | } 844 | }, 845 | "is-finite": { 846 | "version": "1.0.2", 847 | "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", 848 | "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", 849 | "requires": { 850 | "number-is-nan": "1.0.1" 851 | } 852 | }, 853 | "is-fullwidth-code-point": { 854 | "version": "1.0.0", 855 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 856 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 857 | "requires": { 858 | "number-is-nan": "1.0.1" 859 | } 860 | }, 861 | "is-path-cwd": { 862 | "version": "1.0.0", 863 | "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", 864 | "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" 865 | }, 866 | "is-path-in-cwd": { 867 | "version": "1.0.0", 868 | "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", 869 | "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", 870 | "requires": { 871 | "is-path-inside": "1.0.0" 872 | } 873 | }, 874 | "is-path-inside": { 875 | "version": "1.0.0", 876 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", 877 | "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", 878 | "requires": { 879 | "path-is-inside": "1.0.2" 880 | } 881 | }, 882 | "is-promise": { 883 | "version": "2.1.0", 884 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 885 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", 886 | "dev": true 887 | }, 888 | "is-stream": { 889 | "version": "1.1.0", 890 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 891 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", 892 | "dev": true 893 | }, 894 | "is-typedarray": { 895 | "version": "1.0.0", 896 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 897 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 898 | }, 899 | "is-utf8": { 900 | "version": "0.2.1", 901 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", 902 | "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" 903 | }, 904 | "isexe": { 905 | "version": "2.0.0", 906 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 907 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 908 | }, 909 | "isstream": { 910 | "version": "0.1.2", 911 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 912 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 913 | }, 914 | "jest-matcher-utils": { 915 | "version": "19.0.0", 916 | "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-19.0.0.tgz", 917 | "integrity": "sha1-Xs2bY1ZdKwAfYfv37Ex/U3lkVk0=", 918 | "dev": true, 919 | "requires": { 920 | "chalk": "1.1.3", 921 | "pretty-format": "19.0.0" 922 | } 923 | }, 924 | "jest-validate": { 925 | "version": "19.0.0", 926 | "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-19.0.0.tgz", 927 | "integrity": "sha1-jGMYog7P6roLpTeL+7gner3tQXM=", 928 | "dev": true, 929 | "requires": { 930 | "chalk": "1.1.3", 931 | "jest-matcher-utils": "19.0.0", 932 | "leven": "2.1.0", 933 | "pretty-format": "19.0.0" 934 | } 935 | }, 936 | "jodid25519": { 937 | "version": "1.0.2", 938 | "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", 939 | "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", 940 | "optional": true, 941 | "requires": { 942 | "jsbn": "0.1.1" 943 | } 944 | }, 945 | "jpeg-js": { 946 | "version": "0.1.2", 947 | "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.1.2.tgz", 948 | "integrity": "sha1-E1uZLAV1yYXPoPSUoyJ+0jhYPs4=" 949 | }, 950 | "js-tokens": { 951 | "version": "3.0.1", 952 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", 953 | "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", 954 | "dev": true 955 | }, 956 | "js-yaml": { 957 | "version": "3.8.4", 958 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz", 959 | "integrity": "sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=", 960 | "requires": { 961 | "argparse": "1.0.9", 962 | "esprima": "3.1.3" 963 | } 964 | }, 965 | "jsbn": { 966 | "version": "0.1.1", 967 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 968 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 969 | "optional": true 970 | }, 971 | "json-schema": { 972 | "version": "0.2.3", 973 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 974 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 975 | }, 976 | "json-stable-stringify": { 977 | "version": "1.0.1", 978 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", 979 | "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", 980 | "requires": { 981 | "jsonify": "0.0.0" 982 | } 983 | }, 984 | "json-stringify-safe": { 985 | "version": "5.0.1", 986 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 987 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 988 | }, 989 | "jsonfile": { 990 | "version": "2.4.0", 991 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", 992 | "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", 993 | "requires": { 994 | "graceful-fs": "4.1.11" 995 | } 996 | }, 997 | "jsonify": { 998 | "version": "0.0.0", 999 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", 1000 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" 1001 | }, 1002 | "jsprim": { 1003 | "version": "1.4.0", 1004 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", 1005 | "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", 1006 | "requires": { 1007 | "assert-plus": "1.0.0", 1008 | "extsprintf": "1.0.2", 1009 | "json-schema": "0.2.3", 1010 | "verror": "1.3.6" 1011 | }, 1012 | "dependencies": { 1013 | "assert-plus": { 1014 | "version": "1.0.0", 1015 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 1016 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 1017 | } 1018 | } 1019 | }, 1020 | "lcid": { 1021 | "version": "1.0.0", 1022 | "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", 1023 | "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", 1024 | "requires": { 1025 | "invert-kv": "1.0.0" 1026 | } 1027 | }, 1028 | "leven": { 1029 | "version": "2.1.0", 1030 | "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", 1031 | "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", 1032 | "dev": true 1033 | }, 1034 | "lighthouse": { 1035 | "version": "1.6.3", 1036 | "resolved": "https://registry.npmjs.org/lighthouse/-/lighthouse-1.6.3.tgz", 1037 | "integrity": "sha1-CZ70hNlNhE+rcYnvEF4fM0ZDJrY=", 1038 | "requires": { 1039 | "axe-core": "2.1.7", 1040 | "chrome-devtools-frontend": "1.0.422034", 1041 | "debug": "2.2.0", 1042 | "devtools-timeline-model": "1.1.6", 1043 | "gl-matrix": "2.3.2", 1044 | "handlebars": "4.0.5", 1045 | "json-stringify-safe": "5.0.1", 1046 | "marked": "0.3.6", 1047 | "metaviewport-parser": "0.0.1", 1048 | "mkdirp": "0.5.1", 1049 | "opn": "4.0.2", 1050 | "rimraf": "2.2.8", 1051 | "semver": "5.3.0", 1052 | "speedline": "1.0.3", 1053 | "whatwg-url": "4.0.0", 1054 | "ws": "1.1.1", 1055 | "yargs": "3.32.0" 1056 | } 1057 | }, 1058 | "lint-staged": { 1059 | "version": "3.4.0", 1060 | "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-3.4.0.tgz", 1061 | "integrity": "sha1-UvqF38krscb+itDQ2YyhOSTgPks=", 1062 | "dev": true, 1063 | "requires": { 1064 | "app-root-path": "2.0.1", 1065 | "cosmiconfig": "1.1.0", 1066 | "execa": "0.6.3", 1067 | "listr": "0.11.0", 1068 | "minimatch": "3.0.4", 1069 | "npm-which": "3.0.1", 1070 | "staged-git-files": "0.0.4" 1071 | } 1072 | }, 1073 | "listr": { 1074 | "version": "0.11.0", 1075 | "resolved": "https://registry.npmjs.org/listr/-/listr-0.11.0.tgz", 1076 | "integrity": "sha1-XneLwjgGrDq5hO11VkRYFR85sD4=", 1077 | "dev": true, 1078 | "requires": { 1079 | "chalk": "1.1.3", 1080 | "cli-truncate": "0.2.1", 1081 | "figures": "1.7.0", 1082 | "indent-string": "2.1.0", 1083 | "is-promise": "2.1.0", 1084 | "is-stream": "1.1.0", 1085 | "listr-silent-renderer": "1.1.1", 1086 | "listr-update-renderer": "0.2.0", 1087 | "listr-verbose-renderer": "0.4.0", 1088 | "log-symbols": "1.0.2", 1089 | "log-update": "1.0.2", 1090 | "ora": "0.2.3", 1091 | "rxjs": "5.3.1", 1092 | "stream-to-observable": "0.1.0", 1093 | "strip-ansi": "3.0.1" 1094 | } 1095 | }, 1096 | "listr-silent-renderer": { 1097 | "version": "1.1.1", 1098 | "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", 1099 | "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", 1100 | "dev": true 1101 | }, 1102 | "listr-update-renderer": { 1103 | "version": "0.2.0", 1104 | "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz", 1105 | "integrity": "sha1-yoDhd5tOcCZoB+ju0a1qvjmFUPk=", 1106 | "dev": true, 1107 | "requires": { 1108 | "chalk": "1.1.3", 1109 | "cli-truncate": "0.2.1", 1110 | "elegant-spinner": "1.0.1", 1111 | "figures": "1.7.0", 1112 | "indent-string": "3.1.0", 1113 | "log-symbols": "1.0.2", 1114 | "log-update": "1.0.2", 1115 | "strip-ansi": "3.0.1" 1116 | }, 1117 | "dependencies": { 1118 | "indent-string": { 1119 | "version": "3.1.0", 1120 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.1.0.tgz", 1121 | "integrity": "sha1-CP9DNGAziDmbMp5rlTjcejz13n0=", 1122 | "dev": true 1123 | } 1124 | } 1125 | }, 1126 | "listr-verbose-renderer": { 1127 | "version": "0.4.0", 1128 | "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.0.tgz", 1129 | "integrity": "sha1-RNwBuww0oDxXIVTU0Izemx3FYg8=", 1130 | "dev": true, 1131 | "requires": { 1132 | "chalk": "1.1.3", 1133 | "cli-cursor": "1.0.2", 1134 | "date-fns": "1.28.4", 1135 | "figures": "1.7.0" 1136 | } 1137 | }, 1138 | "load-json-file": { 1139 | "version": "1.1.0", 1140 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", 1141 | "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", 1142 | "requires": { 1143 | "graceful-fs": "4.1.11", 1144 | "parse-json": "2.2.0", 1145 | "pify": "2.3.0", 1146 | "pinkie-promise": "2.0.1", 1147 | "strip-bom": "2.0.0" 1148 | } 1149 | }, 1150 | "locate-path": { 1151 | "version": "2.0.0", 1152 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", 1153 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", 1154 | "requires": { 1155 | "p-locate": "2.0.0", 1156 | "path-exists": "3.0.0" 1157 | }, 1158 | "dependencies": { 1159 | "path-exists": { 1160 | "version": "3.0.0", 1161 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1162 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" 1163 | } 1164 | } 1165 | }, 1166 | "lodash": { 1167 | "version": "3.10.1", 1168 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", 1169 | "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" 1170 | }, 1171 | "lodash.kebabcase": { 1172 | "version": "4.1.1", 1173 | "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", 1174 | "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=" 1175 | }, 1176 | "lodash.startcase": { 1177 | "version": "4.4.0", 1178 | "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", 1179 | "integrity": "sha1-lDbjTtJgk+1/+uGTYUQ1CRXZrdg=" 1180 | }, 1181 | "log-symbols": { 1182 | "version": "1.0.2", 1183 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", 1184 | "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", 1185 | "dev": true, 1186 | "requires": { 1187 | "chalk": "1.1.3" 1188 | } 1189 | }, 1190 | "log-update": { 1191 | "version": "1.0.2", 1192 | "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", 1193 | "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", 1194 | "dev": true, 1195 | "requires": { 1196 | "ansi-escapes": "1.4.0", 1197 | "cli-cursor": "1.0.2" 1198 | } 1199 | }, 1200 | "loud-rejection": { 1201 | "version": "1.6.0", 1202 | "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", 1203 | "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", 1204 | "requires": { 1205 | "currently-unhandled": "0.4.1", 1206 | "signal-exit": "3.0.2" 1207 | } 1208 | }, 1209 | "lru-cache": { 1210 | "version": "4.0.2", 1211 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", 1212 | "integrity": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", 1213 | "dev": true, 1214 | "requires": { 1215 | "pseudomap": "1.0.2", 1216 | "yallist": "2.1.2" 1217 | } 1218 | }, 1219 | "map-obj": { 1220 | "version": "1.0.1", 1221 | "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", 1222 | "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" 1223 | }, 1224 | "marked": { 1225 | "version": "0.3.6", 1226 | "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz", 1227 | "integrity": "sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc=" 1228 | }, 1229 | "meow": { 1230 | "version": "3.7.0", 1231 | "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", 1232 | "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", 1233 | "requires": { 1234 | "camelcase-keys": "2.1.0", 1235 | "decamelize": "1.2.0", 1236 | "loud-rejection": "1.6.0", 1237 | "map-obj": "1.0.1", 1238 | "minimist": "1.2.0", 1239 | "normalize-package-data": "2.3.8", 1240 | "object-assign": "4.1.1", 1241 | "read-pkg-up": "1.0.1", 1242 | "redent": "1.0.0", 1243 | "trim-newlines": "1.0.0" 1244 | }, 1245 | "dependencies": { 1246 | "minimist": { 1247 | "version": "1.2.0", 1248 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 1249 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 1250 | } 1251 | } 1252 | }, 1253 | "metaviewport-parser": { 1254 | "version": "0.0.1", 1255 | "resolved": "https://registry.npmjs.org/metaviewport-parser/-/metaviewport-parser-0.0.1.tgz", 1256 | "integrity": "sha1-mygXllm3b/nSHehK4lWDJXkJsgY=" 1257 | }, 1258 | "mime-db": { 1259 | "version": "1.27.0", 1260 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", 1261 | "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" 1262 | }, 1263 | "mime-types": { 1264 | "version": "2.1.15", 1265 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", 1266 | "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", 1267 | "requires": { 1268 | "mime-db": "1.27.0" 1269 | } 1270 | }, 1271 | "minimatch": { 1272 | "version": "3.0.4", 1273 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1274 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1275 | "requires": { 1276 | "brace-expansion": "1.1.7" 1277 | } 1278 | }, 1279 | "minimist": { 1280 | "version": "0.0.10", 1281 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", 1282 | "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" 1283 | }, 1284 | "mkdirp": { 1285 | "version": "0.5.1", 1286 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1287 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1288 | "requires": { 1289 | "minimist": "0.0.8" 1290 | }, 1291 | "dependencies": { 1292 | "minimist": { 1293 | "version": "0.0.8", 1294 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1295 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 1296 | } 1297 | } 1298 | }, 1299 | "ms": { 1300 | "version": "0.7.1", 1301 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 1302 | "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" 1303 | }, 1304 | "node-localstorage": { 1305 | "version": "1.3.0", 1306 | "resolved": "https://registry.npmjs.org/node-localstorage/-/node-localstorage-1.3.0.tgz", 1307 | "integrity": "sha1-LkNqro3Mms6XtDxlwWwNV3vgpVw=", 1308 | "requires": { 1309 | "write-file-atomic": "1.3.4" 1310 | } 1311 | }, 1312 | "normalize-package-data": { 1313 | "version": "2.3.8", 1314 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz", 1315 | "integrity": "sha1-2Bntoqne29H/pWPqQHHZNngilbs=", 1316 | "requires": { 1317 | "hosted-git-info": "2.4.2", 1318 | "is-builtin-module": "1.0.0", 1319 | "semver": "5.3.0", 1320 | "validate-npm-package-license": "3.0.1" 1321 | } 1322 | }, 1323 | "normalize-path": { 1324 | "version": "1.0.0", 1325 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", 1326 | "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", 1327 | "dev": true 1328 | }, 1329 | "npm-path": { 1330 | "version": "2.0.3", 1331 | "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.3.tgz", 1332 | "integrity": "sha1-Fc/04ciaONp39W9gVbJPl137K74=", 1333 | "dev": true, 1334 | "requires": { 1335 | "which": "1.2.14" 1336 | } 1337 | }, 1338 | "npm-run-path": { 1339 | "version": "2.0.2", 1340 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", 1341 | "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", 1342 | "dev": true, 1343 | "requires": { 1344 | "path-key": "2.0.1" 1345 | } 1346 | }, 1347 | "npm-which": { 1348 | "version": "3.0.1", 1349 | "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", 1350 | "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", 1351 | "dev": true, 1352 | "requires": { 1353 | "commander": "2.9.0", 1354 | "npm-path": "2.0.3", 1355 | "which": "1.2.14" 1356 | } 1357 | }, 1358 | "number-is-nan": { 1359 | "version": "1.0.1", 1360 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 1361 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" 1362 | }, 1363 | "oauth-sign": { 1364 | "version": "0.8.2", 1365 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", 1366 | "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" 1367 | }, 1368 | "object-assign": { 1369 | "version": "4.1.1", 1370 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1371 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 1372 | }, 1373 | "once": { 1374 | "version": "1.4.0", 1375 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1376 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1377 | "requires": { 1378 | "wrappy": "1.0.2" 1379 | } 1380 | }, 1381 | "onetime": { 1382 | "version": "1.1.0", 1383 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", 1384 | "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", 1385 | "dev": true 1386 | }, 1387 | "opn": { 1388 | "version": "4.0.2", 1389 | "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", 1390 | "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", 1391 | "requires": { 1392 | "object-assign": "4.1.1", 1393 | "pinkie-promise": "2.0.1" 1394 | } 1395 | }, 1396 | "optimist": { 1397 | "version": "0.6.1", 1398 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 1399 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 1400 | "requires": { 1401 | "minimist": "0.0.10", 1402 | "wordwrap": "0.0.3" 1403 | } 1404 | }, 1405 | "options": { 1406 | "version": "0.0.6", 1407 | "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", 1408 | "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" 1409 | }, 1410 | "ora": { 1411 | "version": "0.2.3", 1412 | "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", 1413 | "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", 1414 | "dev": true, 1415 | "requires": { 1416 | "chalk": "1.1.3", 1417 | "cli-cursor": "1.0.2", 1418 | "cli-spinners": "0.1.2", 1419 | "object-assign": "4.1.1" 1420 | } 1421 | }, 1422 | "os-homedir": { 1423 | "version": "1.0.2", 1424 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", 1425 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", 1426 | "dev": true 1427 | }, 1428 | "os-locale": { 1429 | "version": "1.4.0", 1430 | "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", 1431 | "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", 1432 | "requires": { 1433 | "lcid": "1.0.0" 1434 | } 1435 | }, 1436 | "os-tmpdir": { 1437 | "version": "1.0.2", 1438 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1439 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 1440 | }, 1441 | "p-finally": { 1442 | "version": "1.0.0", 1443 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 1444 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", 1445 | "dev": true 1446 | }, 1447 | "p-limit": { 1448 | "version": "1.1.0", 1449 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", 1450 | "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=" 1451 | }, 1452 | "p-locate": { 1453 | "version": "2.0.0", 1454 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", 1455 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", 1456 | "requires": { 1457 | "p-limit": "1.1.0" 1458 | } 1459 | }, 1460 | "parse-json": { 1461 | "version": "2.2.0", 1462 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", 1463 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", 1464 | "requires": { 1465 | "error-ex": "1.3.1" 1466 | } 1467 | }, 1468 | "path-exists": { 1469 | "version": "2.1.0", 1470 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", 1471 | "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", 1472 | "requires": { 1473 | "pinkie-promise": "2.0.1" 1474 | } 1475 | }, 1476 | "path-is-absolute": { 1477 | "version": "1.0.1", 1478 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1479 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 1480 | }, 1481 | "path-is-inside": { 1482 | "version": "1.0.2", 1483 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 1484 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" 1485 | }, 1486 | "path-key": { 1487 | "version": "2.0.1", 1488 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 1489 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", 1490 | "dev": true 1491 | }, 1492 | "path-type": { 1493 | "version": "1.1.0", 1494 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", 1495 | "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", 1496 | "requires": { 1497 | "graceful-fs": "4.1.11", 1498 | "pify": "2.3.0", 1499 | "pinkie-promise": "2.0.1" 1500 | } 1501 | }, 1502 | "pend": { 1503 | "version": "1.2.0", 1504 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 1505 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" 1506 | }, 1507 | "performance-now": { 1508 | "version": "0.2.0", 1509 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", 1510 | "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" 1511 | }, 1512 | "pify": { 1513 | "version": "2.3.0", 1514 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1515 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" 1516 | }, 1517 | "pinkie": { 1518 | "version": "2.0.4", 1519 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 1520 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" 1521 | }, 1522 | "pinkie-promise": { 1523 | "version": "2.0.1", 1524 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 1525 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 1526 | "requires": { 1527 | "pinkie": "2.0.4" 1528 | } 1529 | }, 1530 | "pkg-dir": { 1531 | "version": "2.0.0", 1532 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", 1533 | "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", 1534 | "requires": { 1535 | "find-up": "2.1.0" 1536 | }, 1537 | "dependencies": { 1538 | "find-up": { 1539 | "version": "2.1.0", 1540 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", 1541 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", 1542 | "requires": { 1543 | "locate-path": "2.0.0" 1544 | } 1545 | } 1546 | } 1547 | }, 1548 | "prettier": { 1549 | "version": "1.2.2", 1550 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.2.2.tgz", 1551 | "integrity": "sha1-ItF8ETL6quofHU+uox8Z96GVnz4=", 1552 | "dev": true, 1553 | "requires": { 1554 | "ast-types": "0.9.8", 1555 | "babel-code-frame": "6.22.0", 1556 | "babylon": "7.0.0-beta.8", 1557 | "chalk": "1.1.3", 1558 | "esutils": "2.0.2", 1559 | "flow-parser": "0.43.0", 1560 | "get-stdin": "5.0.1", 1561 | "glob": "7.1.1", 1562 | "jest-validate": "19.0.0", 1563 | "minimist": "1.2.0" 1564 | }, 1565 | "dependencies": { 1566 | "get-stdin": { 1567 | "version": "5.0.1", 1568 | "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", 1569 | "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", 1570 | "dev": true 1571 | }, 1572 | "minimist": { 1573 | "version": "1.2.0", 1574 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 1575 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", 1576 | "dev": true 1577 | } 1578 | } 1579 | }, 1580 | "pretty-format": { 1581 | "version": "19.0.0", 1582 | "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-19.0.0.tgz", 1583 | "integrity": "sha1-VlMNMqy5ij+khRxOK503tCBoTIQ=", 1584 | "dev": true, 1585 | "requires": { 1586 | "ansi-styles": "3.0.0" 1587 | }, 1588 | "dependencies": { 1589 | "ansi-styles": { 1590 | "version": "3.0.0", 1591 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.0.0.tgz", 1592 | "integrity": "sha1-VATpOlRMT+x/BIJil3vr/jFV4ME=", 1593 | "dev": true, 1594 | "requires": { 1595 | "color-convert": "1.9.0" 1596 | } 1597 | } 1598 | } 1599 | }, 1600 | "prettycli": { 1601 | "version": "1.3.0", 1602 | "resolved": "https://registry.npmjs.org/prettycli/-/prettycli-1.3.0.tgz", 1603 | "integrity": "sha1-HGoFAYBkxN+23RMyQ1/WcV5JsnM=", 1604 | "requires": { 1605 | "chalk": "1.1.3" 1606 | } 1607 | }, 1608 | "pseudomap": { 1609 | "version": "1.0.2", 1610 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 1611 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", 1612 | "dev": true 1613 | }, 1614 | "punycode": { 1615 | "version": "1.4.1", 1616 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1617 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 1618 | }, 1619 | "qs": { 1620 | "version": "6.4.0", 1621 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", 1622 | "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" 1623 | }, 1624 | "read-pkg": { 1625 | "version": "1.1.0", 1626 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", 1627 | "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", 1628 | "requires": { 1629 | "load-json-file": "1.1.0", 1630 | "normalize-package-data": "2.3.8", 1631 | "path-type": "1.1.0" 1632 | } 1633 | }, 1634 | "read-pkg-up": { 1635 | "version": "1.0.1", 1636 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", 1637 | "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", 1638 | "requires": { 1639 | "find-up": "1.1.2", 1640 | "read-pkg": "1.1.0" 1641 | } 1642 | }, 1643 | "redent": { 1644 | "version": "1.0.0", 1645 | "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", 1646 | "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", 1647 | "requires": { 1648 | "indent-string": "2.1.0", 1649 | "strip-indent": "1.0.1" 1650 | } 1651 | }, 1652 | "repeating": { 1653 | "version": "2.0.1", 1654 | "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", 1655 | "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", 1656 | "requires": { 1657 | "is-finite": "1.0.2" 1658 | } 1659 | }, 1660 | "request": { 1661 | "version": "2.81.0", 1662 | "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", 1663 | "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", 1664 | "requires": { 1665 | "aws-sign2": "0.6.0", 1666 | "aws4": "1.6.0", 1667 | "caseless": "0.12.0", 1668 | "combined-stream": "1.0.5", 1669 | "extend": "3.0.1", 1670 | "forever-agent": "0.6.1", 1671 | "form-data": "2.1.4", 1672 | "har-validator": "4.2.1", 1673 | "hawk": "3.1.3", 1674 | "http-signature": "1.1.1", 1675 | "is-typedarray": "1.0.0", 1676 | "isstream": "0.1.2", 1677 | "json-stringify-safe": "5.0.1", 1678 | "mime-types": "2.1.15", 1679 | "oauth-sign": "0.8.2", 1680 | "performance-now": "0.2.0", 1681 | "qs": "6.4.0", 1682 | "safe-buffer": "5.0.1", 1683 | "stringstream": "0.0.5", 1684 | "tough-cookie": "2.3.2", 1685 | "tunnel-agent": "0.6.0", 1686 | "uuid": "3.0.1" 1687 | } 1688 | }, 1689 | "require-from-string": { 1690 | "version": "1.2.1", 1691 | "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", 1692 | "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", 1693 | "dev": true 1694 | }, 1695 | "resolve": { 1696 | "version": "1.1.7", 1697 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", 1698 | "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" 1699 | }, 1700 | "restore-cursor": { 1701 | "version": "1.0.1", 1702 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", 1703 | "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", 1704 | "dev": true, 1705 | "requires": { 1706 | "exit-hook": "1.1.1", 1707 | "onetime": "1.1.0" 1708 | } 1709 | }, 1710 | "rimraf": { 1711 | "version": "2.2.8", 1712 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", 1713 | "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" 1714 | }, 1715 | "rxjs": { 1716 | "version": "5.3.1", 1717 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.3.1.tgz", 1718 | "integrity": "sha1-nsyeciJH5PRJDTCoeFd6N0D9DLc=", 1719 | "dev": true, 1720 | "requires": { 1721 | "symbol-observable": "1.0.4" 1722 | } 1723 | }, 1724 | "safe-buffer": { 1725 | "version": "5.0.1", 1726 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", 1727 | "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" 1728 | }, 1729 | "sauce-connect-launcher": { 1730 | "version": "1.2.2", 1731 | "resolved": "https://registry.npmjs.org/sauce-connect-launcher/-/sauce-connect-launcher-1.2.2.tgz", 1732 | "integrity": "sha1-c0bMj73EQxkTI0ObBzNFH181IfI=", 1733 | "requires": { 1734 | "adm-zip": "0.4.7", 1735 | "async": "2.4.0", 1736 | "https-proxy-agent": "1.0.0", 1737 | "lodash": "4.17.4", 1738 | "rimraf": "2.6.1" 1739 | }, 1740 | "dependencies": { 1741 | "async": { 1742 | "version": "2.4.0", 1743 | "resolved": "https://registry.npmjs.org/async/-/async-2.4.0.tgz", 1744 | "integrity": "sha1-SZAgDxjqW4N8LMT4wDGmmFw4VhE=", 1745 | "requires": { 1746 | "lodash": "4.17.4" 1747 | } 1748 | }, 1749 | "lodash": { 1750 | "version": "4.17.4", 1751 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 1752 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" 1753 | }, 1754 | "rimraf": { 1755 | "version": "2.6.1", 1756 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", 1757 | "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", 1758 | "requires": { 1759 | "glob": "7.1.1" 1760 | } 1761 | } 1762 | } 1763 | }, 1764 | "sax": { 1765 | "version": "1.2.2", 1766 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.2.tgz", 1767 | "integrity": "sha1-/YYxojvHgmvvXYcb24c3jJVkeCg=" 1768 | }, 1769 | "selenium-assistant": { 1770 | "version": "5.0.5", 1771 | "resolved": "https://registry.npmjs.org/selenium-assistant/-/selenium-assistant-5.0.5.tgz", 1772 | "integrity": "sha1-Gwg5pd+Upz9VJZTobmXrW6+esp0=", 1773 | "requires": { 1774 | "chalk": "1.1.3", 1775 | "del": "2.2.2", 1776 | "dmg": "0.1.0", 1777 | "fs-extra": "2.1.2", 1778 | "mkdirp": "0.5.1", 1779 | "node-localstorage": "1.3.0", 1780 | "request": "2.81.0", 1781 | "sauce-connect-launcher": "1.2.2", 1782 | "selenium-webdriver": "3.4.0", 1783 | "semver": "5.3.0", 1784 | "which": "1.2.14", 1785 | "yauzl": "2.8.0" 1786 | } 1787 | }, 1788 | "selenium-webdriver": { 1789 | "version": "3.4.0", 1790 | "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.4.0.tgz", 1791 | "integrity": "sha1-FR90RSlNpqZsScwwB0eioX5TxSo=", 1792 | "requires": { 1793 | "adm-zip": "0.4.7", 1794 | "rimraf": "2.6.1", 1795 | "tmp": "0.0.30", 1796 | "xml2js": "0.4.17" 1797 | }, 1798 | "dependencies": { 1799 | "rimraf": { 1800 | "version": "2.6.1", 1801 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", 1802 | "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", 1803 | "requires": { 1804 | "glob": "7.1.1" 1805 | } 1806 | } 1807 | } 1808 | }, 1809 | "semver": { 1810 | "version": "5.3.0", 1811 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", 1812 | "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" 1813 | }, 1814 | "shebang-command": { 1815 | "version": "1.2.0", 1816 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1817 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1818 | "dev": true, 1819 | "requires": { 1820 | "shebang-regex": "1.0.0" 1821 | } 1822 | }, 1823 | "shebang-regex": { 1824 | "version": "1.0.0", 1825 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1826 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 1827 | "dev": true 1828 | }, 1829 | "signal-exit": { 1830 | "version": "3.0.2", 1831 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1832 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 1833 | }, 1834 | "slice-ansi": { 1835 | "version": "0.0.4", 1836 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", 1837 | "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", 1838 | "dev": true 1839 | }, 1840 | "slide": { 1841 | "version": "1.1.6", 1842 | "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", 1843 | "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" 1844 | }, 1845 | "sntp": { 1846 | "version": "1.0.9", 1847 | "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", 1848 | "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", 1849 | "requires": { 1850 | "hoek": "2.16.3" 1851 | } 1852 | }, 1853 | "source-map": { 1854 | "version": "0.4.4", 1855 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", 1856 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", 1857 | "requires": { 1858 | "amdefine": "1.0.1" 1859 | } 1860 | }, 1861 | "spdx-correct": { 1862 | "version": "1.0.2", 1863 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", 1864 | "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", 1865 | "requires": { 1866 | "spdx-license-ids": "1.2.2" 1867 | } 1868 | }, 1869 | "spdx-expression-parse": { 1870 | "version": "1.0.4", 1871 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", 1872 | "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" 1873 | }, 1874 | "spdx-license-ids": { 1875 | "version": "1.2.2", 1876 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", 1877 | "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" 1878 | }, 1879 | "speedline": { 1880 | "version": "1.0.3", 1881 | "resolved": "https://registry.npmjs.org/speedline/-/speedline-1.0.3.tgz", 1882 | "integrity": "sha1-7h2YwY1YOi2EiKre0tuTNLlD270=", 1883 | "requires": { 1884 | "babar": "0.0.3", 1885 | "image-ssim": "0.2.0", 1886 | "jpeg-js": "0.1.2", 1887 | "loud-rejection": "1.6.0", 1888 | "meow": "3.7.0" 1889 | } 1890 | }, 1891 | "sprintf-js": { 1892 | "version": "1.0.3", 1893 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1894 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 1895 | }, 1896 | "sshpk": { 1897 | "version": "1.13.0", 1898 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.0.tgz", 1899 | "integrity": "sha1-/yo+T9BEl1Vf7Zezmg/YL6+zozw=", 1900 | "requires": { 1901 | "asn1": "0.2.3", 1902 | "assert-plus": "1.0.0", 1903 | "bcrypt-pbkdf": "1.0.1", 1904 | "dashdash": "1.14.1", 1905 | "ecc-jsbn": "0.1.1", 1906 | "getpass": "0.1.7", 1907 | "jodid25519": "1.0.2", 1908 | "jsbn": "0.1.1", 1909 | "tweetnacl": "0.14.5" 1910 | }, 1911 | "dependencies": { 1912 | "assert-plus": { 1913 | "version": "1.0.0", 1914 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 1915 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 1916 | } 1917 | } 1918 | }, 1919 | "staged-git-files": { 1920 | "version": "0.0.4", 1921 | "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-0.0.4.tgz", 1922 | "integrity": "sha1-15fhtVHKemOd7AI33G60u5vhfTU=", 1923 | "dev": true 1924 | }, 1925 | "statistics": { 1926 | "version": "3.3.0", 1927 | "resolved": "https://registry.npmjs.org/statistics/-/statistics-3.3.0.tgz", 1928 | "integrity": "sha1-7HtHUP8DqySmTdmzV6eDFr6teKo=" 1929 | }, 1930 | "stream-to-observable": { 1931 | "version": "0.1.0", 1932 | "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.1.0.tgz", 1933 | "integrity": "sha1-Rb8dny19wJvtgfHDB8Qw5ouEz/4=", 1934 | "dev": true 1935 | }, 1936 | "string-width": { 1937 | "version": "1.0.2", 1938 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 1939 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 1940 | "requires": { 1941 | "code-point-at": "1.1.0", 1942 | "is-fullwidth-code-point": "1.0.0", 1943 | "strip-ansi": "3.0.1" 1944 | } 1945 | }, 1946 | "stringstream": { 1947 | "version": "0.0.5", 1948 | "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", 1949 | "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" 1950 | }, 1951 | "strip-ansi": { 1952 | "version": "3.0.1", 1953 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1954 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1955 | "requires": { 1956 | "ansi-regex": "2.1.1" 1957 | } 1958 | }, 1959 | "strip-bom": { 1960 | "version": "2.0.0", 1961 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", 1962 | "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", 1963 | "requires": { 1964 | "is-utf8": "0.2.1" 1965 | } 1966 | }, 1967 | "strip-eof": { 1968 | "version": "1.0.0", 1969 | "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", 1970 | "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", 1971 | "dev": true 1972 | }, 1973 | "strip-indent": { 1974 | "version": "1.0.1", 1975 | "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", 1976 | "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", 1977 | "requires": { 1978 | "get-stdin": "4.0.1" 1979 | } 1980 | }, 1981 | "supports-color": { 1982 | "version": "2.0.0", 1983 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1984 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 1985 | }, 1986 | "symbol-observable": { 1987 | "version": "1.0.4", 1988 | "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", 1989 | "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=", 1990 | "dev": true 1991 | }, 1992 | "sync-exec": { 1993 | "version": "0.6.2", 1994 | "resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.6.2.tgz", 1995 | "integrity": "sha1-cX0izFPwzh3vVZQ2LzqJouu5EQU=" 1996 | }, 1997 | "tmp": { 1998 | "version": "0.0.30", 1999 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", 2000 | "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", 2001 | "requires": { 2002 | "os-tmpdir": "1.0.2" 2003 | } 2004 | }, 2005 | "tough-cookie": { 2006 | "version": "2.3.2", 2007 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", 2008 | "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", 2009 | "requires": { 2010 | "punycode": "1.4.1" 2011 | } 2012 | }, 2013 | "tr46": { 2014 | "version": "0.0.3", 2015 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 2016 | "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" 2017 | }, 2018 | "trim-newlines": { 2019 | "version": "1.0.0", 2020 | "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", 2021 | "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" 2022 | }, 2023 | "tunnel-agent": { 2024 | "version": "0.6.0", 2025 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 2026 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 2027 | "requires": { 2028 | "safe-buffer": "5.0.1" 2029 | } 2030 | }, 2031 | "tweetnacl": { 2032 | "version": "0.14.5", 2033 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 2034 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 2035 | "optional": true 2036 | }, 2037 | "uglify-js": { 2038 | "version": "2.8.27", 2039 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.27.tgz", 2040 | "integrity": "sha1-R3h/kSsPJC5bmENDvo416V9pTJw=", 2041 | "optional": true, 2042 | "requires": { 2043 | "source-map": "0.5.6", 2044 | "uglify-to-browserify": "1.0.2", 2045 | "yargs": "3.10.0" 2046 | }, 2047 | "dependencies": { 2048 | "source-map": { 2049 | "version": "0.5.6", 2050 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", 2051 | "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", 2052 | "optional": true 2053 | }, 2054 | "yargs": { 2055 | "version": "3.10.0", 2056 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", 2057 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", 2058 | "optional": true, 2059 | "requires": { 2060 | "decamelize": "1.2.0" 2061 | } 2062 | } 2063 | } 2064 | }, 2065 | "uglify-to-browserify": { 2066 | "version": "1.0.2", 2067 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", 2068 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", 2069 | "optional": true 2070 | }, 2071 | "ultron": { 2072 | "version": "1.0.2", 2073 | "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", 2074 | "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" 2075 | }, 2076 | "uuid": { 2077 | "version": "3.0.1", 2078 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", 2079 | "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=" 2080 | }, 2081 | "validate-npm-package-license": { 2082 | "version": "3.0.1", 2083 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", 2084 | "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", 2085 | "requires": { 2086 | "spdx-correct": "1.0.2", 2087 | "spdx-expression-parse": "1.0.4" 2088 | } 2089 | }, 2090 | "verror": { 2091 | "version": "1.3.6", 2092 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", 2093 | "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", 2094 | "requires": { 2095 | "extsprintf": "1.0.2" 2096 | } 2097 | }, 2098 | "webidl-conversions": { 2099 | "version": "3.0.1", 2100 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 2101 | "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" 2102 | }, 2103 | "whatwg-url": { 2104 | "version": "4.0.0", 2105 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-4.0.0.tgz", 2106 | "integrity": "sha1-W+Ni8Lbi+HYPcmDfbg4d9Tb1R5w=", 2107 | "requires": { 2108 | "tr46": "0.0.3", 2109 | "webidl-conversions": "3.0.1" 2110 | } 2111 | }, 2112 | "which": { 2113 | "version": "1.2.14", 2114 | "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", 2115 | "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", 2116 | "requires": { 2117 | "isexe": "2.0.0" 2118 | } 2119 | }, 2120 | "wordwrap": { 2121 | "version": "0.0.3", 2122 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 2123 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" 2124 | }, 2125 | "wrap-ansi": { 2126 | "version": "2.1.0", 2127 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", 2128 | "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", 2129 | "requires": { 2130 | "string-width": "1.0.2", 2131 | "strip-ansi": "3.0.1" 2132 | } 2133 | }, 2134 | "wrappy": { 2135 | "version": "1.0.2", 2136 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2137 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 2138 | }, 2139 | "write-file-atomic": { 2140 | "version": "1.3.4", 2141 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", 2142 | "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", 2143 | "requires": { 2144 | "graceful-fs": "4.1.11", 2145 | "imurmurhash": "0.1.4", 2146 | "slide": "1.1.6" 2147 | } 2148 | }, 2149 | "ws": { 2150 | "version": "1.1.1", 2151 | "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.1.tgz", 2152 | "integrity": "sha1-CC3bbGQehdS7RR8D1S8G6r2x8Bg=", 2153 | "requires": { 2154 | "options": "0.0.6", 2155 | "ultron": "1.0.2" 2156 | } 2157 | }, 2158 | "xml2js": { 2159 | "version": "0.4.17", 2160 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", 2161 | "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", 2162 | "requires": { 2163 | "sax": "1.2.2", 2164 | "xmlbuilder": "4.2.1" 2165 | } 2166 | }, 2167 | "xmlbuilder": { 2168 | "version": "4.2.1", 2169 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", 2170 | "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", 2171 | "requires": { 2172 | "lodash": "4.17.4" 2173 | }, 2174 | "dependencies": { 2175 | "lodash": { 2176 | "version": "4.17.4", 2177 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 2178 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" 2179 | } 2180 | } 2181 | }, 2182 | "y18n": { 2183 | "version": "3.2.1", 2184 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", 2185 | "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" 2186 | }, 2187 | "yallist": { 2188 | "version": "2.1.2", 2189 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 2190 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", 2191 | "dev": true 2192 | }, 2193 | "yargs": { 2194 | "version": "3.32.0", 2195 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", 2196 | "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", 2197 | "requires": { 2198 | "camelcase": "2.1.1", 2199 | "cliui": "3.2.0", 2200 | "decamelize": "1.2.0", 2201 | "os-locale": "1.4.0", 2202 | "string-width": "1.0.2", 2203 | "window-size": "0.1.4", 2204 | "y18n": "3.2.1" 2205 | }, 2206 | "dependencies": { 2207 | "camelcase": { 2208 | "version": "2.1.1", 2209 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", 2210 | "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" 2211 | }, 2212 | "cliui": { 2213 | "version": "3.2.0", 2214 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", 2215 | "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", 2216 | "requires": { 2217 | "string-width": "1.0.2", 2218 | "strip-ansi": "3.0.1", 2219 | "wrap-ansi": "2.1.0" 2220 | } 2221 | }, 2222 | "window-size": { 2223 | "version": "0.1.4", 2224 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", 2225 | "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" 2226 | } 2227 | } 2228 | }, 2229 | "yargs-parser": { 2230 | "version": "5.0.0", 2231 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", 2232 | "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", 2233 | "requires": { 2234 | "camelcase": "3.0.0" 2235 | }, 2236 | "dependencies": { 2237 | "camelcase": { 2238 | "version": "3.0.0", 2239 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", 2240 | "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" 2241 | } 2242 | } 2243 | }, 2244 | "yauzl": { 2245 | "version": "2.8.0", 2246 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz", 2247 | "integrity": "sha1-eUUK/yKyqcWkHvVOAtuQfM+/nuI=", 2248 | "requires": { 2249 | "buffer-crc32": "0.2.13", 2250 | "fd-slicer": "1.0.1" 2251 | } 2252 | } 2253 | } 2254 | } 2255 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "perfbench", 3 | "version": "1.8.1", 4 | "description": "Benchmark metrics for your web application", 5 | "main": "index.js", 6 | "bin": "index.js", 7 | "scripts": { 8 | "precommit": "lint-staged", 9 | "test": "test=true node index" 10 | }, 11 | "engines": { 12 | "node": "8.x.x" 13 | }, 14 | "keywords": [ 15 | "benchmark", 16 | "application", 17 | "metrics" 18 | ], 19 | "repository": "siddharthkp/perfbench", 20 | "files": [ 21 | "index.js", 22 | "src" 23 | ], 24 | "author": "siddharthkp", 25 | "license": "MIT", 26 | "dependencies": { 27 | "ci-env": "1.4.0", 28 | "cli-table2": "0.2.0", 29 | "colors": "1.1.2", 30 | "github-build": "1.2.0", 31 | "js-yaml": "3.8.4", 32 | "lighthouse": "1.6.3", 33 | "lodash.kebabcase": "4.1.1", 34 | "lodash.startcase": "4.4.0", 35 | "pkg-dir": "2.0.0", 36 | "prettycli": "1.3.0", 37 | "selenium-assistant": "5.0.5", 38 | "statistics": "3.3.0", 39 | "sync-exec": "0.6.2", 40 | "yargs-parser": "5.0.0" 41 | }, 42 | "devDependencies": { 43 | "husky": "0.13.3", 44 | "lint-staged": "3.4.0", 45 | "prettier": "1.2.2" 46 | }, 47 | "lint-staged": { 48 | "*.js": [ 49 | "prettier --write --no-semi --single-quote", 50 | "git add" 51 | ] 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/api.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios') 2 | const { repo, sha } = require('ci-env') 3 | const token = require('./token') 4 | const url = 'https://perfbench-store.now.sh/values' 5 | 6 | let enabled = false 7 | let values = {} 8 | 9 | if (repo && token) { 10 | enabled = true 11 | axios 12 | .get(`${url}?repo=${repo}&token=${token}`) 13 | .then(response => (values = response.data)) 14 | .catch(error => console.log(error)) 15 | } 16 | 17 | const get = () => values 18 | 19 | const set = values => { 20 | if (repo && token) { 21 | axios 22 | .post(url, { repo, token, sha, values }) 23 | .catch(error => console.log(error)) 24 | } 25 | } 26 | 27 | const store = { enabled, set, get } 28 | module.exports = store 29 | -------------------------------------------------------------------------------- /src/build.js: -------------------------------------------------------------------------------- 1 | const Build = require('github-build') 2 | const startcase = require('lodash.startcase') 3 | const { repo, sha, event } = require('ci-env') 4 | 5 | const { thresholds } = require('./settings') 6 | const { units } = require('./properties') 7 | const token = require('./token') 8 | const store = require('./api') 9 | 10 | const label = 'perfbench' 11 | const description = 'Running performance tests...' 12 | const meta = { repo, sha, token, label, description } 13 | 14 | const build = new Build(meta) 15 | 16 | let pass = () => {} // noop 17 | let fail = () => process.exit(1) 18 | let error = () => process.exit(1) 19 | 20 | if (token) { 21 | build.start() 22 | 23 | pass = (values, url) => { 24 | /* default message */ 25 | let message = 'Good Job! Performance checks passed!' 26 | 27 | if (store.enabled) { 28 | const master = store.get() 29 | /* If master values are empty, send default message */ 30 | if (!Object.keys(master).length) build.pass(message) 31 | 32 | const keys = ['time-to-interactive', 'first-meaningful-paint'] 33 | let properties = [] 34 | let increased = false 35 | 36 | for (let key of keys) { 37 | if (values[key] > parseFloat(master[key])) { 38 | increased = key 39 | break 40 | } 41 | } 42 | 43 | /* If it did not increase, must have improved */ 44 | const key = increased || keys[0] 45 | const starter = increased ? 'Warning:' : 'Good job!' 46 | const verb = increased ? 'increased' : 'improved' 47 | const difference = Math.round(Math.abs(values[key] - master[key])) 48 | 49 | /* 50 | Show diff in build if it is at least 100ms, 51 | anything below that is not reliable 52 | */ 53 | if (difference >= 100) { 54 | message = `${starter} ${startcase(key)} has ${verb} by ${difference} ${units(key)}` 55 | } 56 | } 57 | 58 | build.pass(message, url) 59 | } 60 | 61 | fail = (values, unreliableResults, url) => { 62 | let properties = [] 63 | let message 64 | 65 | const keys = Object.keys(values) 66 | for (key of keys) { 67 | if (values[key] > thresholds[key]) properties.push(key) 68 | } 69 | 70 | if (properties.length === 1) { 71 | const key = properties[0] 72 | message = `${startcase(key)} is above threshold (${values[key]} > ${thresholds[key]})` 73 | } else { 74 | message = `${properties 75 | .map(p => startcase(p)) 76 | .join(', ') 77 | .replace(/,([^,]*)$/, ' and$1')} are above threshold` 78 | } 79 | 80 | if (unreliableResults.length) { 81 | message = `Results for ${unreliableResults.join(', ')} are not reliable due to high variations` 82 | } 83 | 84 | build.fail(message, url) 85 | } 86 | 87 | error = () => { 88 | build.error('Tests errored out! Check build logs for errors') 89 | } 90 | } 91 | 92 | module.exports = { pass, fail, error } 93 | -------------------------------------------------------------------------------- /src/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "passes": [{ 3 | "recordNetwork": true, 4 | "recordTrace": true, 5 | "pauseBeforeTraceEndMs": 500, 6 | "useThrottling": true, 7 | "gatherers": [ 8 | "url", 9 | "content-width" 10 | ] 11 | }], 12 | 13 | "audits": [ 14 | "first-meaningful-paint", 15 | "speed-index-metric", 16 | "time-to-interactive", 17 | "byte-efficiency/total-byte-weight", 18 | "user-timings" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/lighthouse.js: -------------------------------------------------------------------------------- 1 | const syncExec = require('sync-exec') 2 | 3 | const flags = { disableCpuThrottling: false } 4 | 5 | let configPath = './node_modules/perfbench/src/config.json' 6 | if (process.env.test) configPath = './src/config.json' 7 | 8 | const run = url => 9 | new Promise((resolve, reject) => { 10 | const command = [ 11 | './node_modules/.bin/lighthouse', 12 | url, 13 | '--output=json', 14 | '--disable-cpu-throttling=false', 15 | '--config-path=' + configPath 16 | ].join(' ') 17 | 18 | const output = syncExec(command) 19 | 20 | if (output.stderr) reject(output.stderr) 21 | else resolve(JSON.parse(output.stdout)) 22 | }) 23 | 24 | module.exports = { run } 25 | -------------------------------------------------------------------------------- /src/properties.js: -------------------------------------------------------------------------------- 1 | const optimalValues = { 2 | 'first-meaningful-paint': 1600, 3 | 'speed-index-metric': 1250, 4 | 'time-to-interactive': 2500, 5 | 'total-byte-weight': 1600 6 | } 7 | 8 | const units = property => { 9 | return ( 10 | { 11 | 'first-meaningful-paint': 'ms', 12 | 'speed-index-metric': ' ', 13 | 'time-to-interactive': 'ms', 14 | 'total-byte-weight': 'Kb' 15 | }[property] || 'ms' 16 | ) 17 | } 18 | 19 | module.exports = { optimalValues, units } 20 | -------------------------------------------------------------------------------- /src/reporter.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const Table = require('cli-table2') 3 | const { white, yellow, green, red } = require('colors/safe') 4 | const statistics = require('statistics') 5 | const kebabcase = require('lodash.kebabcase') 6 | const { repo, branch, commit_message, sha } = require('ci-env') 7 | 8 | const build = require('./build') 9 | const { units } = require('./properties') 10 | let { debug, fail, thresholds } = require('./settings') 11 | const store = require('./api') 12 | 13 | /* Table headers */ 14 | let head = [white('Property'), white('Values'), white('Threshold')] 15 | let table = new Table({ head }) 16 | 17 | let error = false 18 | let averageValues = {} 19 | let unreliableResults = [] 20 | let master = {} 21 | 22 | const print = results => { 23 | if (debug) fs.writeFileSync('./debug.json', JSON.stringify(results, null, 2)) 24 | 25 | /* 26 | If store is enabled 27 | 1. fetch values from api 28 | 2. add column in table header 29 | */ 30 | if (store.enabled) { 31 | table.options.head.splice(2, 0, white('Master')) 32 | master = store.get() 33 | } 34 | 35 | /* Print the test conditions */ 36 | console.log('Test conditions: \n') 37 | const conditions = results[0].runtimeConfig.environment 38 | for (let { enabled, name, description } of conditions) { 39 | if (enabled) console.log(yellow(name), yellow(description)) 40 | } 41 | 42 | /* Flatten user timings results */ 43 | for (let i = 0; i < results.length; i++) { 44 | results[i].audits['user-timings'].extendedInfo.value.map( 45 | audit => 46 | (results[i].audits[kebabcase(audit.name)] = { 47 | description: audit.name, 48 | rawValue: audit.startTime 49 | }) 50 | ) 51 | delete results[i].audits['user-timings'] 52 | } 53 | 54 | /* Get all the audit keys */ 55 | const keys = Object.keys(results[0].audits) 56 | 57 | for (let key of keys) { 58 | const property = results[0].audits[key].description 59 | const threshold = thresholds[key] || 0 60 | 61 | let values = [] 62 | for (let i = 0; i < results.length; i++) { 63 | values.push(results[i].audits[key].rawValue) 64 | } 65 | 66 | if (debug) console.log(property, threshold, values) 67 | 68 | let { sum, stdev } = values.reduce(statistics) 69 | 70 | if (key === 'total-byte-weight') { 71 | sum = sum / 1024 72 | stdev = stdev / 1024 73 | } 74 | 75 | /* Take average of all values */ 76 | let numberOfDecimals = 2 77 | if (key === 'speed-index-metric') numberOfDecimals = 0 78 | 79 | const average = (sum / results.length).toFixed(numberOfDecimals) 80 | 81 | let color 82 | if (average < threshold) color = green 83 | else { 84 | color = red 85 | error = true 86 | } 87 | 88 | const row = [ 89 | color(property), 90 | color(average + ' ' + units(key)), 91 | color(threshold + ' ' + units(key)) 92 | ] 93 | if (store.enabled) { 94 | let value = '' 95 | if (master[key]) value = master[key] + ' ' + units(key) 96 | row.splice(2, 0, color(value)) 97 | } 98 | 99 | averageValues[key] = average 100 | table.push(row) 101 | 102 | /* if average crosses threshold by standard deviation, throw a warning */ 103 | if (average > threshold && average - stdev < threshold) 104 | unreliableResults.push(`${property}: ± ${stdev.toFixed(2)} ${units(key)}`) 105 | } 106 | 107 | console.log(table.toString()) 108 | console.log() 109 | 110 | /* warnings for unreliable results due to variation */ 111 | if (unreliableResults.length) { 112 | console.log( 113 | yellow('The following results are not reliable due to high variations:') 114 | ) 115 | console.log() 116 | console.log(unreliableResults.join('\n')) 117 | console.log() 118 | } 119 | 120 | if (branch === 'master') store.set(averageValues) 121 | 122 | /* prepare details page url */ 123 | const params = encodeURIComponent( 124 | JSON.stringify({ 125 | averageValues, 126 | master, 127 | thresholds, 128 | repo, 129 | branch, 130 | commit_message, 131 | sha 132 | }) 133 | ) 134 | const url = `https://perfbench-store.now.sh/build?info=${params}` 135 | 136 | /* error build if average > threshold */ 137 | if (error && fail) build.fail(averageValues, unreliableResults, url) 138 | else build.pass(averageValues, url) 139 | } 140 | 141 | module.exports = { print } 142 | -------------------------------------------------------------------------------- /src/settings.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const argv = require('yargs-parser')(process.argv.slice(2)) 3 | const pkgDir = require('pkg-dir') 4 | const { resolve } = require('path') 5 | const { error } = require('prettycli') 6 | const yaml = require('js-yaml') 7 | const { optimalValues } = require('./properties') 8 | 9 | let settings = {} 10 | const properties = ['runs', 'fail', 'url', 'debug', 'thresholds'] 11 | 12 | /* 13 | There are 3 layers of settings. 14 | 15 | In increasing order of priority: 16 | 1. defaults 17 | 2. config file 18 | 3. cli params 19 | */ 20 | 21 | const defaults = { 22 | runs: 3, 23 | fail: true, 24 | debug: false, 25 | thresholds: {}, 26 | event: 'push' 27 | } 28 | let fileSettings = {} 29 | let cliParams = {} 30 | 31 | const root = pkgDir.sync() 32 | const configPath = resolve(root, '.perf.yml') 33 | const configFileExists = fs.existsSync(configPath) 34 | 35 | /* file */ 36 | if (configFileExists) { 37 | try { 38 | fileSettings = yaml.safeLoad(fs.readFileSync(configPath)) 39 | } catch ({ message }) { 40 | error(message, { silent: true }) 41 | } 42 | } 43 | 44 | /* cli */ 45 | for (let property of properties) { 46 | if (argv[property]) cliParams[property] = argv[property] 47 | } 48 | if (process.argv[2]) cliParams.url = process.argv[2] 49 | 50 | Object.assign(settings, defaults, fileSettings, cliParams) 51 | 52 | /* validation */ 53 | for (let property of properties) { 54 | if (typeof settings[property] === 'undefined') 55 | error(`${property} is missing`, { silent: true }) 56 | } 57 | 58 | if (!Array.isArray(settings.thresholds)) settings.thresholds = [] 59 | 60 | /* Merge defaults and settings to get thresholds */ 61 | settings.thresholds = Object.assign({}, optimalValues, ...settings.thresholds) 62 | if (settings.debug) console.log('setting: ', settings) 63 | 64 | module.exports = settings 65 | -------------------------------------------------------------------------------- /src/setup.js: -------------------------------------------------------------------------------- 1 | const seleniumAssistant = require('selenium-assistant') 2 | const syncExec = require('sync-exec') 3 | const path = require('path') 4 | 5 | const setup = () => { 6 | process.env.DISPLAY = ':99.0' 7 | const output = syncExec('sh -e /etc/init.d/xvfb start') 8 | return seleniumAssistant.downloadLocalBrowser('chrome', 'stable') 9 | } 10 | 11 | module.exports = setup 12 | -------------------------------------------------------------------------------- /src/token.js: -------------------------------------------------------------------------------- 1 | const token = 2 | process.env.github_token || 3 | process.env.GITHUB_TOKEN || 4 | process.env.perfbench_github_token || 5 | process.env.PERFBENCH_GITHUB_TOKEN 6 | 7 | module.exports = token 8 | -------------------------------------------------------------------------------- /store/.env.sample: -------------------------------------------------------------------------------- 1 | apiKey=firebase-api-key 2 | databaseURL=firebase-database-url 3 | githubId=github-client-id 4 | githubSecret=github-client-secret 5 | newrelicKey=newrelic-key 6 | -------------------------------------------------------------------------------- /store/dummy.js: -------------------------------------------------------------------------------- 1 | const params = { 2 | averageValues: { 3 | 'first-meaningful-paint': '955', 4 | 'time-to-interactive': '1251', 5 | 'speed-index-metric': '610', 6 | 'search-ready': '2700' 7 | }, 8 | master: { 9 | 'first-meaningful-paint': '955', 10 | 'speed-index-metric': '586', 11 | 'time-to-interactive': '610', 12 | 'search-ready': '2305' 13 | }, 14 | thresholds: { 15 | 'first-meaningful-paint': 1600, 16 | 'speed-index-metric': 1250, 17 | 'time-to-interactive': 1700, 18 | 'search-ready': '2500' 19 | }, 20 | repo: 'practo/medicine-info', 21 | branch: 'awesome-feature', 22 | commit_message: 'Add super awesome feature', 23 | sha: 'da87b46702da847ad80f18c04408cf931c318b2d' 24 | } 25 | 26 | const stuff = 27 | 'http://localhost:3001/build?info=' + 28 | encodeURIComponent(JSON.stringify(params)) 29 | console.log(stuff) 30 | -------------------------------------------------------------------------------- /store/firebase.js: -------------------------------------------------------------------------------- 1 | const firebase = require('firebase') 2 | 3 | if (process.env.dev) { 4 | require('dotenv').config() 5 | } 6 | 7 | const { apiKey, databaseURL } = process.env 8 | 9 | firebase.initializeApp({ apiKey, databaseURL }) 10 | 11 | const database = firebase.database() 12 | 13 | const authenticate = token => { 14 | const credential = firebase.auth.GithubAuthProvider.credential(token) 15 | return firebase 16 | .auth() 17 | .signInWithCredential(credential) 18 | .catch(error => console.log(error)) 19 | } 20 | 21 | const logout = () => firebase.auth().signOut() 22 | 23 | const set = (repo, sha, values, token) => { 24 | authenticate(token) 25 | const ref = `${token}/${repo}` 26 | values.sha = sha 27 | firebase.database().ref(ref).push(values) 28 | logout() 29 | } 30 | 31 | const get = (repo, token) => { 32 | authenticate(token) 33 | const ref = `${token}/${repo}` 34 | return firebase 35 | .database() 36 | .ref(ref) 37 | .limitToLast(1) 38 | .once('value') 39 | .then(snapshot => { 40 | return snapshot.val() || {} 41 | }) 42 | logout() 43 | } 44 | 45 | module.exports = { set, get } 46 | -------------------------------------------------------------------------------- /store/github.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios') 2 | 3 | if (process.env.dev) { 4 | require('dotenv').config() 5 | } 6 | 7 | const token = code => { 8 | return axios({ 9 | method: 'POST', 10 | url: 'https://github.com/login/oauth/access_token', 11 | 'Content-type': 'application/x-www-form-urlencoded', 12 | data: { 13 | code: code, 14 | client_id: process.env.githubId, 15 | client_secret: process.env.githubSecret 16 | } 17 | }) 18 | .then(response => response.data) 19 | .catch(response => response.response.status) 20 | } 21 | 22 | module.exports = { token } 23 | -------------------------------------------------------------------------------- /store/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const server = express() 3 | const lowercase = require('lodash.lowercase') 4 | const bodyParser = require('body-parser') 5 | const querystring = require('querystring') 6 | const { get, set } = require('./firebase') 7 | const github = require('./github') 8 | 9 | server.use(bodyParser.json()) 10 | server.set('view engine', 'pug') 11 | server.use(express.static('static')) 12 | 13 | server.get('/status', (req, res) => { 14 | res.status(200).end('OK') 15 | }) 16 | 17 | server.get('/values', (req, res) => { 18 | const { repo, token } = req.query 19 | if (!repo) res.status(400).end('repo missing') 20 | else if (!token) res.status(401).end('token missing') 21 | else { 22 | get(repo, token).then(response => { 23 | /* Firebase returns a list */ 24 | const values = Object.values(response)[0] 25 | res.end(JSON.stringify(values)) 26 | }) 27 | } 28 | }) 29 | 30 | server.post('/values', (req, res) => { 31 | const { repo, sha, values, token } = req.body 32 | if (!token) res.status(401).end('token missing') 33 | else { 34 | set(repo, sha, values, token) 35 | res.status(200).end() 36 | } 37 | }) 38 | 39 | server.get('/auth', (req, res) => { 40 | const { code } = req.query 41 | if (!code) res.status(400).end('code missing') 42 | else 43 | github 44 | .token(code) 45 | .then(response => { 46 | const token = querystring.parse(response).access_token 47 | res.render('auth', { token }) 48 | }) 49 | .catch(() => res.status(500).end('Oops')) 50 | }) 51 | 52 | server.get('/build', (req, res) => { 53 | let { info } = req.query 54 | info = JSON.parse(info) 55 | 56 | const data = { 57 | repo: info.repo, 58 | branch: info.branch, 59 | sha: info.sha.slice(0, 8), 60 | commit_message: info.commit_message || '', 61 | metrics: [] 62 | } 63 | 64 | const keys = Object.keys(info.averageValues) 65 | keys.map(key => { 66 | const name = lowercase(key) 67 | const value = info.averageValues[key] 68 | const threshold = info.thresholds[key] 69 | 70 | const values = { name, value, threshold } 71 | 72 | if (key != 'speed-index-metric') values.unit = 'ms' 73 | 74 | if (info.master && info.master[key]) { 75 | let diff = (value - info.master[key]).toFixed(0) 76 | if (diff >= 0) diff = `+${diff}` 77 | values.diff = diff 78 | } 79 | 80 | /* Logic to draw bars */ 81 | values.maxLength = Math.max(value, threshold) 82 | if (value < values.maxLength) { 83 | values.fillLength = value 84 | values.baseColor = '#EEE' 85 | } else { 86 | values.fillLength = threshold 87 | values.baseColor = '#FA5E7C' 88 | values.class = 'fail' 89 | } 90 | 91 | data.metrics.push(values) 92 | }) 93 | 94 | res.render('build', data) 95 | }) 96 | 97 | server.get('/', (req, res) => { 98 | res.redirect('/status') 99 | }) 100 | 101 | server.listen(3001) 102 | -------------------------------------------------------------------------------- /store/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "perfbench-store", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.3", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", 10 | "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", 11 | "requires": { 12 | "mime-types": "2.1.15", 13 | "negotiator": "0.6.1" 14 | } 15 | }, 16 | "acorn": { 17 | "version": "3.3.0", 18 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 19 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" 20 | }, 21 | "acorn-globals": { 22 | "version": "3.1.0", 23 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", 24 | "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", 25 | "requires": { 26 | "acorn": "4.0.13" 27 | }, 28 | "dependencies": { 29 | "acorn": { 30 | "version": "4.0.13", 31 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", 32 | "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" 33 | } 34 | } 35 | }, 36 | "align-text": { 37 | "version": "0.1.4", 38 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", 39 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", 40 | "requires": { 41 | "kind-of": "3.2.2", 42 | "longest": "1.0.1", 43 | "repeat-string": "1.6.1" 44 | } 45 | }, 46 | "amdefine": { 47 | "version": "1.0.1", 48 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 49 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" 50 | }, 51 | "array-flatten": { 52 | "version": "1.1.1", 53 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 54 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 55 | }, 56 | "asap": { 57 | "version": "2.0.5", 58 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz", 59 | "integrity": "sha1-UidltQw1EEkOUtfc/ghe+bqWlY8=" 60 | }, 61 | "axios": { 62 | "version": "0.16.1", 63 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.16.1.tgz", 64 | "integrity": "sha1-wLbSZgCEI4S49QnlcRHw0t+CI8o=", 65 | "requires": { 66 | "follow-redirects": "1.2.4" 67 | } 68 | }, 69 | "body-parser": { 70 | "version": "1.17.2", 71 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz", 72 | "integrity": "sha1-+IkqvI+eYn1Crtr7yma/WrmRBO4=", 73 | "requires": { 74 | "bytes": "2.4.0", 75 | "content-type": "1.0.2", 76 | "debug": "2.6.7", 77 | "depd": "1.1.0", 78 | "http-errors": "1.6.1", 79 | "iconv-lite": "0.4.15", 80 | "on-finished": "2.3.0", 81 | "qs": "6.4.0", 82 | "raw-body": "2.2.0", 83 | "type-is": "1.6.15" 84 | }, 85 | "dependencies": { 86 | "debug": { 87 | "version": "2.6.7", 88 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", 89 | "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", 90 | "requires": { 91 | "ms": "2.0.0" 92 | } 93 | }, 94 | "ms": { 95 | "version": "2.0.0", 96 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 97 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 98 | } 99 | } 100 | }, 101 | "bytes": { 102 | "version": "2.4.0", 103 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", 104 | "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" 105 | }, 106 | "camelcase": { 107 | "version": "1.2.1", 108 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", 109 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" 110 | }, 111 | "center-align": { 112 | "version": "0.1.3", 113 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", 114 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", 115 | "requires": { 116 | "align-text": "0.1.4", 117 | "lazy-cache": "1.0.4" 118 | } 119 | }, 120 | "character-parser": { 121 | "version": "2.2.0", 122 | "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", 123 | "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", 124 | "requires": { 125 | "is-regex": "1.0.4" 126 | } 127 | }, 128 | "clean-css": { 129 | "version": "3.4.26", 130 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.26.tgz", 131 | "integrity": "sha1-VTI7NE/zvO5oSi6sgck9+Ppz3us=", 132 | "requires": { 133 | "commander": "2.8.1", 134 | "source-map": "0.4.4" 135 | } 136 | }, 137 | "cliui": { 138 | "version": "2.1.0", 139 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", 140 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", 141 | "requires": { 142 | "center-align": "0.1.3", 143 | "right-align": "0.1.3", 144 | "wordwrap": "0.0.2" 145 | } 146 | }, 147 | "commander": { 148 | "version": "2.8.1", 149 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", 150 | "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", 151 | "requires": { 152 | "graceful-readlink": "1.0.1" 153 | } 154 | }, 155 | "constantinople": { 156 | "version": "3.1.0", 157 | "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.0.tgz", 158 | "integrity": "sha1-dWnKqKo/jVk11i4fqW+fcCzYHHk=", 159 | "requires": { 160 | "acorn": "3.3.0", 161 | "is-expression": "2.1.0" 162 | } 163 | }, 164 | "content-disposition": { 165 | "version": "0.5.2", 166 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 167 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 168 | }, 169 | "content-type": { 170 | "version": "1.0.2", 171 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", 172 | "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=" 173 | }, 174 | "cookie": { 175 | "version": "0.3.1", 176 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 177 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 178 | }, 179 | "cookie-signature": { 180 | "version": "1.0.6", 181 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 182 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 183 | }, 184 | "debug": { 185 | "version": "2.6.1", 186 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.1.tgz", 187 | "integrity": "sha1-eYVQkLosTjEVzH2HaUkdWPBJE1E=", 188 | "requires": { 189 | "ms": "0.7.2" 190 | } 191 | }, 192 | "decamelize": { 193 | "version": "1.2.0", 194 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 195 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 196 | }, 197 | "depd": { 198 | "version": "1.1.0", 199 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", 200 | "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=" 201 | }, 202 | "destroy": { 203 | "version": "1.0.4", 204 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 205 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 206 | }, 207 | "doctypes": { 208 | "version": "1.1.0", 209 | "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", 210 | "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=" 211 | }, 212 | "dotenv": { 213 | "version": "4.0.0", 214 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", 215 | "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=" 216 | }, 217 | "ee-first": { 218 | "version": "1.1.1", 219 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 220 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 221 | }, 222 | "encodeurl": { 223 | "version": "1.0.1", 224 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", 225 | "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" 226 | }, 227 | "escape-html": { 228 | "version": "1.0.3", 229 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 230 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 231 | }, 232 | "etag": { 233 | "version": "1.8.0", 234 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", 235 | "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE=" 236 | }, 237 | "express": { 238 | "version": "4.15.2", 239 | "resolved": "https://registry.npmjs.org/express/-/express-4.15.2.tgz", 240 | "integrity": "sha1-rxB/wUhQRFfy3Kmm8lcdcSm5ezU=", 241 | "requires": { 242 | "accepts": "1.3.3", 243 | "array-flatten": "1.1.1", 244 | "content-disposition": "0.5.2", 245 | "content-type": "1.0.2", 246 | "cookie": "0.3.1", 247 | "cookie-signature": "1.0.6", 248 | "debug": "2.6.1", 249 | "depd": "1.1.0", 250 | "encodeurl": "1.0.1", 251 | "escape-html": "1.0.3", 252 | "etag": "1.8.0", 253 | "finalhandler": "1.0.2", 254 | "fresh": "0.5.0", 255 | "merge-descriptors": "1.0.1", 256 | "methods": "1.1.2", 257 | "on-finished": "2.3.0", 258 | "parseurl": "1.3.1", 259 | "path-to-regexp": "0.1.7", 260 | "proxy-addr": "1.1.4", 261 | "qs": "6.4.0", 262 | "range-parser": "1.2.0", 263 | "send": "0.15.1", 264 | "serve-static": "1.12.1", 265 | "setprototypeof": "1.0.3", 266 | "statuses": "1.3.1", 267 | "type-is": "1.6.15", 268 | "utils-merge": "1.0.0", 269 | "vary": "1.1.1" 270 | } 271 | }, 272 | "finalhandler": { 273 | "version": "1.0.2", 274 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.2.tgz", 275 | "integrity": "sha1-0ONvnbxVfy3hRCPfYmGInp1gyTo=", 276 | "requires": { 277 | "debug": "2.6.4", 278 | "encodeurl": "1.0.1", 279 | "escape-html": "1.0.3", 280 | "on-finished": "2.3.0", 281 | "parseurl": "1.3.1", 282 | "statuses": "1.3.1", 283 | "unpipe": "1.0.0" 284 | }, 285 | "dependencies": { 286 | "debug": { 287 | "version": "2.6.4", 288 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.4.tgz", 289 | "integrity": "sha1-dYaps8OXQcAoKuM0RcTorHRzT+A=", 290 | "requires": { 291 | "ms": "0.7.3" 292 | } 293 | }, 294 | "ms": { 295 | "version": "0.7.3", 296 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.3.tgz", 297 | "integrity": "sha1-cIFVpeROM/X9D8U+gdDUCpG+H/8=" 298 | } 299 | } 300 | }, 301 | "firebase": { 302 | "version": "4.1.2", 303 | "resolved": "https://registry.npmjs.org/firebase/-/firebase-4.1.2.tgz", 304 | "integrity": "sha1-shOrIp62XjG9vR0mIFmxux7frB8=", 305 | "requires": { 306 | "dom-storage": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.0.2.tgz", 307 | "faye-websocket": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.3.tgz", 308 | "jsonwebtoken": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.1.tgz", 309 | "promise-polyfill": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-6.0.2.tgz", 310 | "xmlhttprequest": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz" 311 | }, 312 | "dependencies": { 313 | "base64url": { 314 | "version": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", 315 | "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" 316 | }, 317 | "buffer-equal-constant-time": { 318 | "version": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 319 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" 320 | }, 321 | "dom-storage": { 322 | "version": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.0.2.tgz", 323 | "integrity": "sha1-7RfL9oq9EOCu+BgnE+KXxeS1ALA=" 324 | }, 325 | "ecdsa-sig-formatter": { 326 | "version": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", 327 | "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", 328 | "requires": { 329 | "base64url": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", 330 | "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.0.tgz" 331 | } 332 | }, 333 | "faye-websocket": { 334 | "version": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.3.tgz", 335 | "integrity": "sha1-SCpQWw3wrmJrlphm0710DNuWLoM=", 336 | "requires": { 337 | "websocket-driver": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz" 338 | } 339 | }, 340 | "hoek": { 341 | "version": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", 342 | "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" 343 | }, 344 | "isemail": { 345 | "version": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", 346 | "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=" 347 | }, 348 | "joi": { 349 | "version": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", 350 | "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", 351 | "requires": { 352 | "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", 353 | "isemail": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", 354 | "moment": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", 355 | "topo": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz" 356 | } 357 | }, 358 | "jsonwebtoken": { 359 | "version": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.1.tgz", 360 | "integrity": "sha1-fKMk9SFfi+A5zTWmxFu4y3SkSPs=", 361 | "requires": { 362 | "joi": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", 363 | "jws": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", 364 | "lodash.once": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 365 | "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 366 | "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" 367 | } 368 | }, 369 | "jwa": { 370 | "version": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", 371 | "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=", 372 | "requires": { 373 | "base64url": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", 374 | "buffer-equal-constant-time": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 375 | "ecdsa-sig-formatter": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", 376 | "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.0.tgz" 377 | } 378 | }, 379 | "jws": { 380 | "version": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", 381 | "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", 382 | "requires": { 383 | "base64url": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", 384 | "jwa": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", 385 | "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.0.tgz" 386 | } 387 | }, 388 | "lodash.once": { 389 | "version": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 390 | "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" 391 | }, 392 | "moment": { 393 | "version": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", 394 | "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=" 395 | }, 396 | "ms": { 397 | "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 398 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 399 | }, 400 | "promise-polyfill": { 401 | "version": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-6.0.2.tgz", 402 | "integrity": "sha1-2chtPcTcLfkBboiUbe/Wm0m0EWI=" 403 | }, 404 | "safe-buffer": { 405 | "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.0.tgz", 406 | "integrity": "sha1-/kyEYDl/nqqqWOc75GJzQIpF4iM=" 407 | }, 408 | "topo": { 409 | "version": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", 410 | "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", 411 | "requires": { 412 | "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" 413 | } 414 | }, 415 | "websocket-driver": { 416 | "version": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", 417 | "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", 418 | "requires": { 419 | "websocket-extensions": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz" 420 | } 421 | }, 422 | "websocket-extensions": { 423 | "version": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz", 424 | "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=" 425 | }, 426 | "xmlhttprequest": { 427 | "version": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", 428 | "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" 429 | }, 430 | "xtend": { 431 | "version": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 432 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" 433 | } 434 | } 435 | }, 436 | "follow-redirects": { 437 | "version": "1.2.4", 438 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.2.4.tgz", 439 | "integrity": "sha512-Suw6KewLV2hReSyEOeql+UUkBVyiBm3ok1VPrVFRZnQInWpdoZbbiG5i8aJVSjTr0yQ4Ava0Sh6/joCg1Brdqw==", 440 | "requires": { 441 | "debug": "2.6.1" 442 | } 443 | }, 444 | "forwarded": { 445 | "version": "0.1.0", 446 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", 447 | "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=" 448 | }, 449 | "fresh": { 450 | "version": "0.5.0", 451 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", 452 | "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=" 453 | }, 454 | "function-bind": { 455 | "version": "1.1.0", 456 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", 457 | "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=" 458 | }, 459 | "graceful-readlink": { 460 | "version": "1.0.1", 461 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 462 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" 463 | }, 464 | "has": { 465 | "version": "1.0.1", 466 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", 467 | "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", 468 | "requires": { 469 | "function-bind": "1.1.0" 470 | } 471 | }, 472 | "http-errors": { 473 | "version": "1.6.1", 474 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", 475 | "integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc=", 476 | "requires": { 477 | "depd": "1.1.0", 478 | "inherits": "2.0.3", 479 | "setprototypeof": "1.0.3", 480 | "statuses": "1.3.1" 481 | } 482 | }, 483 | "iconv-lite": { 484 | "version": "0.4.15", 485 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", 486 | "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=" 487 | }, 488 | "inherits": { 489 | "version": "2.0.3", 490 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 491 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 492 | }, 493 | "ipaddr.js": { 494 | "version": "1.3.0", 495 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz", 496 | "integrity": "sha1-HgOlL9rYOou7KyXL9JmLTP/NPew=" 497 | }, 498 | "is-buffer": { 499 | "version": "1.1.5", 500 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", 501 | "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" 502 | }, 503 | "is-expression": { 504 | "version": "2.1.0", 505 | "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-2.1.0.tgz", 506 | "integrity": "sha1-kb6dR968/vB3l36XIr5tz7RGXvA=", 507 | "requires": { 508 | "acorn": "3.3.0", 509 | "object-assign": "4.1.1" 510 | } 511 | }, 512 | "is-promise": { 513 | "version": "2.1.0", 514 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 515 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 516 | }, 517 | "is-regex": { 518 | "version": "1.0.4", 519 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 520 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 521 | "requires": { 522 | "has": "1.0.1" 523 | } 524 | }, 525 | "js-stringify": { 526 | "version": "1.0.2", 527 | "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", 528 | "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" 529 | }, 530 | "jstransformer": { 531 | "version": "1.0.0", 532 | "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", 533 | "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", 534 | "requires": { 535 | "is-promise": "2.1.0", 536 | "promise": "7.1.1" 537 | } 538 | }, 539 | "kind-of": { 540 | "version": "3.2.2", 541 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 542 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 543 | "requires": { 544 | "is-buffer": "1.1.5" 545 | } 546 | }, 547 | "lazy-cache": { 548 | "version": "1.0.4", 549 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 550 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" 551 | }, 552 | "lodash.lowercase": { 553 | "version": "4.3.0", 554 | "resolved": "https://registry.npmjs.org/lodash.lowercase/-/lodash.lowercase-4.3.0.tgz", 555 | "integrity": "sha1-RlFaztSssLcJMTMzOvBo5MOxTp0=" 556 | }, 557 | "longest": { 558 | "version": "1.0.1", 559 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", 560 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" 561 | }, 562 | "media-typer": { 563 | "version": "0.3.0", 564 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 565 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 566 | }, 567 | "merge-descriptors": { 568 | "version": "1.0.1", 569 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 570 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 571 | }, 572 | "methods": { 573 | "version": "1.1.2", 574 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 575 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 576 | }, 577 | "mime": { 578 | "version": "1.3.4", 579 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", 580 | "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" 581 | }, 582 | "mime-db": { 583 | "version": "1.27.0", 584 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", 585 | "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" 586 | }, 587 | "mime-types": { 588 | "version": "2.1.15", 589 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", 590 | "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", 591 | "requires": { 592 | "mime-db": "1.27.0" 593 | } 594 | }, 595 | "ms": { 596 | "version": "0.7.2", 597 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", 598 | "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" 599 | }, 600 | "negotiator": { 601 | "version": "0.6.1", 602 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 603 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 604 | }, 605 | "object-assign": { 606 | "version": "4.1.1", 607 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 608 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 609 | }, 610 | "on-finished": { 611 | "version": "2.3.0", 612 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 613 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 614 | "requires": { 615 | "ee-first": "1.1.1" 616 | } 617 | }, 618 | "parseurl": { 619 | "version": "1.3.1", 620 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", 621 | "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=" 622 | }, 623 | "path-parse": { 624 | "version": "1.0.5", 625 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", 626 | "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" 627 | }, 628 | "path-to-regexp": { 629 | "version": "0.1.7", 630 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 631 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 632 | }, 633 | "promise": { 634 | "version": "7.1.1", 635 | "resolved": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz", 636 | "integrity": "sha1-SJZUxpJha4qlWwck+oCbt9tJxb8=", 637 | "requires": { 638 | "asap": "2.0.5" 639 | } 640 | }, 641 | "proxy-addr": { 642 | "version": "1.1.4", 643 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.4.tgz", 644 | "integrity": "sha1-J+VF9pYKRKYn2bREZ+NcG2tM4vM=", 645 | "requires": { 646 | "forwarded": "0.1.0", 647 | "ipaddr.js": "1.3.0" 648 | } 649 | }, 650 | "pug": { 651 | "version": "2.0.0-rc.2", 652 | "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.0-rc.2.tgz", 653 | "integrity": "sha1-B4RVJ3kKssa+Z9z16x8xgECB8Eo=", 654 | "requires": { 655 | "pug-code-gen": "1.1.1", 656 | "pug-filters": "2.1.3", 657 | "pug-lexer": "3.1.0", 658 | "pug-linker": "3.0.1", 659 | "pug-load": "2.0.7", 660 | "pug-parser": "3.0.0", 661 | "pug-runtime": "2.0.3", 662 | "pug-strip-comments": "1.0.2" 663 | } 664 | }, 665 | "pug-attrs": { 666 | "version": "2.0.2", 667 | "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.2.tgz", 668 | "integrity": "sha1-i+KyIlVo/6ddG4Zpgr/59BEa/8s=", 669 | "requires": { 670 | "constantinople": "3.1.0", 671 | "js-stringify": "1.0.2", 672 | "pug-runtime": "2.0.3" 673 | } 674 | }, 675 | "pug-code-gen": { 676 | "version": "1.1.1", 677 | "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-1.1.1.tgz", 678 | "integrity": "sha1-HPcnRO8qA56uajNAyqoRBYcSWOg=", 679 | "requires": { 680 | "constantinople": "3.1.0", 681 | "doctypes": "1.1.0", 682 | "js-stringify": "1.0.2", 683 | "pug-attrs": "2.0.2", 684 | "pug-error": "1.3.2", 685 | "pug-runtime": "2.0.3", 686 | "void-elements": "2.0.1", 687 | "with": "5.1.1" 688 | } 689 | }, 690 | "pug-error": { 691 | "version": "1.3.2", 692 | "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.2.tgz", 693 | "integrity": "sha1-U659nSm7A89WRJOgJhCfVMR/XyY=" 694 | }, 695 | "pug-filters": { 696 | "version": "2.1.3", 697 | "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-2.1.3.tgz", 698 | "integrity": "sha1-1ZdnoiDeeX3XVUifZoNM+aqDqlQ=", 699 | "requires": { 700 | "clean-css": "3.4.26", 701 | "constantinople": "3.1.0", 702 | "jstransformer": "1.0.0", 703 | "pug-error": "1.3.2", 704 | "pug-walk": "1.1.3", 705 | "resolve": "1.3.3", 706 | "uglify-js": "2.8.29" 707 | } 708 | }, 709 | "pug-lexer": { 710 | "version": "3.1.0", 711 | "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-3.1.0.tgz", 712 | "integrity": "sha1-/QhzdtSmdbT1n4/vQiiDQ06VgaI=", 713 | "requires": { 714 | "character-parser": "2.2.0", 715 | "is-expression": "3.0.0", 716 | "pug-error": "1.3.2" 717 | }, 718 | "dependencies": { 719 | "acorn": { 720 | "version": "4.0.13", 721 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", 722 | "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" 723 | }, 724 | "is-expression": { 725 | "version": "3.0.0", 726 | "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", 727 | "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=", 728 | "requires": { 729 | "acorn": "4.0.13", 730 | "object-assign": "4.1.1" 731 | } 732 | } 733 | } 734 | }, 735 | "pug-linker": { 736 | "version": "3.0.1", 737 | "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.1.tgz", 738 | "integrity": "sha1-uj+P8hPKjzowSFm0T+0Tynud+hk=", 739 | "requires": { 740 | "pug-error": "1.3.2", 741 | "pug-walk": "1.1.3" 742 | } 743 | }, 744 | "pug-load": { 745 | "version": "2.0.7", 746 | "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.7.tgz", 747 | "integrity": "sha1-Ux0MbhFUYBDphGMNA99AY2fS3nc=", 748 | "requires": { 749 | "object-assign": "4.1.1", 750 | "pug-walk": "1.1.3" 751 | } 752 | }, 753 | "pug-parser": { 754 | "version": "3.0.0", 755 | "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-3.0.0.tgz", 756 | "integrity": "sha1-N8YZ3YAPZCGHzk1s4aFkzddUh6M=", 757 | "requires": { 758 | "pug-error": "1.3.2", 759 | "token-stream": "0.0.1" 760 | } 761 | }, 762 | "pug-runtime": { 763 | "version": "2.0.3", 764 | "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.3.tgz", 765 | "integrity": "sha1-mBYmB7D86eJU1CfzOYelrucWi9o=" 766 | }, 767 | "pug-strip-comments": { 768 | "version": "1.0.2", 769 | "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.2.tgz", 770 | "integrity": "sha1-0xOvoBvMN0mA4TmeI+vy65vchRM=", 771 | "requires": { 772 | "pug-error": "1.3.2" 773 | } 774 | }, 775 | "pug-walk": { 776 | "version": "1.1.3", 777 | "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.3.tgz", 778 | "integrity": "sha1-181bI9s8qHxjbIaglz+c2OAwQ2w=" 779 | }, 780 | "qs": { 781 | "version": "6.4.0", 782 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", 783 | "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" 784 | }, 785 | "range-parser": { 786 | "version": "1.2.0", 787 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 788 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 789 | }, 790 | "raw-body": { 791 | "version": "2.2.0", 792 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", 793 | "integrity": "sha1-mUl2z2pQlqQRYoQEkvC9xdbn+5Y=", 794 | "requires": { 795 | "bytes": "2.4.0", 796 | "iconv-lite": "0.4.15", 797 | "unpipe": "1.0.0" 798 | } 799 | }, 800 | "repeat-string": { 801 | "version": "1.6.1", 802 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 803 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" 804 | }, 805 | "resolve": { 806 | "version": "1.3.3", 807 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", 808 | "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", 809 | "requires": { 810 | "path-parse": "1.0.5" 811 | } 812 | }, 813 | "right-align": { 814 | "version": "0.1.3", 815 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", 816 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", 817 | "requires": { 818 | "align-text": "0.1.4" 819 | } 820 | }, 821 | "send": { 822 | "version": "0.15.1", 823 | "resolved": "https://registry.npmjs.org/send/-/send-0.15.1.tgz", 824 | "integrity": "sha1-igI1TCbm9cynAAZfXwzeupDse18=", 825 | "requires": { 826 | "debug": "2.6.1", 827 | "depd": "1.1.0", 828 | "destroy": "1.0.4", 829 | "encodeurl": "1.0.1", 830 | "escape-html": "1.0.3", 831 | "etag": "1.8.0", 832 | "fresh": "0.5.0", 833 | "http-errors": "1.6.1", 834 | "mime": "1.3.4", 835 | "ms": "0.7.2", 836 | "on-finished": "2.3.0", 837 | "range-parser": "1.2.0", 838 | "statuses": "1.3.1" 839 | } 840 | }, 841 | "serve-static": { 842 | "version": "1.12.1", 843 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.1.tgz", 844 | "integrity": "sha1-dEOpZePO1kes61Y5+ga/TRu+ADk=", 845 | "requires": { 846 | "encodeurl": "1.0.1", 847 | "escape-html": "1.0.3", 848 | "parseurl": "1.3.1", 849 | "send": "0.15.1" 850 | } 851 | }, 852 | "setprototypeof": { 853 | "version": "1.0.3", 854 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 855 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 856 | }, 857 | "source-map": { 858 | "version": "0.4.4", 859 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", 860 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", 861 | "requires": { 862 | "amdefine": "1.0.1" 863 | } 864 | }, 865 | "statuses": { 866 | "version": "1.3.1", 867 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", 868 | "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" 869 | }, 870 | "token-stream": { 871 | "version": "0.0.1", 872 | "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", 873 | "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=" 874 | }, 875 | "type-is": { 876 | "version": "1.6.15", 877 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", 878 | "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", 879 | "requires": { 880 | "media-typer": "0.3.0", 881 | "mime-types": "2.1.15" 882 | } 883 | }, 884 | "uglify-js": { 885 | "version": "2.8.29", 886 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", 887 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", 888 | "requires": { 889 | "source-map": "0.5.6", 890 | "uglify-to-browserify": "1.0.2", 891 | "yargs": "3.10.0" 892 | }, 893 | "dependencies": { 894 | "source-map": { 895 | "version": "0.5.6", 896 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", 897 | "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=" 898 | } 899 | } 900 | }, 901 | "uglify-to-browserify": { 902 | "version": "1.0.2", 903 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", 904 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", 905 | "optional": true 906 | }, 907 | "unpipe": { 908 | "version": "1.0.0", 909 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 910 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 911 | }, 912 | "utils-merge": { 913 | "version": "1.0.0", 914 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", 915 | "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" 916 | }, 917 | "vary": { 918 | "version": "1.1.1", 919 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", 920 | "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=" 921 | }, 922 | "void-elements": { 923 | "version": "2.0.1", 924 | "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", 925 | "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" 926 | }, 927 | "window-size": { 928 | "version": "0.1.0", 929 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", 930 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" 931 | }, 932 | "with": { 933 | "version": "5.1.1", 934 | "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", 935 | "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=", 936 | "requires": { 937 | "acorn": "3.3.0", 938 | "acorn-globals": "3.1.0" 939 | } 940 | }, 941 | "wordwrap": { 942 | "version": "0.0.2", 943 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", 944 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" 945 | }, 946 | "yargs": { 947 | "version": "3.10.0", 948 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", 949 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", 950 | "requires": { 951 | "camelcase": "1.2.1", 952 | "cliui": "2.1.0", 953 | "decamelize": "1.2.0", 954 | "window-size": "0.1.0" 955 | } 956 | } 957 | } 958 | } 959 | -------------------------------------------------------------------------------- /store/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "perfbench-store", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "dev": "dev=true node index", 7 | "start": "node index" 8 | }, 9 | "engines": { 10 | "node": "8.x.x" 11 | }, 12 | "now": { 13 | "env": { 14 | "apiKey": "@perfbench_apikey", 15 | "databaseURL": "@perfbench_databaseurl", 16 | "githubId": "@perfbench_githubid", 17 | "githubSecret": "@perfbench_githubsecret" 18 | }, 19 | "files": [ 20 | "index.js", 21 | "github.js", 22 | "firebase.js", 23 | "views", 24 | "static" 25 | ] 26 | }, 27 | "keywords": [], 28 | "author": "siddharthkp", 29 | "license": "MIT", 30 | "dependencies": { 31 | "axios": "0.16.1", 32 | "body-parser": "1.17.2", 33 | "dotenv": "4.0.0", 34 | "express": "4.15.2", 35 | "firebase": "4.1.2", 36 | "lodash.lowercase": "4.3.0", 37 | "pug": "2.0.0-rc.2" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /store/static/styles.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | body { 6 | background: #F5F7FA; 7 | font-family: 'Nunito', sans-serif; 8 | font-size: 16px; 9 | line-height: 1.6; 10 | } 11 | .logo { 12 | display: block; 13 | height: 100px; 14 | margin: 50px auto; 15 | } 16 | .big { 17 | font-size: 25px; 18 | } 19 | .dark { 20 | color: #192235; 21 | } 22 | .light { 23 | color: #969FA5; 24 | } 25 | .card { 26 | width: 80%; 27 | margin: 0 auto; 28 | padding: 25px; 29 | background: #FFF; 30 | border-radius: 5px; 31 | box-shadow: 0px 3px 5px 2px rgba(201, 214, 255, 0.15); 32 | } 33 | .metrics { 34 | margin: 50px 0; 35 | } 36 | .metrics .label { 37 | display: inline-block; 38 | font-size: 12px; 39 | } 40 | .metric { 41 | margin: 25px 0; 42 | } 43 | .metric > div { 44 | display: inline-block; 45 | } 46 | .metric.fail { 47 | color: #FA5E7C; 48 | } 49 | .name { 50 | width: 20%; 51 | } 52 | .threshold { 53 | width: 50%; 54 | } 55 | .metric.fail .light { 56 | color: #FA5E7C; 57 | } 58 | .size { 59 | text-align: right; 60 | width: 15%; 61 | } 62 | .master { 63 | text-align: right; 64 | width: 10%; 65 | } 66 | .bar { 67 | height: 7px; 68 | background: #EEE; 69 | border-radius: 10px; 70 | width: 100%; 71 | } 72 | .bar.first { 73 | background: #4680FF; 74 | z-index: 2; 75 | position: relative; 76 | top: 7px; 77 | } 78 | .guides { 79 | line-height: 2; 80 | } 81 | 82 | .mobile { 83 | display: none; 84 | } 85 | @media (max-width: 800px) { 86 | .desktop { 87 | display: none; 88 | } 89 | .mobile { 90 | display: inline; 91 | } 92 | .name { 93 | width: 50%; 94 | } 95 | .threshold { 96 | width: 100%; 97 | padding: 10px 0; 98 | } 99 | .size, .master { 100 | width: 100%; 101 | text-align: left; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /store/views/auth.pug: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 | BUNDLESIZE_GITHUB_TOKEN: 13 | #{token} 14 |
15 |
Add this as an environment variable in your CIs project settings
16 |
17 |
18 |
19 |
GUIDES
20 |
21 |
22 |
travis CI
23 |
circle CI
24 |
wercker CI
25 |
26 |
27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /store/views/build.pug: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 | #{commit_message} 13 | ##{sha} 14 |
15 |
#{repo} : #{branch}
16 |
17 |
18 |
19 |
NAME
20 |
21 |
SIZE/THRESHOLD
22 |
MASTER
23 |
24 | each metric in metrics 25 |
26 |
#{metric.name}
27 |
28 |
29 |
30 |
31 |
#{metric.value}/#{metric.threshold} #{metric.unit}
32 | if metric.diff 33 |
master #{metric.diff} #{metric.unit}
34 |
35 |
36 |
37 | 38 | 39 | --------------------------------------------------------------------------------