├── .dockerignore ├── .gitignore ├── .jshintignore ├── .npmignore ├── .npmrc ├── .prettierrc ├── .tool-versions ├── Dockerfile ├── LICENSE ├── Procfile ├── README.md ├── docker-compose.yml ├── docker-entrypoint.sh ├── package.json ├── src ├── app.js ├── generator.js ├── generatorQueue.js ├── main.js ├── middleware │ ├── requireHeader.js │ └── requireNestedParams.js ├── models │ └── CachedCss.js ├── processors │ └── cssProcessor.js ├── redisOpts.js ├── workers.js └── workers │ ├── BuildCss.js │ └── QueueBuildRequests.js ├── test ├── app_test.js ├── generator_test.js ├── models │ └── cached_css_test.js └── workers │ └── build_css_test.js └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | tmp 2 | log 3 | .git 4 | *.dump 5 | .idea 6 | *.swp 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | test-interaction.js 3 | test-read.js 4 | npm-debug.log 5 | newrelic_agent.log 6 | curl_command 7 | .DS_Store 8 | node_modules 9 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # package directories 2 | node_modules 3 | jspm_packages 4 | 5 | # Serverless directories 6 | .serverless -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | save=true 2 | save-exact=true 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | nodejs 14.16.0 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8.2.0 2 | 3 | ENV APP_HOME /app_home 4 | RUN mkdir $APP_HOME 5 | WORKDIR $APP_HOME 6 | ADD . $APP_HOME 7 | 8 | RUN npm install -g yarn 9 | 10 | RUN apt-get update && apt-get install -yq libgconf-2-4 11 | 12 | # Install latest chrome dev package. 13 | # Note: this installs the necessary libs to make the bundled version of Chromium that Puppeteer 14 | # installs, work. 15 | RUN apt-get update && apt-get install -y wget --no-install-recommends \ 16 | && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ 17 | && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ 18 | && apt-get update \ 19 | && apt-get install -y google-chrome-stable \ 20 | --no-install-recommends \ 21 | && rm -rf /var/lib/apt/lists/* \ 22 | && apt-get purge --auto-remove -y curl \ 23 | && rm -rf /src/*.deb 24 | 25 | # Install puppeteer so it's available in the container. 26 | RUN yarn add puppeteer 27 | 28 | COPY ./docker-entrypoint.sh / 29 | ENTRYPOINT ["/docker-entrypoint.sh"] 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Michael Wheeler 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: npm start 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Eliminate render-blocking CSS in above-the-fold content 2 | 3 | If you've run [Google Pagespeed Insights](https://developers.google.com/speed/pagespeed/insights/) on your web app, you might have seen this message: 4 | 5 | > *Eliminate render-blocking JavaScript and CSS in above-the-fold content* 6 | > 7 | > Your page has blocking CSS resources. This causes a delay in rendering your page. 8 | > None of the above-the-fold content on your page could be rendered without waiting for the following resources to load. Try to defer or asynchronously load blocking resources, or inline the critical portions of those resources directly in the HTML. 9 | 10 | This server generates the critical path CSS for you. It is designed to sit alongside your production app, and prepare the critical CSS asynchronously. 11 | 12 | Builds can be started after each deploy, and a few seconds later, you'll be able to defer or asynchronously load blocking resources, and inline the critical portions for your page. 13 | 14 | ## Install 15 | 16 | `npm install critical-path-server` 17 | 18 | ## Usage 19 | 20 | #### Start the server 21 | 22 | npm start 23 | > Listening on port: 8080 24 | 25 | #### Send a request with details about the page you want cached 26 | 27 | The first request returns immediately, and starts generating the CSS in the background: 28 | 29 | curl -H "Content-Type: application/json" -X POST -d '{ "page": {"key":"unique-key","url":"http://www.example.com/","css":"https://www.example.com/style.css"}}' localhost:5000/api/v1/css 30 | > Accepted 31 | 32 | #### Eventually... 33 | 34 | curl -H "Content-Type: application/json" -X POST -d '{ "page": {"key":"unique-key","url":"http://www.example.com/","css":"https://www.example.com/style.css"}}' localhost:5000/api/v1/css 35 | > .your-critical-css {} 36 | 37 | 38 | ## Ruby on Rails 39 | 40 | Use the Ruby on Rails client to manage rewriting and lazy-loading your other CSS assets, once the critical path has been 41 | compiled and is available. 42 | 43 | [RailsCriticalCssServer](https://github.com/wheeyls/rails_critical_css_server) 44 | 45 | ## Docker 46 | 47 | This repo is setup with docker. You can get it up and running with the following commands. 48 | 49 | ``` 50 | docker build -t critical-css-server . 51 | docker-compose up critical-css 52 | ``` 53 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | redis: 4 | image: redis:2.8 5 | ports: 6 | - '6739:6379' 7 | critical-css: 8 | image: critical-css-server:latest 9 | command: npm start 10 | ports: 11 | - '5000:5000' 12 | depends_on: 13 | - redis 14 | volumes: 15 | - ./:/app_home:delegated 16 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | export PORT=5000 4 | export REDIS_URL=redis://redis 5 | yarn install 6 | exec "$@" 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "critical-css-server", 3 | "version": "0.5.0", 4 | "description": "Build critical path css asynchronously on demand", 5 | "main": "src/main.js", 6 | "scripts": { 7 | "start": "node src/main.js", 8 | "test": "mocha --recursive", 9 | "debug": "node --inspect-brk src/main.js" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/wheeyls/critical-css-server" 14 | }, 15 | "keywords": [ 16 | "node", 17 | "criticalcss", 18 | "above-the-fold", 19 | "inline-css", 20 | "pagespeed", 21 | "phantomjs" 22 | ], 23 | "license": "MIT", 24 | "dependencies": { 25 | "bluebird": "3.4.7", 26 | "body-parser": "1.16.0", 27 | "bull": "3.3.7", 28 | "cluster": "0.7.7", 29 | "express": "4.14.1", 30 | "extend": "3.0.0", 31 | "penthouse": "1.3.0", 32 | "redis": "2.6.5", 33 | "redis-url": "1.2.1", 34 | "request": "2.79.0", 35 | "yarn": "1.0.2" 36 | }, 37 | "devDependencies": { 38 | "expect.js": "0.3.1", 39 | "mocha": "3.2.0", 40 | "prettier": "1.6.1", 41 | "redis-mock": "0.16.0", 42 | "simple-mock": "0.7.3", 43 | "supertest": "3.0.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var express = require('express'); 3 | var extend = require('extend'); 4 | var redis = require('redis'); 5 | var redisOpts = require('./redisOpts.js'); 6 | var QueueBuildRequests = require('./workers/QueueBuildRequests.js'); 7 | var requireHeader = require('./middleware/requireHeader.js'); 8 | var requireNestedParams = require('./middleware/requireNestedParams.js'); 9 | 10 | var bull = require('bull'); 11 | var bodyParser = require('body-parser'); 12 | 13 | var defaults = { 14 | redis: redis.createClient(redisOpts), 15 | queue: bull( 16 | 'CriticalPath Generator', 17 | process.env.REDIS_URL, 18 | redisOpts.options, 19 | ), 20 | }; 21 | 22 | function prepareApp(config) { 23 | var app = express(); 24 | var options = extend(defaults, config); 25 | var worker = new QueueBuildRequests(options.redis, options.queue); 26 | 27 | options.redis.on('error', function(err) { console.error(err); }); 28 | 29 | app.use(bodyParser.json()); 30 | 31 | app.post( 32 | '/api/v1/css', 33 | requireHeader('Content-Type', 'application/json'), 34 | requireNestedParams('page', ['key', 'url', 'css']), 35 | function(req, res) { 36 | worker 37 | .perform(req.body) 38 | .then(function(item) { 39 | if (item.attributes.content) { 40 | res.send(item.attributes.content); 41 | } else { 42 | res.status(202).send('Accepted'); 43 | } 44 | }) 45 | .catch(function(e) { 46 | console.log(e); 47 | res.sendStatus(500); 48 | }); 49 | }, 50 | ); 51 | 52 | return app; 53 | } 54 | 55 | module.exports = prepareApp; 56 | -------------------------------------------------------------------------------- /src/generator.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var request = require('request'); 3 | var bluebird = require('bluebird'); 4 | var path = require('path'); 5 | var penthouse = require('penthouse'); 6 | var fs = require('fs'); 7 | var tmpDir = require('os').tmpdir(); 8 | var extend = require('extend'); 9 | 10 | var tmpPath = path.join(tmpDir, 'crit.css'); 11 | var forced = []; 12 | 13 | var defaultOptions = {forceInclude: forced, ignoreConsole: true}; 14 | var phantomJsOptions = {'ssl-protocol': 'any'}; 15 | 16 | var generate = bluebird.promisify(function( 17 | sourceUrl, 18 | cssUrl, 19 | options, 20 | callback, 21 | ) { 22 | try { 23 | options = extend({}, defaultOptions, options); 24 | 25 | request({uri: cssUrl, timeout: 10000}) 26 | .on('error', callback) 27 | .pipe(fs.createWriteStream(tmpPath)) 28 | .on('error', callback) 29 | .on('close', function() { 30 | penthouse( 31 | extend(options, { 32 | url: sourceUrl, 33 | css: tmpPath, 34 | strict: true, 35 | phantomJsOptions: phantomJsOptions, 36 | }), 37 | ) 38 | .then(function(criticalCss) { 39 | callback(null, criticalCss); 40 | }) 41 | .catch(callback); 42 | }); 43 | } catch (err) { 44 | callback(err); 45 | } 46 | }); 47 | 48 | module.exports = function() { 49 | var me; 50 | 51 | me = {generate: generate}; 52 | 53 | return me; 54 | }; 55 | -------------------------------------------------------------------------------- /src/generatorQueue.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var bull = require('bull'); 3 | var queue = bull('CriticalPath Generator', process.env.REDIS_URL); 4 | 5 | module.exports = queue; 6 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var cluster = require('cluster'); 3 | var workerCount = process.env.CONCURRENCY || 1; 4 | var app = require('./app.js')(); 5 | var queue = require('./generatorQueue.js'); 6 | var workers = require('./workers.js')(queue); 7 | var port = process.env.PORT || 5000; 8 | 9 | if (cluster.isMaster) { 10 | setInterval(function() { 11 | queue.clean(1000 * 60 * 60); 12 | }, 60000); 13 | 14 | app.listen(port, function() { 15 | console.log('Listening on port:', this.address().port); 16 | }); 17 | 18 | for (var i = 0, ii = workerCount; i < ii; i += 1) { 19 | var clusterWorker = cluster.fork(); 20 | clusterWorker.on('exit', function(code, signal) { 21 | if (signal) { 22 | console.log(`worker was killed by signal: ${signal}`); 23 | } else if (code !== 0) { 24 | console.error(`worker exited with error code: ${code}`); 25 | } else { 26 | console.log('worker success!'); 27 | } 28 | }); 29 | 30 | clusterWorker.on('error', function(err) { console.error(err) }); 31 | } 32 | } else { 33 | workers.start(); 34 | } 35 | -------------------------------------------------------------------------------- /src/middleware/requireHeader.js: -------------------------------------------------------------------------------- 1 | // @format 2 | function requireHeader(name, value) { 3 | return function(req, res, next) { 4 | if (req.get(name) !== value) { 5 | console.log('Wrong Header', {required: name, value: req.get(name)}); 6 | res.sendStatus(406); 7 | } else { 8 | next(); 9 | } 10 | }; 11 | } 12 | 13 | module.exports = requireHeader; 14 | -------------------------------------------------------------------------------- /src/middleware/requireNestedParams.js: -------------------------------------------------------------------------------- 1 | // @format 2 | function requireNestedParams(parentKey, keys) { 3 | return function(req, res, next) { 4 | var hash = req.body && req.body[parentKey]; 5 | if (!hash) { 6 | console.log('Missing Required Key', parentKey); 7 | return res.sendStatus(406); 8 | } 9 | 10 | var paramKeys = Object.keys(hash); 11 | 12 | if ( 13 | keys.some(function(key) { 14 | return !paramKeys.includes(key); 15 | }) 16 | ) { 17 | console.log('Missing Required Key', {required: keys, actual: paramKeys}); 18 | res.sendStatus(406); 19 | } else { 20 | next(); 21 | } 22 | }; 23 | } 24 | 25 | module.exports = requireNestedParams; 26 | -------------------------------------------------------------------------------- /src/models/CachedCss.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var extend = require('extend'); 3 | 4 | function CachedCss(client, finders) { 5 | this.client = client; 6 | this.finders = finders; 7 | this.attributes = extend({}, finders); 8 | } 9 | 10 | extend(CachedCss.prototype, { 11 | loaded: false, 12 | 13 | expireAfter: 60 * 60, 14 | 15 | load: function() { 16 | var that = this; 17 | 18 | return new Promise(function(resolve, reject) { 19 | if (that.loaded) { 20 | resolve(that.attributes); 21 | } else { 22 | that.client.hgetall(that.finders.key, function(err, value) { 23 | if (err) { 24 | return reject(err); 25 | } 26 | 27 | if (!value) { 28 | extend(that.attributes, {status: 'new'}); 29 | } else { 30 | that.attributes = value; 31 | } 32 | 33 | that.loaded = true; 34 | resolve(that.attributes); 35 | }); 36 | } 37 | }); 38 | }, 39 | 40 | save: function(attrs, cb) { 41 | if (attrs) { 42 | extend(this.attributes, attrs); 43 | } 44 | 45 | this.client.expire(this.finders.key, this.expireAfter); 46 | this.client.hmset(this.finders.key, this.flatAttributes(), function( 47 | err, 48 | value, 49 | ) { 50 | cb(err); 51 | }); 52 | }, 53 | 54 | del: function(cb) { 55 | this.client.del(this.finders.key, cb); 56 | }, 57 | 58 | createStub: function(cb) { 59 | this.save({status: 'waiting'}, cb); 60 | }, 61 | 62 | finish: function(content, cb) { 63 | this.save({status: 'done', content: content}, cb); 64 | }, 65 | 66 | failed: function(cb) { 67 | this.save({status: 'failed'}, cb); 68 | }, 69 | 70 | begin: function(cb) { 71 | this.save({status: 'working'}, cb); 72 | }, 73 | 74 | toJSON: function() { 75 | return this.attributes; 76 | }, 77 | 78 | flatAttributes: function() { 79 | var that = this; 80 | var results = []; 81 | 82 | Object.keys(this.attributes).forEach(function(key) { 83 | results.push(key); 84 | results.push(that.attributes[key]); 85 | }); 86 | 87 | return results; 88 | }, 89 | }); 90 | 91 | module.exports = CachedCss; 92 | -------------------------------------------------------------------------------- /src/processors/cssProcessor.js: -------------------------------------------------------------------------------- 1 | 2 | var BuildCss = require('../workers/BuildCss.js'); 3 | var redis = require('redis'); 4 | var generator = require('../generator.js'); 5 | 6 | var redisClient = redis.createClient({ url: process.env.REDIS_URL }); 7 | redisClient.on('error', function (err) { console.error(err) }); 8 | var worker = new BuildCss(generator(), redisClient); 9 | 10 | 11 | module.exports = function (job, done) { 12 | console.log('bull: process started...', job.data.page.key); 13 | return worker 14 | .perform(job.data) 15 | .then(function (data) { 16 | console.log('bull: process done', job.data.page.key); 17 | done(null, data); 18 | }) 19 | .catch(function (err) { 20 | console.error('bull: process catch', job.data.page.key); 21 | done(err); 22 | }); 23 | }; 24 | -------------------------------------------------------------------------------- /src/redisOpts.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var url = process.env.REDIS_URL || 'redis://127.0.0.1:6379/'; 3 | var redisOpts = require('redis-url').parse(url); 4 | 5 | module.exports = { 6 | host: redisOpts.hostname, 7 | port: redisOpts.port, 8 | password: redisOpts.password, 9 | options: {db: redisOpts.database || 0}, 10 | }; 11 | -------------------------------------------------------------------------------- /src/workers.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var path = require('path'); 3 | 4 | module.exports = function(queue) { 5 | return { 6 | start: function() { 7 | console.log('bull: worker started...'); 8 | 9 | 10 | 11 | queue.on('completed', function(job) { 12 | console.log('bull: completed: ', job.data.page.key); 13 | }); 14 | 15 | queue.on('error', function(job) { 16 | console.error('bull: job error! ', job); 17 | }); 18 | 19 | queue.on('stalled', function(job) { 20 | console.error('bull: job stalled', job); 21 | }) 22 | 23 | queue.on('exit', function(worker, code, signal) { 24 | console.error('bull: worker died', worker, code, signal); 25 | }); 26 | 27 | queue.on('failed', function(job) { 28 | console.error('bull: job failed! ', job); 29 | }); 30 | 31 | queue.process(path.join(__dirname, 'processors', 'cssProcessor.js')); 32 | }, 33 | }; 34 | }; 35 | -------------------------------------------------------------------------------- /src/workers/BuildCss.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var CachedCss = require('../models/CachedCss.js'); 3 | var bluebird = require('bluebird'); 4 | 5 | function BuildCss(generator, client) { 6 | this.perform = bluebird.promisify(function(data, done) { 7 | var pageData = data.page; 8 | var config = data.config; 9 | var item = new CachedCss(client, pageData); 10 | 11 | try { 12 | item.begin(function() { 13 | generator.generate(pageData.url, pageData.css, config, function( 14 | err, 15 | output 16 | ) { 17 | if (err) { 18 | item.del(function() { 19 | done(err); 20 | }); 21 | } else { 22 | item.finish(output, done); 23 | } 24 | }); 25 | }); 26 | } catch (err) { 27 | item.del(function() { 28 | done(err); 29 | }); 30 | } 31 | }); 32 | } 33 | 34 | module.exports = BuildCss; 35 | -------------------------------------------------------------------------------- /src/workers/QueueBuildRequests.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var CachedCss = require('../models/CachedCss.js'); 3 | var bluebird = require('bluebird'); 4 | 5 | function QueueBuildRequests(client, queue) { 6 | this.perform = bluebird.promisify(function(data, done) { 7 | var item = new CachedCss(client, data.page); 8 | 9 | item 10 | .load() 11 | .then(function(attributes) { 12 | if (['new', 'failed'].includes(attributes.status)) { 13 | item.createStub(function(err) { 14 | if (err) { 15 | return done(err); 16 | } 17 | 18 | queue.add( 19 | {page: item.toJSON(), config: data.config}, 20 | {attempts: 1, timeout: 30000}, 21 | ); 22 | console.log('added...'); 23 | done(null, item); 24 | }); 25 | } else { 26 | done(null, item); 27 | } 28 | }) 29 | .catch(function(e) { 30 | done(e); 31 | }); 32 | }); 33 | } 34 | 35 | module.exports = QueueBuildRequests; 36 | -------------------------------------------------------------------------------- /test/app_test.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var request = require('supertest'); 3 | var prepareApp = require('../src/app.js'); 4 | var expect = require('expect.js'); 5 | var CachedCss = require('../src/models/CachedCss.js'); 6 | var redis = require('redis-mock'); 7 | var simple = require('simple-mock'); 8 | 9 | describe('app.js', function() { 10 | describe('POST /api/v1/css', function() { 11 | before(function() { 12 | this.client = redis.createClient(); 13 | this.app = prepareApp({redis: this.client, queue: {add: simple.stub()}}); 14 | }); 15 | 16 | describe('with valid params', function() { 17 | var params = {page: {key: 1, url: '/path', css: '/css'}}; 18 | 19 | describe('asking for item that is ready', function() { 20 | before(function(done) { 21 | this.cached = new CachedCss(this.client, params.page); 22 | this.cached.finish('css {};', done); 23 | }); 24 | 25 | it('should return a 200 and the content', function() { 26 | return request(this.app) 27 | .post('/api/v1/css') 28 | .send(params) 29 | .set('Content-Type', 'application/json') 30 | .expect(200, 'css {};'); 31 | }); 32 | }); 33 | 34 | describe('asking for item that is new', function() { 35 | var params = {page: {key: 2, url: '/path', css: '/css'}}; 36 | 37 | it('should return a 202', function() { 38 | return request(this.app) 39 | .post('/api/v1/css') 40 | .send(params) 41 | .set('Content-Type', 'application/json') 42 | .expect(202); 43 | }); 44 | }); 45 | 46 | describe('asking for item that is working', function() { 47 | var params = {page: {key: 'working', url: '/path', css: '/css'}}; 48 | before(function(done) { 49 | this.cached = new CachedCss(this.client, params.page); 50 | this.cached.createStub(done); 51 | }); 52 | 53 | it('should return a 202', function() { 54 | return request(this.app) 55 | .post('/api/v1/css') 56 | .send(params) 57 | .set('Content-Type', 'application/json') 58 | .expect(202); 59 | }); 60 | }); 61 | 62 | describe('asking for item that is waiting', function() { 63 | var params = {page: {key: 'waiting', url: '/path', css: '/css'}}; 64 | before(function(done) { 65 | this.cached = new CachedCss(this.client, params.page); 66 | this.cached.begin(done); 67 | }); 68 | 69 | it('should return a 202', function() { 70 | return request(this.app) 71 | .post('/api/v1/css') 72 | .send(params) 73 | .set('Content-Type', 'application/json') 74 | .expect(202); 75 | }); 76 | }); 77 | 78 | describe('asking for item that is failed', function() { 79 | var params = {page: {key: 'failed', url: '/path', css: '/css'}}; 80 | before(function(done) { 81 | this.cached = new CachedCss(this.client, params.page); 82 | this.cached.failed(done); 83 | }); 84 | 85 | it('should return a 202', function() { 86 | return request(this.app) 87 | .post('/api/v1/css') 88 | .send(params) 89 | .set('Content-Type', 'application/json') 90 | .expect(202); 91 | }); 92 | }); 93 | }); 94 | }); 95 | }); 96 | -------------------------------------------------------------------------------- /test/generator_test.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var expect = require('expect.js'); 3 | var generator = require('../src/generator.js')(); 4 | 5 | describe('#generate', function() { 6 | describe('with no url', function() { 7 | it('returns an error', function() { 8 | generator 9 | .generate('http://example.com', 'aaa', function() {}) 10 | .catch(function(e) { 11 | expect(e).to.be.a(Error); 12 | }); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/models/cached_css_test.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var expect = require('expect.js'); 3 | var CachedCss = require('../../src/models/CachedCss.js'); 4 | var redis = require('redis-mock'); 5 | 6 | describe('CachedCss', function() { 7 | before(function() { 8 | this.client = redis.createClient(); 9 | this.subject = new CachedCss(this.client, { 10 | key: 'unique', 11 | url: '/path', 12 | css: '/css', 13 | }); 14 | }); 15 | 16 | describe('#load', function() { 17 | describe('with no existing record', function(done) { 18 | it('returns undefined', function() { 19 | return this.subject.load().then(function(attributes) { 20 | expect(attributes.status).to.be('new'); 21 | }); 22 | }); 23 | }); 24 | 25 | describe('with existing record', function(done) { 26 | before(function(done) { 27 | this.subject.createStub(done); 28 | }); 29 | 30 | it('returns list of attributes', function() { 31 | return this.subject.load().then(function(attributes) { 32 | expect(attributes.status).to.eql('waiting'); 33 | }); 34 | }); 35 | }); 36 | }); 37 | 38 | describe('#save', function() { 39 | it('writes attributes to redis', function(done) { 40 | var that = this; 41 | 42 | this.subject.save({x: 1}, function() { 43 | expect(that.subject.attributes.x).to.eql(1); 44 | done(); 45 | }); 46 | }); 47 | }); 48 | 49 | describe('#createStub', function() { 50 | it('sets status to waiting', function(done) { 51 | var that = this; 52 | 53 | this.subject.createStub(function() { 54 | expect(that.subject.attributes.status).to.eql('waiting'); 55 | done(); 56 | }); 57 | }); 58 | }); 59 | 60 | describe('#finish', function() { 61 | it('sets status to done', function(done) { 62 | var that = this; 63 | that.subject.finish('content', function() { 64 | expect(that.subject.attributes.status).to.eql('done'); 65 | done(); 66 | }); 67 | }); 68 | 69 | it('writes content', function(done) { 70 | var that = this; 71 | that.subject.finish('content', function() { 72 | expect(that.subject.attributes.content).to.eql('content'); 73 | done(); 74 | }); 75 | }); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /test/workers/build_css_test.js: -------------------------------------------------------------------------------- 1 | // @format 2 | var expect = require('expect.js'); 3 | var BuildCss = require('../../src/workers/BuildCss.js'); 4 | var CachedCss = require('../../src/models/CachedCss.js'); 5 | var redis = require('redis-mock'); 6 | var simple = require('simple-mock'); 7 | 8 | describe('BuildCss', function() { 9 | before(function() { 10 | this.client = redis.createClient(); 11 | this.generator = {generate: simple.stub().callbackWith(null, 'content')}; 12 | this.subject = new BuildCss(this.generator, this.client); 13 | this.data = {page: {url: '/path', css: '/css', key: '123'}, config: {o: 1}}; 14 | }); 15 | 16 | describe('#perform', function() { 17 | it('calls generate', function(done) { 18 | var that = this; 19 | 20 | this.subject.perform(that.data).then(function() { 21 | expect(that.generator.generate.lastCall.args[0]).to.eql('/path'); 22 | expect(that.generator.generate.lastCall.args[1]).to.eql('/css'); 23 | expect(that.generator.generate.lastCall.args[2]).to.be( 24 | that.data.config, 25 | ); 26 | done(); 27 | }); 28 | }); 29 | 30 | it('persists the results to a model', function(done) { 31 | var item = new CachedCss(this.client, this.data.page); 32 | 33 | this.subject.perform(this.data).then(function() { 34 | item.load().then(function() { 35 | expect(item.attributes.status).to.eql('done'); 36 | expect(item.attributes.content).to.eql('content'); 37 | done(); 38 | }); 39 | }); 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | accepts@~1.3.3: 6 | version "1.3.4" 7 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" 8 | dependencies: 9 | mime-types "~2.1.16" 10 | negotiator "0.6.1" 11 | 12 | agent-base@^4.1.0: 13 | version "4.1.2" 14 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.1.2.tgz#80fa6cde440f4dcf9af2617cf246099b5d99f0c8" 15 | dependencies: 16 | es6-promisify "^5.0.0" 17 | 18 | ansi-regex@^2.0.0: 19 | version "2.1.1" 20 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 21 | 22 | ansi-styles@^2.2.1: 23 | version "2.2.1" 24 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 25 | 26 | array-flatten@1.1.1: 27 | version "1.1.1" 28 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 29 | 30 | asn1@~0.2.3: 31 | version "0.2.3" 32 | resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" 33 | 34 | assert-plus@1.0.0, assert-plus@^1.0.0: 35 | version "1.0.0" 36 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" 37 | 38 | assert-plus@^0.2.0: 39 | version "0.2.0" 40 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" 41 | 42 | async-limiter@~1.0.0: 43 | version "1.0.0" 44 | resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" 45 | 46 | asynckit@^0.4.0: 47 | version "0.4.0" 48 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 49 | 50 | aws-sign2@~0.6.0: 51 | version "0.6.0" 52 | resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" 53 | 54 | aws4@^1.2.1: 55 | version "1.6.0" 56 | resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" 57 | 58 | balanced-match@^1.0.0: 59 | version "1.0.0" 60 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 61 | 62 | bcrypt-pbkdf@^1.0.0: 63 | version "1.0.1" 64 | resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" 65 | dependencies: 66 | tweetnacl "^0.14.3" 67 | 68 | bluebird@3.4.7: 69 | version "3.4.7" 70 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" 71 | 72 | bluebird@^3.3.4, bluebird@^3.5.0: 73 | version "3.5.0" 74 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" 75 | 76 | body-parser@1.16.0: 77 | version "1.16.0" 78 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.16.0.tgz#924a5e472c6229fb9d69b85a20d5f2532dec788b" 79 | dependencies: 80 | bytes "2.4.0" 81 | content-type "~1.0.2" 82 | debug "2.6.0" 83 | depd "~1.1.0" 84 | http-errors "~1.5.1" 85 | iconv-lite "0.4.15" 86 | on-finished "~2.3.0" 87 | qs "6.2.1" 88 | raw-body "~2.2.0" 89 | type-is "~1.6.14" 90 | 91 | boom@2.x.x: 92 | version "2.10.1" 93 | resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" 94 | dependencies: 95 | hoek "2.x.x" 96 | 97 | brace-expansion@^1.1.7: 98 | version "1.1.8" 99 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" 100 | dependencies: 101 | balanced-match "^1.0.0" 102 | concat-map "0.0.1" 103 | 104 | browser-stdout@1.3.0: 105 | version "1.3.0" 106 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" 107 | 108 | bull@3.3.7: 109 | version "3.3.7" 110 | resolved "https://registry.yarnpkg.com/bull/-/bull-3.3.7.tgz#d8075830134dab28b075bd0bcd2aa5144a5c4218" 111 | dependencies: 112 | bluebird "^3.5.0" 113 | cron-parser "^2.4.1" 114 | debuglog "^1.0.0" 115 | ioredis "^3.1.4" 116 | lodash "^4.17.4" 117 | semver "^5.4.1" 118 | uuid "^3.1.0" 119 | 120 | bytes@2.4.0: 121 | version "2.4.0" 122 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" 123 | 124 | caseless@~0.11.0: 125 | version "0.11.0" 126 | resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" 127 | 128 | chalk@^1.1.1: 129 | version "1.1.3" 130 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 131 | dependencies: 132 | ansi-styles "^2.2.1" 133 | escape-string-regexp "^1.0.2" 134 | has-ansi "^2.0.0" 135 | strip-ansi "^3.0.0" 136 | supports-color "^2.0.0" 137 | 138 | cluster-key-slot@^1.0.6: 139 | version "1.0.8" 140 | resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.0.8.tgz#7654556085a65330932a2e8b5976f8e2d0b3e414" 141 | 142 | cluster@0.7.7: 143 | version "0.7.7" 144 | resolved "https://registry.yarnpkg.com/cluster/-/cluster-0.7.7.tgz#e497e267cc956bd0b0513adb4aa393357d0085ef" 145 | dependencies: 146 | log ">= 1.2.0" 147 | mkdirp ">= 0.0.1" 148 | 149 | combined-stream@^1.0.5, combined-stream@~1.0.5: 150 | version "1.0.5" 151 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" 152 | dependencies: 153 | delayed-stream "~1.0.0" 154 | 155 | commander@2.9.0: 156 | version "2.9.0" 157 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" 158 | dependencies: 159 | graceful-readlink ">= 1.0.0" 160 | 161 | commander@^2.9.0: 162 | version "2.11.0" 163 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" 164 | 165 | component-emitter@^1.2.0: 166 | version "1.2.1" 167 | resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" 168 | 169 | concat-map@0.0.1: 170 | version "0.0.1" 171 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 172 | 173 | concat-stream@1.6.0: 174 | version "1.6.0" 175 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" 176 | dependencies: 177 | inherits "^2.0.3" 178 | readable-stream "^2.2.2" 179 | typedarray "^0.0.6" 180 | 181 | content-disposition@0.5.2: 182 | version "0.5.2" 183 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" 184 | 185 | content-type@~1.0.2: 186 | version "1.0.4" 187 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" 188 | 189 | cookie-signature@1.0.6: 190 | version "1.0.6" 191 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 192 | 193 | cookie@0.3.1: 194 | version "0.3.1" 195 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" 196 | 197 | cookiejar@^2.1.0: 198 | version "2.1.1" 199 | resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.1.tgz#41ad57b1b555951ec171412a81942b1e8200d34a" 200 | 201 | core-util-is@1.0.2, core-util-is@~1.0.0: 202 | version "1.0.2" 203 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 204 | 205 | cron-parser@^2.4.1: 206 | version "2.4.1" 207 | resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.4.1.tgz#022befce1af293e4d3144ff04c2cbd2edb491271" 208 | dependencies: 209 | is-nan "^1.2.1" 210 | moment-timezone "^0.5.0" 211 | 212 | cryptiles@2.x.x: 213 | version "2.0.5" 214 | resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" 215 | dependencies: 216 | boom "2.x.x" 217 | 218 | css-mediaquery@^0.1.2: 219 | version "0.1.2" 220 | resolved "https://registry.yarnpkg.com/css-mediaquery/-/css-mediaquery-0.1.2.tgz#6a2c37344928618631c54bd33cedd301da18bea0" 221 | 222 | css-tree@1.0.0-alpha.26: 223 | version "1.0.0-alpha.26" 224 | resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.26.tgz#690bee3458fb5b6b7000553983c8c30876da0b3e" 225 | dependencies: 226 | mdn-data "^1.0.0" 227 | source-map "^0.5.3" 228 | 229 | dashdash@^1.12.0: 230 | version "1.14.1" 231 | resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 232 | dependencies: 233 | assert-plus "^1.0.0" 234 | 235 | debug@2.2.0, debug@~2.2.0: 236 | version "2.2.0" 237 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" 238 | dependencies: 239 | ms "0.7.1" 240 | 241 | debug@2.6.0: 242 | version "2.6.0" 243 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b" 244 | dependencies: 245 | ms "0.7.2" 246 | 247 | debug@2.6.9, debug@^2.6.8: 248 | version "2.6.9" 249 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 250 | dependencies: 251 | ms "2.0.0" 252 | 253 | debug@^2.2.0, debug@^2.6.0: 254 | version "2.6.8" 255 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" 256 | dependencies: 257 | ms "2.0.0" 258 | 259 | debug@^3.1.0: 260 | version "3.1.0" 261 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 262 | dependencies: 263 | ms "2.0.0" 264 | 265 | debuglog@^1.0.0: 266 | version "1.0.1" 267 | resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" 268 | 269 | define-properties@^1.1.1: 270 | version "1.1.2" 271 | resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" 272 | dependencies: 273 | foreach "^2.0.5" 274 | object-keys "^1.0.8" 275 | 276 | delayed-stream@~1.0.0: 277 | version "1.0.0" 278 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 279 | 280 | denque@^1.1.0: 281 | version "1.2.2" 282 | resolved "https://registry.yarnpkg.com/denque/-/denque-1.2.2.tgz#e06cf7cf0da8badc88cbdaabf8fc0a70d659f1d4" 283 | 284 | depd@~1.1.0: 285 | version "1.1.1" 286 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" 287 | 288 | destroy@~1.0.4: 289 | version "1.0.4" 290 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" 291 | 292 | diff@1.4.0: 293 | version "1.4.0" 294 | resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" 295 | 296 | double-ended-queue@^2.1.0-0: 297 | version "2.1.0-0" 298 | resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" 299 | 300 | ecc-jsbn@~0.1.1: 301 | version "0.1.1" 302 | resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" 303 | dependencies: 304 | jsbn "~0.1.0" 305 | 306 | ee-first@1.1.1: 307 | version "1.1.1" 308 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 309 | 310 | encodeurl@~1.0.1: 311 | version "1.0.1" 312 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" 313 | 314 | es6-promise@^4.0.3: 315 | version "4.2.2" 316 | resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.2.tgz#f722d7769af88bd33bc13ec6605e1f92966b82d9" 317 | 318 | es6-promisify@^5.0.0: 319 | version "5.0.0" 320 | resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" 321 | dependencies: 322 | es6-promise "^4.0.3" 323 | 324 | escape-html@~1.0.3: 325 | version "1.0.3" 326 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 327 | 328 | escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2: 329 | version "1.0.5" 330 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 331 | 332 | etag@~1.7.0: 333 | version "1.7.0" 334 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" 335 | 336 | expect.js@0.3.1: 337 | version "0.3.1" 338 | resolved "https://registry.yarnpkg.com/expect.js/-/expect.js-0.3.1.tgz#b0a59a0d2eff5437544ebf0ceaa6015841d09b5b" 339 | 340 | express@4.14.1: 341 | version "4.14.1" 342 | resolved "https://registry.yarnpkg.com/express/-/express-4.14.1.tgz#646c237f766f148c2120aff073817b9e4d7e0d33" 343 | dependencies: 344 | accepts "~1.3.3" 345 | array-flatten "1.1.1" 346 | content-disposition "0.5.2" 347 | content-type "~1.0.2" 348 | cookie "0.3.1" 349 | cookie-signature "1.0.6" 350 | debug "~2.2.0" 351 | depd "~1.1.0" 352 | encodeurl "~1.0.1" 353 | escape-html "~1.0.3" 354 | etag "~1.7.0" 355 | finalhandler "0.5.1" 356 | fresh "0.3.0" 357 | merge-descriptors "1.0.1" 358 | methods "~1.1.2" 359 | on-finished "~2.3.0" 360 | parseurl "~1.3.1" 361 | path-to-regexp "0.1.7" 362 | proxy-addr "~1.1.3" 363 | qs "6.2.0" 364 | range-parser "~1.2.0" 365 | send "0.14.2" 366 | serve-static "~1.11.2" 367 | type-is "~1.6.14" 368 | utils-merge "1.0.0" 369 | vary "~1.1.0" 370 | 371 | extend@3.0.0: 372 | version "3.0.0" 373 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" 374 | 375 | extend@^3.0.0, extend@~3.0.0: 376 | version "3.0.1" 377 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" 378 | 379 | extract-zip@^1.6.5: 380 | version "1.6.6" 381 | resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c" 382 | dependencies: 383 | concat-stream "1.6.0" 384 | debug "2.6.9" 385 | mkdirp "0.5.0" 386 | yauzl "2.4.1" 387 | 388 | extsprintf@1.3.0, extsprintf@^1.2.0: 389 | version "1.3.0" 390 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" 391 | 392 | fd-slicer@~1.0.1: 393 | version "1.0.1" 394 | resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" 395 | dependencies: 396 | pend "~1.2.0" 397 | 398 | finalhandler@0.5.1: 399 | version "0.5.1" 400 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.5.1.tgz#2c400d8d4530935bc232549c5fa385ec07de6fcd" 401 | dependencies: 402 | debug "~2.2.0" 403 | escape-html "~1.0.3" 404 | on-finished "~2.3.0" 405 | statuses "~1.3.1" 406 | unpipe "~1.0.0" 407 | 408 | flexbuffer@0.0.6: 409 | version "0.0.6" 410 | resolved "https://registry.yarnpkg.com/flexbuffer/-/flexbuffer-0.0.6.tgz#039fdf23f8823e440c38f3277e6fef1174215b30" 411 | 412 | foreach@^2.0.5: 413 | version "2.0.5" 414 | resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" 415 | 416 | forever-agent@~0.6.1: 417 | version "0.6.1" 418 | resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" 419 | 420 | form-data@^2.1.1: 421 | version "2.3.1" 422 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" 423 | dependencies: 424 | asynckit "^0.4.0" 425 | combined-stream "^1.0.5" 426 | mime-types "^2.1.12" 427 | 428 | form-data@~2.1.1: 429 | version "2.1.4" 430 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" 431 | dependencies: 432 | asynckit "^0.4.0" 433 | combined-stream "^1.0.5" 434 | mime-types "^2.1.12" 435 | 436 | formidable@^1.1.1: 437 | version "1.1.1" 438 | resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.1.1.tgz#96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9" 439 | 440 | forwarded@~0.1.0: 441 | version "0.1.2" 442 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" 443 | 444 | fresh@0.3.0: 445 | version "0.3.0" 446 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" 447 | 448 | fs.realpath@^1.0.0: 449 | version "1.0.0" 450 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 451 | 452 | generate-function@^2.0.0: 453 | version "2.0.0" 454 | resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" 455 | 456 | generate-object-property@^1.1.0: 457 | version "1.2.0" 458 | resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" 459 | dependencies: 460 | is-property "^1.0.0" 461 | 462 | getpass@^0.1.1: 463 | version "0.1.7" 464 | resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" 465 | dependencies: 466 | assert-plus "^1.0.0" 467 | 468 | glob@7.0.5: 469 | version "7.0.5" 470 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" 471 | dependencies: 472 | fs.realpath "^1.0.0" 473 | inflight "^1.0.4" 474 | inherits "2" 475 | minimatch "^3.0.2" 476 | once "^1.3.0" 477 | path-is-absolute "^1.0.0" 478 | 479 | glob@^7.0.5: 480 | version "7.1.2" 481 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 482 | dependencies: 483 | fs.realpath "^1.0.0" 484 | inflight "^1.0.4" 485 | inherits "2" 486 | minimatch "^3.0.4" 487 | once "^1.3.0" 488 | path-is-absolute "^1.0.0" 489 | 490 | "graceful-readlink@>= 1.0.0": 491 | version "1.0.1" 492 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 493 | 494 | growl@1.9.2: 495 | version "1.9.2" 496 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" 497 | 498 | har-validator@~2.0.6: 499 | version "2.0.6" 500 | resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" 501 | dependencies: 502 | chalk "^1.1.1" 503 | commander "^2.9.0" 504 | is-my-json-valid "^2.12.4" 505 | pinkie-promise "^2.0.0" 506 | 507 | has-ansi@^2.0.0: 508 | version "2.0.0" 509 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 510 | dependencies: 511 | ansi-regex "^2.0.0" 512 | 513 | has-flag@^1.0.0: 514 | version "1.0.0" 515 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" 516 | 517 | hawk@~3.1.3: 518 | version "3.1.3" 519 | resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" 520 | dependencies: 521 | boom "2.x.x" 522 | cryptiles "2.x.x" 523 | hoek "2.x.x" 524 | sntp "1.x.x" 525 | 526 | hoek@2.x.x: 527 | version "2.16.3" 528 | resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" 529 | 530 | http-errors@~1.5.1: 531 | version "1.5.1" 532 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750" 533 | dependencies: 534 | inherits "2.0.3" 535 | setprototypeof "1.0.2" 536 | statuses ">= 1.3.1 < 2" 537 | 538 | http-signature@~1.1.0: 539 | version "1.1.1" 540 | resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" 541 | dependencies: 542 | assert-plus "^0.2.0" 543 | jsprim "^1.2.2" 544 | sshpk "^1.7.0" 545 | 546 | https-proxy-agent@^2.1.0: 547 | version "2.1.1" 548 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz#a7ce4382a1ba8266ee848578778122d491260fd9" 549 | dependencies: 550 | agent-base "^4.1.0" 551 | debug "^3.1.0" 552 | 553 | iconv-lite@0.4.15: 554 | version "0.4.15" 555 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" 556 | 557 | inflight@^1.0.4: 558 | version "1.0.6" 559 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 560 | dependencies: 561 | once "^1.3.0" 562 | wrappy "1" 563 | 564 | inherits@2, inherits@2.0.3, inherits@^2.0.3, inherits@~2.0.3: 565 | version "2.0.3" 566 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 567 | 568 | ioredis@^3.1.4: 569 | version "3.1.4" 570 | resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-3.1.4.tgz#8688293f5f2f1757e1c812ad17cce49f46d811bc" 571 | dependencies: 572 | bluebird "^3.3.4" 573 | cluster-key-slot "^1.0.6" 574 | debug "^2.2.0" 575 | denque "^1.1.0" 576 | flexbuffer "0.0.6" 577 | lodash.assign "^4.2.0" 578 | lodash.bind "^4.2.1" 579 | lodash.clone "^4.5.0" 580 | lodash.clonedeep "^4.5.0" 581 | lodash.defaults "^4.2.0" 582 | lodash.difference "^4.5.0" 583 | lodash.flatten "^4.4.0" 584 | lodash.foreach "^4.5.0" 585 | lodash.isempty "^4.4.0" 586 | lodash.keys "^4.2.0" 587 | lodash.noop "^3.0.1" 588 | lodash.partial "^4.2.1" 589 | lodash.pick "^4.4.0" 590 | lodash.sample "^4.2.1" 591 | lodash.shuffle "^4.2.0" 592 | lodash.values "^4.3.0" 593 | redis-commands "^1.2.0" 594 | redis-parser "^2.4.0" 595 | 596 | ipaddr.js@1.4.0: 597 | version "1.4.0" 598 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0" 599 | 600 | is-my-json-valid@^2.12.4: 601 | version "2.16.1" 602 | resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz#5a846777e2c2620d1e69104e5d3a03b1f6088f11" 603 | dependencies: 604 | generate-function "^2.0.0" 605 | generate-object-property "^1.1.0" 606 | jsonpointer "^4.0.0" 607 | xtend "^4.0.0" 608 | 609 | is-nan@^1.2.1: 610 | version "1.2.1" 611 | resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2" 612 | dependencies: 613 | define-properties "^1.1.1" 614 | 615 | is-property@^1.0.0: 616 | version "1.0.2" 617 | resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" 618 | 619 | is-typedarray@~1.0.0: 620 | version "1.0.0" 621 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 622 | 623 | isarray@~1.0.0: 624 | version "1.0.0" 625 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 626 | 627 | isstream@~0.1.2: 628 | version "0.1.2" 629 | resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 630 | 631 | jsbn@~0.1.0: 632 | version "0.1.1" 633 | resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" 634 | 635 | jsesc@^1.0.0: 636 | version "1.3.0" 637 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" 638 | 639 | json-schema@0.2.3: 640 | version "0.2.3" 641 | resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" 642 | 643 | json-stringify-safe@~5.0.1: 644 | version "5.0.1" 645 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 646 | 647 | json3@3.3.2: 648 | version "3.3.2" 649 | resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" 650 | 651 | jsonpointer@^4.0.0: 652 | version "4.0.1" 653 | resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" 654 | 655 | jsprim@^1.2.2: 656 | version "1.4.1" 657 | resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" 658 | dependencies: 659 | assert-plus "1.0.0" 660 | extsprintf "1.3.0" 661 | json-schema "0.2.3" 662 | verror "1.10.0" 663 | 664 | lodash._baseassign@^3.0.0: 665 | version "3.2.0" 666 | resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" 667 | dependencies: 668 | lodash._basecopy "^3.0.0" 669 | lodash.keys "^3.0.0" 670 | 671 | lodash._basecopy@^3.0.0: 672 | version "3.0.1" 673 | resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" 674 | 675 | lodash._basecreate@^3.0.0: 676 | version "3.0.3" 677 | resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" 678 | 679 | lodash._getnative@^3.0.0: 680 | version "3.9.1" 681 | resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" 682 | 683 | lodash._isiterateecall@^3.0.0: 684 | version "3.0.9" 685 | resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" 686 | 687 | lodash.assign@^4.2.0: 688 | version "4.2.0" 689 | resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" 690 | 691 | lodash.bind@^4.2.1: 692 | version "4.2.1" 693 | resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" 694 | 695 | lodash.clone@^4.5.0: 696 | version "4.5.0" 697 | resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" 698 | 699 | lodash.clonedeep@^4.5.0: 700 | version "4.5.0" 701 | resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" 702 | 703 | lodash.create@3.1.1: 704 | version "3.1.1" 705 | resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" 706 | dependencies: 707 | lodash._baseassign "^3.0.0" 708 | lodash._basecreate "^3.0.0" 709 | lodash._isiterateecall "^3.0.0" 710 | 711 | lodash.defaults@^4.2.0: 712 | version "4.2.0" 713 | resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" 714 | 715 | lodash.difference@^4.5.0: 716 | version "4.5.0" 717 | resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c" 718 | 719 | lodash.flatten@^4.4.0: 720 | version "4.4.0" 721 | resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" 722 | 723 | lodash.foreach@^4.5.0: 724 | version "4.5.0" 725 | resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" 726 | 727 | lodash.isarguments@^3.0.0: 728 | version "3.1.0" 729 | resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" 730 | 731 | lodash.isarray@^3.0.0: 732 | version "3.0.4" 733 | resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" 734 | 735 | lodash.isempty@^4.4.0: 736 | version "4.4.0" 737 | resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" 738 | 739 | lodash.keys@^3.0.0: 740 | version "3.1.2" 741 | resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" 742 | dependencies: 743 | lodash._getnative "^3.0.0" 744 | lodash.isarguments "^3.0.0" 745 | lodash.isarray "^3.0.0" 746 | 747 | lodash.keys@^4.2.0: 748 | version "4.2.0" 749 | resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205" 750 | 751 | lodash.noop@^3.0.1: 752 | version "3.0.1" 753 | resolved "https://registry.yarnpkg.com/lodash.noop/-/lodash.noop-3.0.1.tgz#38188f4d650a3a474258439b96ec45b32617133c" 754 | 755 | lodash.partial@^4.2.1: 756 | version "4.2.1" 757 | resolved "https://registry.yarnpkg.com/lodash.partial/-/lodash.partial-4.2.1.tgz#49f3d8cfdaa3bff8b3a91d127e923245418961d4" 758 | 759 | lodash.pick@^4.4.0: 760 | version "4.4.0" 761 | resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" 762 | 763 | lodash.sample@^4.2.1: 764 | version "4.2.1" 765 | resolved "https://registry.yarnpkg.com/lodash.sample/-/lodash.sample-4.2.1.tgz#5e4291b0c753fa1abeb0aab8fb29df1b66f07f6d" 766 | 767 | lodash.shuffle@^4.2.0: 768 | version "4.2.0" 769 | resolved "https://registry.yarnpkg.com/lodash.shuffle/-/lodash.shuffle-4.2.0.tgz#145b5053cf875f6f5c2a33f48b6e9948c6ec7b4b" 770 | 771 | lodash.values@^4.3.0: 772 | version "4.3.0" 773 | resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347" 774 | 775 | lodash@^4.17.4: 776 | version "4.17.4" 777 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 778 | 779 | "log@>= 1.2.0": 780 | version "1.4.0" 781 | resolved "https://registry.yarnpkg.com/log/-/log-1.4.0.tgz#4ba1d890fde249b031dca03bc37eaaf325656f1c" 782 | 783 | mdn-data@^1.0.0: 784 | version "1.0.0" 785 | resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.0.0.tgz#a69d9da76847b4d5834c1465ea25c0653a1fbf66" 786 | 787 | media-typer@0.3.0: 788 | version "0.3.0" 789 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 790 | 791 | merge-descriptors@1.0.1: 792 | version "1.0.1" 793 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 794 | 795 | methods@^1.1.1, methods@~1.1.2: 796 | version "1.1.2" 797 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 798 | 799 | mime-db@~1.30.0: 800 | version "1.30.0" 801 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" 802 | 803 | mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.7: 804 | version "2.1.17" 805 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" 806 | dependencies: 807 | mime-db "~1.30.0" 808 | 809 | mime@1.3.4: 810 | version "1.3.4" 811 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" 812 | 813 | mime@^1.3.4: 814 | version "1.6.0" 815 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 816 | 817 | mime@^1.3.6: 818 | version "1.4.0" 819 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.0.tgz#69e9e0db51d44f2a3b56e48b7817d7d137f1a343" 820 | 821 | minimatch@^3.0.2, minimatch@^3.0.4: 822 | version "3.0.4" 823 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 824 | dependencies: 825 | brace-expansion "^1.1.7" 826 | 827 | minimist@0.0.8: 828 | version "0.0.8" 829 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 830 | 831 | mkdirp@0.5.0: 832 | version "0.5.0" 833 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" 834 | dependencies: 835 | minimist "0.0.8" 836 | 837 | mkdirp@0.5.1, "mkdirp@>= 0.0.1": 838 | version "0.5.1" 839 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 840 | dependencies: 841 | minimist "0.0.8" 842 | 843 | mocha@3.2.0: 844 | version "3.2.0" 845 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.2.0.tgz#7dc4f45e5088075171a68896814e6ae9eb7a85e3" 846 | dependencies: 847 | browser-stdout "1.3.0" 848 | commander "2.9.0" 849 | debug "2.2.0" 850 | diff "1.4.0" 851 | escape-string-regexp "1.0.5" 852 | glob "7.0.5" 853 | growl "1.9.2" 854 | json3 "3.3.2" 855 | lodash.create "3.1.1" 856 | mkdirp "0.5.1" 857 | supports-color "3.1.2" 858 | 859 | moment-timezone@^0.5.0: 860 | version "0.5.13" 861 | resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.13.tgz#99ce5c7d827262eb0f1f702044177f60745d7b90" 862 | dependencies: 863 | moment ">= 2.9.0" 864 | 865 | "moment@>= 2.9.0": 866 | version "2.18.1" 867 | resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" 868 | 869 | ms@0.7.1: 870 | version "0.7.1" 871 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" 872 | 873 | ms@0.7.2: 874 | version "0.7.2" 875 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" 876 | 877 | ms@2.0.0: 878 | version "2.0.0" 879 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 880 | 881 | negotiator@0.6.1: 882 | version "0.6.1" 883 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" 884 | 885 | oauth-sign@~0.8.1: 886 | version "0.8.2" 887 | resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" 888 | 889 | object-keys@^1.0.8: 890 | version "1.0.11" 891 | resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" 892 | 893 | on-finished@~2.3.0: 894 | version "2.3.0" 895 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 896 | dependencies: 897 | ee-first "1.1.1" 898 | 899 | once@^1.3.0: 900 | version "1.4.0" 901 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 902 | dependencies: 903 | wrappy "1" 904 | 905 | parseurl@~1.3.1: 906 | version "1.3.2" 907 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" 908 | 909 | path-is-absolute@^1.0.0: 910 | version "1.0.1" 911 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 912 | 913 | path-to-regexp@0.1.7: 914 | version "0.1.7" 915 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 916 | 917 | pend@~1.2.0: 918 | version "1.2.0" 919 | resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" 920 | 921 | penthouse@1.3.0: 922 | version "1.3.0" 923 | resolved "https://registry.yarnpkg.com/penthouse/-/penthouse-1.3.0.tgz#979f1670a7cc58a257b8ae36bee7a2ee6fbc32cd" 924 | dependencies: 925 | css-mediaquery "^0.1.2" 926 | css-tree "1.0.0-alpha.26" 927 | debug "^3.1.0" 928 | jsesc "^1.0.0" 929 | puppeteer "0.12" 930 | 931 | pinkie-promise@^2.0.0: 932 | version "2.0.1" 933 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 934 | dependencies: 935 | pinkie "^2.0.0" 936 | 937 | pinkie@^2.0.0: 938 | version "2.0.4" 939 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 940 | 941 | prettier@1.6.1: 942 | version "1.6.1" 943 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.6.1.tgz#850f411a3116226193e32ea5acfc21c0f9a76d7d" 944 | 945 | process-nextick-args@~1.0.6: 946 | version "1.0.7" 947 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" 948 | 949 | progress@^2.0.0: 950 | version "2.0.0" 951 | resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" 952 | 953 | proxy-addr@~1.1.3: 954 | version "1.1.5" 955 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918" 956 | dependencies: 957 | forwarded "~0.1.0" 958 | ipaddr.js "1.4.0" 959 | 960 | proxy-from-env@^1.0.0: 961 | version "1.0.0" 962 | resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" 963 | 964 | punycode@^1.4.1: 965 | version "1.4.1" 966 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" 967 | 968 | puppeteer@0.12: 969 | version "0.12.0" 970 | resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-0.12.0.tgz#9c421930851594dfdd479d07646666a74ced7719" 971 | dependencies: 972 | debug "^2.6.8" 973 | extract-zip "^1.6.5" 974 | https-proxy-agent "^2.1.0" 975 | mime "^1.3.4" 976 | progress "^2.0.0" 977 | proxy-from-env "^1.0.0" 978 | rimraf "^2.6.1" 979 | ws "^3.0.0" 980 | 981 | qs@6.2.0: 982 | version "6.2.0" 983 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.0.tgz#3b7848c03c2dece69a9522b0fae8c4126d745f3b" 984 | 985 | qs@6.2.1: 986 | version "6.2.1" 987 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.1.tgz#ce03c5ff0935bc1d9d69a9f14cbd18e568d67625" 988 | 989 | qs@^6.4.0: 990 | version "6.5.1" 991 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" 992 | 993 | qs@~6.3.0: 994 | version "6.3.2" 995 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" 996 | 997 | range-parser@~1.2.0: 998 | version "1.2.0" 999 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" 1000 | 1001 | raw-body@~2.2.0: 1002 | version "2.2.0" 1003 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.2.0.tgz#994976cf6a5096a41162840492f0bdc5d6e7fb96" 1004 | dependencies: 1005 | bytes "2.4.0" 1006 | iconv-lite "0.4.15" 1007 | unpipe "1.0.0" 1008 | 1009 | readable-stream@^2.0.5, readable-stream@^2.2.2: 1010 | version "2.3.3" 1011 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" 1012 | dependencies: 1013 | core-util-is "~1.0.0" 1014 | inherits "~2.0.3" 1015 | isarray "~1.0.0" 1016 | process-nextick-args "~1.0.6" 1017 | safe-buffer "~5.1.1" 1018 | string_decoder "~1.0.3" 1019 | util-deprecate "~1.0.1" 1020 | 1021 | redis-commands@^1.2.0: 1022 | version "1.3.1" 1023 | resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.3.1.tgz#81d826f45fa9c8b2011f4cd7a0fe597d241d442b" 1024 | 1025 | redis-mock@0.16.0: 1026 | version "0.16.0" 1027 | resolved "https://registry.yarnpkg.com/redis-mock/-/redis-mock-0.16.0.tgz#a839e7869c5cf9abab8ce08044327d8c0bd3aaba" 1028 | dependencies: 1029 | redis "^2.6.2" 1030 | 1031 | redis-parser@^2.0.0, redis-parser@^2.4.0, redis-parser@^2.6.0: 1032 | version "2.6.0" 1033 | resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-2.6.0.tgz#52ed09dacac108f1a631c07e9b69941e7a19504b" 1034 | 1035 | redis-url@1.2.1: 1036 | version "1.2.1" 1037 | resolved "https://registry.yarnpkg.com/redis-url/-/redis-url-1.2.1.tgz#18670095a38e989d379359dd4c6e4abff85e2eb1" 1038 | dependencies: 1039 | redis ">= 0.0.1" 1040 | 1041 | redis@2.6.5: 1042 | version "2.6.5" 1043 | resolved "https://registry.yarnpkg.com/redis/-/redis-2.6.5.tgz#87c1eff4a489f94b70871f3d08b6988f23a95687" 1044 | dependencies: 1045 | double-ended-queue "^2.1.0-0" 1046 | redis-commands "^1.2.0" 1047 | redis-parser "^2.0.0" 1048 | 1049 | "redis@>= 0.0.1", redis@^2.6.2: 1050 | version "2.8.0" 1051 | resolved "https://registry.yarnpkg.com/redis/-/redis-2.8.0.tgz#202288e3f58c49f6079d97af7a10e1303ae14b02" 1052 | dependencies: 1053 | double-ended-queue "^2.1.0-0" 1054 | redis-commands "^1.2.0" 1055 | redis-parser "^2.6.0" 1056 | 1057 | request@2.79.0: 1058 | version "2.79.0" 1059 | resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" 1060 | dependencies: 1061 | aws-sign2 "~0.6.0" 1062 | aws4 "^1.2.1" 1063 | caseless "~0.11.0" 1064 | combined-stream "~1.0.5" 1065 | extend "~3.0.0" 1066 | forever-agent "~0.6.1" 1067 | form-data "~2.1.1" 1068 | har-validator "~2.0.6" 1069 | hawk "~3.1.3" 1070 | http-signature "~1.1.0" 1071 | is-typedarray "~1.0.0" 1072 | isstream "~0.1.2" 1073 | json-stringify-safe "~5.0.1" 1074 | mime-types "~2.1.7" 1075 | oauth-sign "~0.8.1" 1076 | qs "~6.3.0" 1077 | stringstream "~0.0.4" 1078 | tough-cookie "~2.3.0" 1079 | tunnel-agent "~0.4.1" 1080 | uuid "^3.0.0" 1081 | 1082 | rimraf@^2.6.1: 1083 | version "2.6.2" 1084 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" 1085 | dependencies: 1086 | glob "^7.0.5" 1087 | 1088 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 1089 | version "5.1.1" 1090 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" 1091 | 1092 | semver@^5.4.1: 1093 | version "5.4.1" 1094 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" 1095 | 1096 | send@0.14.2: 1097 | version "0.14.2" 1098 | resolved "https://registry.yarnpkg.com/send/-/send-0.14.2.tgz#39b0438b3f510be5dc6f667a11f71689368cdeef" 1099 | dependencies: 1100 | debug "~2.2.0" 1101 | depd "~1.1.0" 1102 | destroy "~1.0.4" 1103 | encodeurl "~1.0.1" 1104 | escape-html "~1.0.3" 1105 | etag "~1.7.0" 1106 | fresh "0.3.0" 1107 | http-errors "~1.5.1" 1108 | mime "1.3.4" 1109 | ms "0.7.2" 1110 | on-finished "~2.3.0" 1111 | range-parser "~1.2.0" 1112 | statuses "~1.3.1" 1113 | 1114 | serve-static@~1.11.2: 1115 | version "1.11.2" 1116 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.11.2.tgz#2cf9889bd4435a320cc36895c9aa57bd662e6ac7" 1117 | dependencies: 1118 | encodeurl "~1.0.1" 1119 | escape-html "~1.0.3" 1120 | parseurl "~1.3.1" 1121 | send "0.14.2" 1122 | 1123 | setprototypeof@1.0.2: 1124 | version "1.0.2" 1125 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08" 1126 | 1127 | simple-mock@0.7.3: 1128 | version "0.7.3" 1129 | resolved "https://registry.yarnpkg.com/simple-mock/-/simple-mock-0.7.3.tgz#461c9e6f1c339cc49a7871b390676cd064388036" 1130 | 1131 | sntp@1.x.x: 1132 | version "1.0.9" 1133 | resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" 1134 | dependencies: 1135 | hoek "2.x.x" 1136 | 1137 | source-map@^0.5.3: 1138 | version "0.5.7" 1139 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 1140 | 1141 | sshpk@^1.7.0: 1142 | version "1.13.1" 1143 | resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" 1144 | dependencies: 1145 | asn1 "~0.2.3" 1146 | assert-plus "^1.0.0" 1147 | dashdash "^1.12.0" 1148 | getpass "^0.1.1" 1149 | optionalDependencies: 1150 | bcrypt-pbkdf "^1.0.0" 1151 | ecc-jsbn "~0.1.1" 1152 | jsbn "~0.1.0" 1153 | tweetnacl "~0.14.0" 1154 | 1155 | "statuses@>= 1.3.1 < 2", statuses@~1.3.1: 1156 | version "1.3.1" 1157 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" 1158 | 1159 | string_decoder@~1.0.3: 1160 | version "1.0.3" 1161 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" 1162 | dependencies: 1163 | safe-buffer "~5.1.0" 1164 | 1165 | stringstream@~0.0.4: 1166 | version "0.0.5" 1167 | resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" 1168 | 1169 | strip-ansi@^3.0.0: 1170 | version "3.0.1" 1171 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 1172 | dependencies: 1173 | ansi-regex "^2.0.0" 1174 | 1175 | superagent@^3.0.0: 1176 | version "3.6.0" 1177 | resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.6.0.tgz#eb679651057c3462199c7b902b696c25350e1b87" 1178 | dependencies: 1179 | component-emitter "^1.2.0" 1180 | cookiejar "^2.1.0" 1181 | debug "^2.6.0" 1182 | extend "^3.0.0" 1183 | form-data "^2.1.1" 1184 | formidable "^1.1.1" 1185 | methods "^1.1.1" 1186 | mime "^1.3.6" 1187 | qs "^6.4.0" 1188 | readable-stream "^2.0.5" 1189 | 1190 | supertest@3.0.0: 1191 | version "3.0.0" 1192 | resolved "https://registry.yarnpkg.com/supertest/-/supertest-3.0.0.tgz#8d4bb68fd1830ee07033b1c5a5a9a4021c965296" 1193 | dependencies: 1194 | methods "~1.1.2" 1195 | superagent "^3.0.0" 1196 | 1197 | supports-color@3.1.2: 1198 | version "3.1.2" 1199 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" 1200 | dependencies: 1201 | has-flag "^1.0.0" 1202 | 1203 | supports-color@^2.0.0: 1204 | version "2.0.0" 1205 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 1206 | 1207 | tough-cookie@~2.3.0: 1208 | version "2.3.2" 1209 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" 1210 | dependencies: 1211 | punycode "^1.4.1" 1212 | 1213 | tunnel-agent@~0.4.1: 1214 | version "0.4.3" 1215 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" 1216 | 1217 | tweetnacl@^0.14.3, tweetnacl@~0.14.0: 1218 | version "0.14.5" 1219 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 1220 | 1221 | type-is@~1.6.14: 1222 | version "1.6.15" 1223 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" 1224 | dependencies: 1225 | media-typer "0.3.0" 1226 | mime-types "~2.1.15" 1227 | 1228 | typedarray@^0.0.6: 1229 | version "0.0.6" 1230 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 1231 | 1232 | ultron@~1.1.0: 1233 | version "1.1.1" 1234 | resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" 1235 | 1236 | unpipe@1.0.0, unpipe@~1.0.0: 1237 | version "1.0.0" 1238 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 1239 | 1240 | util-deprecate@~1.0.1: 1241 | version "1.0.2" 1242 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1243 | 1244 | utils-merge@1.0.0: 1245 | version "1.0.0" 1246 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" 1247 | 1248 | uuid@^3.0.0, uuid@^3.1.0: 1249 | version "3.1.0" 1250 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" 1251 | 1252 | vary@~1.1.0: 1253 | version "1.1.1" 1254 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37" 1255 | 1256 | verror@1.10.0: 1257 | version "1.10.0" 1258 | resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" 1259 | dependencies: 1260 | assert-plus "^1.0.0" 1261 | core-util-is "1.0.2" 1262 | extsprintf "^1.2.0" 1263 | 1264 | wrappy@1: 1265 | version "1.0.2" 1266 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1267 | 1268 | ws@^3.0.0: 1269 | version "3.3.3" 1270 | resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" 1271 | dependencies: 1272 | async-limiter "~1.0.0" 1273 | safe-buffer "~5.1.0" 1274 | ultron "~1.1.0" 1275 | 1276 | xtend@^4.0.0: 1277 | version "4.0.1" 1278 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" 1279 | 1280 | yarn@1.0.2: 1281 | version "1.0.2" 1282 | resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.0.2.tgz#d1b8f4b6d3b0684e86f63a072ac630995b8b7b0a" 1283 | 1284 | yauzl@2.4.1: 1285 | version "2.4.1" 1286 | resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" 1287 | dependencies: 1288 | fd-slicer "~1.0.1" 1289 | --------------------------------------------------------------------------------