diff --git a/.editorconfig b/.editorconfig index d95fdc7..f8e5970 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,11 +11,19 @@ max_line_length = 80 insert_final_newline = true trim_trailing_whitespace = true -# JS -[{*.js}] +# HTML +[*.html] +max_line_length = 120 + +# JS/JSON +[*.{js,json}] quote_type = single curly_bracket_next_line = false spaces_around_operators = true space_after_control_statements = true space_after_anonymous_functions = false spaces_in_brackets = false + +# YAML +[*.yaml] +trim_trailing_whitespace = false diff --git a/.eslintrc.yaml b/.eslintrc.yaml index db9664c..645e201 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -122,6 +122,10 @@ rules: no-multiple-empty-lines: - error - max: 1 + no-global-assign: + - error + - exceptions: + - Promise eol-last: error dot-notation: error space-infix-ops: error @@ -135,6 +139,7 @@ rules: no-mixed-spaces-and-tabs: error no-spaced-func: error no-whitespace-before-property: error + no-unsafe-negation: error no-lonely-if: error no-var: error no-console: off diff --git a/.npmrc b/.npmrc index a399520..b0ee90c 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ -message = "[bump] server@%s" +message = "%s" +git-tag-version = false diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 4dfd132..0000000 --- a/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -# Extend base Dockerfile -FROM gcr.io/google_appengine/nodejs - -# Install node -RUN /usr/local/bin/install_node '>=6.3.0' - -# Copy app -COPY . /app/ - -# Install node packages -RUN npm install --production --unsafe-perm - -# Start app -CMD npm start diff --git a/LICENSE.md b/LICENSE.md index f7894f2..65e4cc1 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -2,7 +2,7 @@ The MIT License (MIT) -Copyright (c) 2016 Adam Buczynski +Copyright (c) 2016 Adam Reis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..61b10f2 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: node scripts/server.js diff --git a/README.md b/README.md index 73c8d68..1e2354d 100644 --- a/README.md +++ b/README.md @@ -97,4 +97,4 @@ Pull requests are welcome! If you would like to contribute to Meanie, please che (MIT License) -Copyright 2015-2016, [Adam Buczynski](http://adambuczynski.com) +Copyright 2015-2017, [Adam Reis](http://adam.reis.nz) diff --git a/app.yaml b/app.yaml deleted file mode 100644 index 61c2c4a..0000000 --- a/app.yaml +++ /dev/null @@ -1,9 +0,0 @@ -runtime: custom -vm: true - -skip_files: - - ^(.*/)?.*/node_modules/.*$ - - ^(.*/)?.*/coverage/.*$ - - ^(.*/)?.*/migrations/.*$ - - ^(.*/)?.*/test/.*$ - - ^(.*/)?.*/config/local\.js$ diff --git a/app/app.js b/app/app.js index 9cbedc0..02db89a 100644 --- a/app/app.js +++ b/app/app.js @@ -3,25 +3,26 @@ /** * Dependencies */ -let path = require('path'); -let i18n = require('i18n'); -let cors = require('cors'); -let morgan = require('morgan'); -let express = require('express'); -let bodyParser = require('body-parser'); -let compression = require('compression'); -let serveStatic = require('serve-static'); -let cookieParser = require('cookie-parser'); -let errors = require('meanie-express-error-handling'); -let jwt = require('meanie-express-jwt-service'); -let router = require('./services/router'); -let db = require('./services/db'); -let auth = require('./services/auth'); -let config = require('./config'); +const i18n = require('i18n'); +const cors = require('cors'); +const morgan = require('morgan'); +const express = require('express'); +const bodyParser = require('body-parser'); +const compression = require('compression'); +const cookieParser = require('cookie-parser'); +const errors = require('meanie-express-error-handling'); +const raven = require('meanie-express-raven-service'); +const jwt = require('meanie-express-jwt-service'); +const router = require('./services/router'); +const db = require('./services/db'); +const auth = require('./services/auth'); +const config = require('./config'); /** * Configuration */ +const ENV = config.ENV; +const APP_VERSION = config.APP_VERSION; const CORS_ORIGINS = config.CORS_ORIGINS; const I18N_LOCALES = config.I18N_LOCALES; const I18N_DEFAULT_LOCALE = config.I18N_DEFAULT_LOCALE; @@ -31,8 +32,20 @@ const TOKEN_DEFAULT_AUDIENCE = config.TOKEN_DEFAULT_AUDIENCE; const SERVER_LATENCY = config.SERVER_LATENCY; const SERVER_LATENCY_MIN = config.SERVER_LATENCY_MIN; const SERVER_LATENCY_MAX = config.SERVER_LATENCY_MAX; +const SENTRY_DSN = config.SENTRY_DSN; +const SENTRY_CONFIG = config.SENTRY_CONFIG; const ERROR_MIDDLEWARE = config.ERROR_MIDDLEWARE; +//Increase stack trace limit for non production environments +if (ENV !== 'production') { + Error.stackTraceLimit = Infinity; +} + +//Use sentry +if (SENTRY_DSN) { + raven(SENTRY_DSN, SENTRY_CONFIG); +} + //Configure i18n i18n.configure({ directory: 'app/locales', @@ -96,10 +109,6 @@ module.exports = function() { //Use i18n app.use(i18n.init); - //Set static folders - app.use(serveStatic(path.resolve('./public'))); - app.use(serveStatic(path.resolve('./data'))); - //Simulate latency if (SERVER_LATENCY) { let latency = require('express-simulate-latency')({ @@ -112,12 +121,18 @@ module.exports = function() { //Load authentication auth(app); + //Set global headers + app.all('/*', (req, res, next) => { + res.header('X-Version', APP_VERSION); + next(); + }); + //Load router router(app); //Create error handling middleware stack errors - .middleware(ERROR_MIDDLEWARE.concat(['auth-clear-cookie', 'send'])) + .middleware(ERROR_MIDDLEWARE.concat(['send'])) .forEach(handler => app.use(handler)); //Return express server instance diff --git a/app/components/auth/auth.ctrl.js b/app/components/auth/auth.ctrl.js index 4bc0df2..b8a3650 100644 --- a/app/components/auth/auth.ctrl.js +++ b/app/components/auth/auth.ctrl.js @@ -3,38 +3,17 @@ /** * Dependencies */ -let passport = require('passport'); -let moment = require('moment'); -let jwt = require('meanie-express-jwt-service'); -let errors = require('meanie-express-error-handling'); -let NotAuthenticatedError = errors.NotAuthenticatedError; -let NotAuthorizedError = errors.NotAuthorizedError; -let UserSuspendedError = errors.UserSuspendedError; -let UserPendingError = errors.UserPendingError; - -/** - * To camel case - */ -function toCamelCase(str, ucfirst) { - if (typeof str === 'number') { - return String(str); - } - else if (typeof str !== 'string') { - return ''; - } - if ((str = String(str).trim()) === '') { - return ''; - } - return str - .replace(/_+|\-+/g, ' ') - .replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, (match, index) => { - if (Number(match) === 0) { - return ''; - } - return (index === 0 && !ucfirst) ? - match.toLowerCase() : match.toUpperCase(); - }); -} +const passport = require('passport'); +const moment = require('moment'); +const mongoose = require('mongoose'); +const jwt = require('meanie-express-jwt-service'); +const errors = require('meanie-express-error-handling'); +const ObjectId = mongoose.Types.ObjectId; +const ServerError = errors.ServerError; +const NotAuthenticatedError = errors.NotAuthenticatedError; +const NotAuthorizedError = errors.NotAuthorizedError; +const UserSuspendedError = errors.UserSuspendedError; +const toCamelCase = require('../../helpers/transform/to-camel-case'); /** * Auth controller @@ -52,9 +31,8 @@ module.exports = { * Forget a user */ forget(req, res) { - const COOKIE_SECURE = req.app.locals.REFRESH_TOKEN_COOKIE_SECURE; res.clearCookie('refreshToken', { - secure: COOKIE_SECURE, + secure: req.secure, httpOnly: true, }); res.end(); @@ -66,9 +44,9 @@ module.exports = { token(req, res, next) { //Get grant type and initialize access token - let grantType = toCamelCase(req.body.grantType); - let remember = !!req.body.remember; - let secureStatus = !!req.body.secureStatus; + const grantType = toCamelCase(req.body.grantType); + const remember = !!req.body.remember; + const secureStatus = !!req.body.secureStatus; /** * Callback handler @@ -77,32 +55,22 @@ module.exports = { //Error given? if (error) { - error = new NotAuthenticatedError(error); + return next(new NotAuthenticatedError(error)); } //No user found? - else if (!user) { - error = new NotAuthenticatedError(); + if (!user) { + return next(new NotAuthenticatedError()); } //User suspended? - else if (user.isSuspended) { - error = new UserSuspendedError(); - } - - //User pending approval? - else if (user.isPending) { - error = new UserPendingError(); - } - - //Check error - if (error) { - return next(error); + if (user.isSuspended) { + return next(new UserSuspendedError()); } //Set user in request and get claims req.me = user; - let claims = user.getClaims(); + const claims = user.getClaims(); //Requesting secure status? if (secureStatus && grantType === 'password') { @@ -113,20 +81,19 @@ module.exports = { } //Generate access token - let accessToken = jwt.generate('access', claims); + const accessToken = jwt.generate('access', claims); //Generate refresh token if we want to be remembered if (remember) { //Get locals const COOKIE_MAX_AGE = req.app.locals.REFRESH_TOKEN_COOKIE_MAX_AGE; - const COOKIE_SECURE = req.app.locals.REFRESH_TOKEN_COOKIE_SECURE; //Create refresh token and set cookie - let refreshToken = jwt.generate('refresh', user.getClaims()); + const refreshToken = jwt.generate('refresh', user.getClaims()); res.cookie('refreshToken', refreshToken, { maxAge: COOKIE_MAX_AGE * 1000, //in ms - secure: COOKIE_SECURE, + secure: req.secure, httpOnly: true, }); } @@ -137,6 +104,9 @@ module.exports = { //Handle specific grant types switch (grantType) { + case 'bearer': + passport.authenticate('bearer', authCallback)(req, res, next); + break; case 'password': passport.authenticate('local', authCallback)(req, res, next); break; @@ -151,71 +121,109 @@ module.exports = { ***/ /** - * Ensure a user is an admin + * Ensure a user is authenticated and has specific roles */ - ensureAdmin(req, res, next) { - if (!req.me || !req.me.hasRole('admin')) { - return next(new NotAuthorizedError()); - } - next(); + ensureAuthenticated(...roles) { + return function(req, res, next) { + + //Get user + const user = req.me; + + //No user present? + if (!user) { + return next(new NotAuthenticatedError()); + } + + //User suspended? + if (user.isSuspended) { + return next(new UserSuspendedError()); + } + + //Check roles + if (roles.length && !roles.some(role => user.hasRole(role))) { + return next(new NotAuthorizedError()); + } + + //All good + next(); + }; }, /** - * Ensure a user is authenticated + * Belongs to check */ - ensureAuthenticated(req, res, next) { + belongsTo(itemKey, ownerKey, propKey, roles) { - //Authenticate now - passport.authenticate('bearer', { - session: false, - }, (error, user) => { + //Array given as prop key, assume roles + if (Array.isArray(propKey)) { + roles = propKey; + propKey = undefined; + } - //Error given? - if (error) { - error = new NotAuthenticatedError(error); + //Guess prop key if not given + if (typeof propKey === 'undefined') { + switch (ownerKey) { + case 'me': + propKey = 'user'; + break; } + } - //No user found? - else if (!user) { - error = new NotAuthenticatedError(); + //Still no prop key? + if (!propKey) { + throw new Error('Missing prop key and unknown owner key'); + } + + //Return middleware + return function(req, res, next) { + + //Get data + const user = req.me; + const owner = req[ownerKey]; + const item = req[itemKey]; + + //Check roles if given + if (Array.isArray(roles) && roles.some(role => user.hasRole(role))) { + return next(); } - //User suspended? - else if (user.isSuspended) { - error = new UserSuspendedError(); + //Must have owner + if (typeof owner === 'undefined') { + return next(new ServerError( + `Owner of type ${ownerKey} has not been loaded` + )); } - //User pending approval? - else if (user.isPending) { - error = new UserPendingError(); + //Must have item + if (typeof item === 'undefined') { + return next(new ServerError( + `Item of type ${itemKey} has not been loaded` + )); } - //Check error - if (error) { - return next(error); + //Must have prop key + if (typeof item[propKey] === 'undefined') { + return next(new ServerError( + `Item of type ${itemKey} has no ${propKey} property` + )); } - //Set user in request - req.me = user; - next(); - })(req, res, next); - }, + //Get ID + const prop = item[propKey]; + let _id = prop; - /** - * Check if a user is authenticated (doesn't throw errors if isn't) - * Use this if authentication is optional for a route but you - * need the authenticated user object if they are authenticated. - */ - checkAuthenticated(req, res, next) { - - //Authenticate now - passport.authenticate('bearer', { - session: false, - }, (error, user) => { - if (user) { - req.me = user; + //If it's a populated object, check ID + if (typeof prop === 'object' && prop._id instanceof ObjectId) { + _id = prop._id; } + + //Compare + if (!owner._id.equals(_id)) { + return next(new NotAuthorizedError()); + } + + //All good next(); - })(req, res, next); + }; }, }; diff --git a/app/components/auth/auth.routes.js b/app/components/auth/auth.routes.js index 25913d1..eed2e81 100644 --- a/app/components/auth/auth.routes.js +++ b/app/components/auth/auth.routes.js @@ -3,24 +3,38 @@ /** * Dependencies */ -let express = require('express'); +const express = require('express'); +const authCtrl = require('./auth.ctrl'); /** * Auth routes */ module.exports = function(app) { - //Get controllers and middleware - let authCtrl = require('./auth.ctrl'); - let ensureAuthenticated = authCtrl.ensureAuthenticated; + //Extract middleware + const {ensureAuthenticated} = authCtrl; //Create new router - let router = express.Router(); + const router = express.Router(); - //Define routes - router.get('/verify', ensureAuthenticated, authCtrl.verify); - router.get('/forget', authCtrl.forget); - router.post('/token', authCtrl.token); + //Verify authentication + router.get( + '/verify', + ensureAuthenticated(), + authCtrl.verify + ); + + //Forget any refresh tokens + router.get( + '/forget', + authCtrl.forget + ); + + //Obtain access token + router.post( + '/token', + authCtrl.token + ); //Register router app.use('/auth', router); diff --git a/app/components/auth/strategies/bearer.js b/app/components/auth/strategies/bearer.js index 96010cf..f0a07c9 100644 --- a/app/components/auth/strategies/bearer.js +++ b/app/components/auth/strategies/bearer.js @@ -3,11 +3,11 @@ /** * Dependencies */ -let passport = require('passport'); -let BearerStrategy = require('passport-http-bearer').Strategy; -let jwt = require('meanie-express-jwt-service'); -let InvalidTokenError = jwt.InvalidTokenError; -let User = require('../../user/user.service'); +const passport = require('passport'); +const BearerStrategy = require('passport-http-bearer').Strategy; +const jwt = require('meanie-express-jwt-service'); +const InvalidTokenError = jwt.InvalidTokenError; +const User = require('../../user/user.service'); /** * Bearer strategy diff --git a/app/components/auth/strategies/local.js b/app/components/auth/strategies/local.js index 1e98a12..4d8a4fb 100644 --- a/app/components/auth/strategies/local.js +++ b/app/components/auth/strategies/local.js @@ -3,22 +3,22 @@ /** * Dependencies */ -let passport = require('passport'); -let LocalStrategy = require('passport-local').Strategy; -let User = require('../../user/user.service'); +const passport = require('passport'); +const LocalStrategy = require('passport-local').Strategy; +const User = require('../../user/user.service'); /** * Local strategy */ module.exports = function() { passport.use(new LocalStrategy({ - usernameField: 'email', + usernameField: 'username', passwordField: 'password', passReqToCallback: true, - }, (req, email, password, cb) => { + }, (req, username, password, cb) => { - //Find user by email - User.findByEmailAndPassword(req, email, password) + //Find user by username + User.findByUsernameAndPassword(req, username, password) .then(user => { if (!user) { return cb(null, false); diff --git a/app/components/auth/strategies/refresh.js b/app/components/auth/strategies/refresh.js index 32b6989..c81b1d3 100644 --- a/app/components/auth/strategies/refresh.js +++ b/app/components/auth/strategies/refresh.js @@ -3,11 +3,11 @@ /** * Dependencies */ -let passport = require('passport'); -let RefreshStrategy = require('meanie-passport-refresh-strategy'); -let jwt = require('meanie-express-jwt-service'); -let InvalidTokenError = jwt.InvalidTokenError; -let User = require('../../user/user.service'); +const passport = require('passport'); +const RefreshStrategy = require('meanie-passport-refresh-strategy'); +const jwt = require('meanie-express-jwt-service'); +const InvalidTokenError = jwt.InvalidTokenError; +const User = require('../../user/user.service'); /** * Refresh token strategy diff --git a/app/components/auth/used-token.model.js b/app/components/auth/used-token.model.js new file mode 100644 index 0000000..4528b3f --- /dev/null +++ b/app/components/auth/used-token.model.js @@ -0,0 +1,25 @@ +'use strict'; + +/** + * Dependencies + */ +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; + +/** + * Used token schema + */ +const UsedTokenSchema = new Schema({ + jti: { + type: Schema.Types.ObjectId, + required: true, + }, +}); + +//Index for JTI +UsedTokenSchema.index({jti: 1}); + +/** + * Define model + */ +mongoose.model('UsedToken', UsedTokenSchema); diff --git a/app/components/error/error.ctrl.js b/app/components/error/error.ctrl.js deleted file mode 100644 index eaaa68c..0000000 --- a/app/components/error/error.ctrl.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -let errors = require('meanie-express-error-handling'); -let ReportedError = errors.ReportedError; - -/** - * Error controller - */ -module.exports = { - - /** - * Report - */ - report(req, res, next) { - - //Get data and prepare error - let {message, stack, context} = req.body; - let error = new ReportedError(message, stack, context); - - //Use express error middleware to handle it - next(error); - }, -}; diff --git a/app/components/error/error.routes.js b/app/components/error/error.routes.js deleted file mode 100644 index fa9f1d4..0000000 --- a/app/components/error/error.routes.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -let express = require('express'); - -/** - * Error routes - */ -module.exports = function(app) { - - //Get controllers and middleware - let errorCtrl = require('./error.ctrl'); - let checkAuthenticated = require('../auth/auth.ctrl').checkAuthenticated; - - //Create new router - let router = express.Router(); - - //Report error - router.post( - '/', - checkAuthenticated, - errorCtrl.report - ); - - //Register router - app.use('/error', router); -}; diff --git a/app/components/file/file.ctrl.js b/app/components/file/file.ctrl.js index 6551b16..ecf8202 100644 --- a/app/components/file/file.ctrl.js +++ b/app/components/file/file.ctrl.js @@ -3,18 +3,19 @@ /** * Dependencies */ -let multer = require('multer'); -let mimeTypesFilter = require('meanie-multer-mime-types-filter'); -let errors = require('meanie-express-error-handling'); -let BadRequestError = errors.BadRequestError; -let FileTooLargeError = errors.FileTooLargeError; -let gcloud = require('../../services/gcloud'); +const multer = require('multer'); +const mimeTypesFilter = require('meanie-multer-mime-types-filter'); +const errors = require('meanie-express-error-handling'); +const BadRequestError = errors.BadRequestError; +const FileTooLargeError = errors.FileTooLargeError; +const gcloud = require('../../services/gcloud'); +const gcs = gcloud.storage(); /** * Helper to generate a path for a GCS file */ function gcsPath(folder, name, mimeType, timestamp) { - let extension = mimeType.split('/')[1].toLowerCase().replace('jpeg', 'jpg'); + const extension = mimeType.split('/')[1].toLowerCase().replace('jpeg', 'jpg'); if (timestamp) { name += '_' + String(Math.floor(Date.now() / 1000)); } @@ -32,13 +33,13 @@ module.exports = { upload(req, res, next) { //Get GCS config - let config = req.fileConfig; + const config = req.fileConfig; if (!config) { return next(); } //Create upload middleware - let upload = multer({ + const upload = multer({ storage: multer.memoryStorage(), fileFilter: mimeTypesFilter(config.mimeTypes), limits: { @@ -66,29 +67,28 @@ module.exports = { streamToCloud(req, res, next) { //Get GCS config - let config = req.fileConfig; + const config = req.fileConfig; if (!config) { return next(); } //Get config params - let {bucket, folder, name, timestamp} = config; + const {bucket, folder, name, timestamp} = config; //Get uploaded file and path for bucket - let file = req.file; + const file = req.file; if (!file) { return next(new BadRequestError('No file')); } //Get data - let contentType = file.mimetype; - let path = gcsPath(folder, name, contentType, timestamp); + const contentType = file.mimetype; + const path = gcsPath(folder, name, contentType, timestamp); //Prepare file and stream - let gcs = gcloud.storage(); - let gcsBucket = gcs.bucket(bucket); - let gcsFile = gcsBucket.file(path); - let stream = gcsFile.createWriteStream({ + const gcsBucket = gcs.bucket(bucket); + const gcsFile = gcsBucket.file(path); + const stream = gcsFile.createWriteStream({ metadata: { contentType, }, @@ -117,13 +117,13 @@ module.exports = { deleteFromCloud(req, res, next) { //Get GCS config - let config = req.fileConfig; + const config = req.fileConfig; if (!config) { return next(); } //Get data - let data = config.existing; + const data = config.existing; if (!data || !data.bucket || !data.path) { return next(); } @@ -138,9 +138,8 @@ module.exports = { } //Get GCS bucket and file - let gcs = gcloud.storage(); - let gcsBucket = gcs.bucket(data.bucket); - let gcsFile = gcsBucket.file(data.path); + const gcsBucket = gcs.bucket(data.bucket); + const gcsFile = gcsBucket.file(data.path); //Delete the file (allow failures but log errors) gcsFile.delete(error => { diff --git a/app/components/file/file.schema.js b/app/components/file/file.schema.js index 2b67030..7d7e01f 100644 --- a/app/components/file/file.schema.js +++ b/app/components/file/file.schema.js @@ -3,8 +3,8 @@ /** * Dependencies */ -let Schema = require('mongoose').Schema; -let config = require('../../config'); +const Schema = require('mongoose').Schema; +const config = require('../../config'); /** * Constants @@ -23,7 +23,7 @@ function extendFileSchema(fields, _id = false) { }, fields || {}); //Create schema - let FileSchema = new Schema(fields, {_id}); + const FileSchema = new Schema(fields, {_id}); //Add transform FileSchema.options.toJSON = { @@ -42,7 +42,7 @@ function extendFileSchema(fields, _id = false) { /** * Create basic schema and expose creation method */ -let FileSchema = extendFileSchema(null, false); +const FileSchema = extendFileSchema(null, false); FileSchema.extend = extendFileSchema; /** diff --git a/app/components/user/address.schema.js b/app/components/user/address.schema.js index 08182d4..9b5976c 100644 --- a/app/components/user/address.schema.js +++ b/app/components/user/address.schema.js @@ -3,12 +3,12 @@ /** * Dependencies */ -let Schema = require('mongoose').Schema; +const Schema = require('mongoose').Schema; /** * Address schema */ -let AddressSchema = new Schema({ +const AddressSchema = new Schema({ inputValue: String, streetNumber: String, streetName: String, @@ -20,6 +20,31 @@ let AddressSchema = new Schema({ _id: false, }); +/** + * Parts + */ +AddressSchema.virtual('parts').get(function() { + const parts = []; + if (this.streetNumber && this.streetName) { + parts.push(this.streetNumber + ' ' + this.streetName); + } + if (this.suburb) { + parts.push(this.suburb); + } + if (this.city) { + if (this.postalCode) { + parts.push(this.city + ' ' + this.postalCode); + } + else { + parts.push(this.city); + } + } + if (this.country) { + parts.push(this.country); + } + return parts; +}); + /** * Export schema */ diff --git a/app/components/user/avatar.ctrl.js b/app/components/user/avatar.ctrl.js index 5b4e786..af3faa9 100644 --- a/app/components/user/avatar.ctrl.js +++ b/app/components/user/avatar.ctrl.js @@ -1,35 +1,37 @@ 'use strict'; /** - * Swatch controller + * Avatar controller */ module.exports = { /** - * Upload image + * Save avatar */ save(req, res, next) { - //Get user - let user = req.me; - let file = req.file; + //Get user and uploaded file + const user = req.user; + const file = req.file; //Save file data user.avatar = file; - //Save + //Save user user.save() - .then(user => res.json({avatar: user.avatar.toJSON()})) + .then(user => user.avatar) + .then(avatar => avatar.toJSON()) + .then(avatar => res.json({avatar})) .catch(next); }, /** - * Delete image + * Delete avatar */ delete(req, res, next) { - //Get user and clear avatar data - let user = req.me; + //Get user and remove file data + const user = req.user; user.avatar = null; //Save @@ -47,13 +49,13 @@ module.exports = { */ configure(req, res, next) { - //Get config + //Get user + let user = req.user; + + //Get configuration const BUCKET = req.app.locals.GCLOUD_BUCKET_CONTENT; const MAX_FILE_SIZE = req.app.locals.USER_AVATAR_MAX_FILE_SIZE; - const MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif']; - - //Get user - let user = req.me; + const MIME_TYPES = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif']; //Configure file handling req.fileConfig = { @@ -61,7 +63,7 @@ module.exports = { bucket: BUCKET, field: 'avatar', folder: 'avatars', - name: user.id, + name: user._id.toString(), timestamp: true, maxFileSize: MAX_FILE_SIZE, mimeTypes: MIME_TYPES, diff --git a/app/components/user/emails/password-has-changed.html b/app/components/user/emails/password-has-changed.html deleted file mode 100644 index 8a5228d..0000000 --- a/app/components/user/emails/password-has-changed.html +++ /dev/null @@ -1 +0,0 @@ -
{{confirmation}}
diff --git a/app/components/user/emails/password-has-changed.js b/app/components/user/emails/password-has-changed.js deleted file mode 100644 index 4ff44c2..0000000 --- a/app/components/user/emails/password-has-changed.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -let Locale = require('../../../services/locale'); -let mailer = require('../../../services/mailer'); -let config = require('../../../config'); - -/** - * Constants - */ -const EMAIL_IDENTITY_NOREPLY = config.EMAIL_IDENTITY_NOREPLY; - -/** - * Password changed helper - */ -module.exports = function passwordHasChanged(user) { - - //Set locale for translation - let locale = new Locale(user.locale); - - //Create data for emails - let data = { - confirmation: locale.t('mail.passwordHasChanged.confirmation'), - }; - - //Load - return mailer.load('user/emails/password-has-changed', data) - .spread((text, html) => ({ - to: user.email, - from: EMAIL_IDENTITY_NOREPLY, - subject: locale.t('mail.passwordHasChanged.subject'), - text, html, - })); -}; diff --git a/app/components/user/emails/password-has-changed.txt b/app/components/user/emails/password-has-changed.txt deleted file mode 100644 index 9520adc..0000000 --- a/app/components/user/emails/password-has-changed.txt +++ /dev/null @@ -1 +0,0 @@ -{{confirmation}} diff --git a/app/components/user/emails/reset-password.html b/app/components/user/emails/reset-password.html deleted file mode 100644 index 96ca738..0000000 --- a/app/components/user/emails/reset-password.html +++ /dev/null @@ -1,4 +0,0 @@ -{{instructions}}
- -{{validityNotice}}
-{{ignoreNotice}}
diff --git a/app/components/user/emails/reset-password.js b/app/components/user/emails/reset-password.js deleted file mode 100644 index 0a328c2..0000000 --- a/app/components/user/emails/reset-password.js +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -let jwt = require('meanie-express-jwt-service'); -let Locale = require('../../../services/locale'); -let mailer = require('../../../services/mailer'); -let config = require('../../../config'); - -/** - * Constants - */ -const EMAIL_IDENTITY_NOREPLY = config.EMAIL_IDENTITY_NOREPLY; -const APP_BASE_URL = config.APP_BASE_URL; -const TOKEN_EXPIRATION = jwt.getExpiration('resetPassword'); - -/** - * Verification email helper - */ -module.exports = function resetPassword(user) { - - //Set locale for translation - let locale = new Locale(user.locale); - - //Generate a password reset token - let token = jwt.generate('resetPassword', { - id: user.id, - }); - - //Get link and number of hours link is valid - let link = APP_BASE_URL + '/password/reset/' + token; - let numHours = Math.floor(TOKEN_EXPIRATION / 3600); - - //Create data for emails - let data = { - link, - instructions: locale.t('mail.resetPassword.instructions'), - action: locale.t('mail.resetPassword.action'), - validityNotice: locale.t('mail.resetPassword.validityNotice', { - numHours, - }), - ignoreNotice: locale.t('mail.resetPassword.ignoreNotice'), - }; - - //Load - return mailer.load('user/emails/reset-password', data) - .spread((text, html) => ({ - to: user.email, - from: EMAIL_IDENTITY_NOREPLY, - subject: locale.t('mail.resetPassword.subject'), - text, html, - })); -}; diff --git a/app/components/user/emails/reset-password.txt b/app/components/user/emails/reset-password.txt deleted file mode 100644 index 7479e6b..0000000 --- a/app/components/user/emails/reset-password.txt +++ /dev/null @@ -1,7 +0,0 @@ -{{instructions}} - -{{link}} - -{{validityNotice}} - -{{ignoreNotice}} diff --git a/app/components/user/emails/verify-email-address.html b/app/components/user/emails/verify-email-address.html deleted file mode 100644 index 88596de..0000000 --- a/app/components/user/emails/verify-email-address.html +++ /dev/null @@ -1,2 +0,0 @@ -{{instructions}}
- diff --git a/app/components/user/emails/verify-email-address.js b/app/components/user/emails/verify-email-address.js deleted file mode 100644 index a27e421..0000000 --- a/app/components/user/emails/verify-email-address.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -let jwt = require('meanie-express-jwt-service'); -let Locale = require('../../../services/locale'); -let mailer = require('../../../services/mailer'); -let config = require('../../../config'); - -/** - * Constants - */ -const EMAIL_IDENTITY_NOREPLY = config.EMAIL_IDENTITY_NOREPLY; -const APP_BASE_URL = config.APP_BASE_URL; - -/** - * Verify email address email - */ -module.exports = function verifyEmailAddress(user) { - - //Set locale for translation - let locale = new Locale(user.locale); - - //Generate a verify email token - let token = jwt.generate('verifyEmail', { - id: user.id, - }); - - //Create data for emails - let data = { - link: APP_BASE_URL + '/email/verify/' + token, - instructions: locale.t('mail.verifyEmailAddress.instructions'), - action: locale.t('mail.verifyEmailAddress.action'), - }; - - //Load - return mailer.load('user/emails/verify-email-address', data) - .spread((text, html) => ({ - to: user.email, - from: EMAIL_IDENTITY_NOREPLY, - subject: locale.t('mail.verifyEmailAddress.subject'), - text, html, - })); -}; diff --git a/app/components/user/emails/verify-email-address.txt b/app/components/user/emails/verify-email-address.txt deleted file mode 100644 index 5d0cc19..0000000 --- a/app/components/user/emails/verify-email-address.txt +++ /dev/null @@ -1,3 +0,0 @@ -{{instructions}} - -{{link}} diff --git a/app/components/user/user.ctrl.js b/app/components/user/user.ctrl.js index 71208d0..39b0743 100644 --- a/app/components/user/user.ctrl.js +++ b/app/components/user/user.ctrl.js @@ -3,25 +3,22 @@ /** * Dependencies */ -let mongoose = require('mongoose'); -let jwt = require('meanie-express-jwt-service'); -let errors = require('meanie-express-error-handling'); -let NotFoundError = errors.NotFoundError; -let BadRequestError = errors.BadRequestError; -let InvalidTokenError = errors.InvalidTokenError; -let mailer = require('../../services/mailer'); - -/** - * Emails - */ -let verifyEmailAddressEmail = require('./emails/verify-email-address'); -let passwordHasChangedEmail = require('./emails/password-has-changed'); -let resetPasswordEmail = require('./emails/reset-password'); +const mongoose = require('mongoose'); +const jwt = require('meanie-express-jwt-service'); +const errors = require('meanie-express-error-handling'); +const BadRequestError = errors.BadRequestError; +const NotFoundError = errors.NotFoundError; +const InvalidTokenError = errors.InvalidTokenError; +const ExpiredTokenError = errors.ExpiredTokenError; +const ValidationError = errors.ValidationError; +const UserSuspendedError = errors.UserSuspendedError; +const mailer = require('../../services/mailer'); /** * Models */ -let User = mongoose.model('User'); +const User = mongoose.model('User'); +const UsedToken = mongoose.model('UsedToken'); /** * User controller @@ -31,9 +28,30 @@ module.exports = { /** * Get data of authenticated user */ - me(req, res) { - let user = req.me; - res.json(user.toJSON()); + me(req, res, next) { + + //Initialize user JSON + const user = req.me; + + //Update last active + user.lastActive = new Date(); + user.save().catch(error => errors.handler(error, req)); + + //Next middleware + next(); + }, + + /** + * Get user data + */ + get(req, res) { + + //Get data and status + const user = req.me.toJSON(); + const status = req.isCreate ? 201 : 200; + + //Output + res.status(status).json(user); }, /** @@ -42,26 +60,23 @@ module.exports = { create(req, res, next) { //Get user data - let data = req.body; + const data = User.parseData(req.data); + data.isEmailVerified = false; + + //Mark as a create + req.isCreate = true; //Create user User.create(data) .then(user => { - verifyEmailAddressEmail(user) - .then(email => mailer.send(email)) + req.me = user; + mailer + .load('user/verify-email-address', req) + .compose(user) + .then(email => email.send()) .catch(error => errors.handler(error, req)); - return (req.me = user); - }) - .then(user => { - - //Generate access token for immediate login - let json = user.toJSON(); - json.accessToken = jwt.generate('access', user.getClaims()); - return json; - }) - .then(user => { - res.status(201).json(user); }) + .then(next) .catch(next); }, @@ -71,48 +86,89 @@ module.exports = { update(req, res, next) { //Get user and data - let user = req.me; - let data = User.parseData(req.data); + const user = req.me; + const data = User.parseData(req.data); - //Set data and check if email changed + //Set data user.setProperties(data); - let isEmailChanged = user.isModified('email'); + + //Check if certain data changed + const emailChanged = user.isModified('email'); + + //Mark as non email verified if email was changed + if (emailChanged) { + user.isEmailVerified = false; + } //Save user user.save() .then(user => { - if (isEmailChanged) { - verifyEmailAddressEmail(user) - .then(email => mailer.send(email)) - .catch(error => errors.handler(error, req)); + + //Send new verification email + if (emailChanged) { + mailer + .load('user/verify-email-address', req) + .compose(user) + .then(email => email.send()) + .catch(error => errors.handler(error, req)); } - return (req.me = user); - }) - .then(user => user.toJSON()) - .then(user => { - res.json(user); + + //Set in request + req.me = user; }) + .then(next) + .catch(next); + }, + + /** + * Patch + */ + patch(req, res, next) { + + //Get user + const user = req.me; + + //Determine what to patch + const property = req.property; + const value = req.data[property]; + const patch = User.parseData({[property]: value}); + + //Set the property + user[property] = patch[property]; + + //Save the user + user.save() + .then(() => res.json(patch)) .catch(next); }, /** - * Change password + * Change credentials */ - changePassword(req, res, next) { + changeCredentials(req, res, next) { + + //Get user and new username/password + const user = req.me; + const {username, password} = req.body; - //Get user and new password - let user = req.me; - let password = req.body.password; + //Set username + user.username = username; + + //Set new password if not empty + if (password) { + user.password = password; + } - //Set password - user.password = password; + //Save user user.save() .then(user => { - passwordHasChangedEmail(user) - .then(email => mailer.send(email)) + mailer + .load('user/credentials-changed', req) + .compose(user) + .then(email => email.send()) .catch(error => errors.handler(error, req)); - res.end(); }) + .then(() => res.end()) .catch(next); }, @@ -120,7 +176,26 @@ module.exports = { * Exists check */ exists(req, res, next) { - User.find(req.body).limit(1) + + //Initialize filter and allowed filter properties + let filter = {}; + let allowed = ['username']; + + //Find properties to filter on + for (let key in req.query) { + if (req.query.hasOwnProperty(key) && allowed.indexOf(key) >= 0) { + filter[key] = req.query[key]; + } + } + + //No filter properties? + if (Object.keys(filter).length === 0) { + return res.json({exists: false}); + } + + //Check if exists + User.find(filter) + .limit(1) .then(users => (users.length > 0)) .then(exists => res.json({exists})) .catch(next); @@ -134,18 +209,17 @@ module.exports = { //If no user was found, send response anyway to prevent hackers from //figuring out which email addresses are valid and which aren't. if (!req.me) { - return setTimeout(() => { - res.end(); - }, 1234); + return res.end(); } //Get user - let user = req.me; + const user = req.me; //Send password reset email - resetPasswordEmail(user) - .then(email => mailer.send(email)) - .then(() => res.end()) + mailer + .load('user/reset-password', req) + .compose(user) + .then(email => email.send()) .catch(next); }, @@ -154,46 +228,67 @@ module.exports = { */ resetPassword(req, res, next) { - //Get token from body - let token = req.body.token; + //Get user + const user = req.me; + const jti = req.jti; - //Validate token - jwt.validate('resetPassword', token) - .then(jwt.getId) - .then(id => User.findById(id)) + //Update password + user.password = req.body.password; + + //Save user + user.save() .then(user => { - //No user or token already used? - if (!user) { - throw new InvalidTokenError('No matching user found'); - } - if (user.usedTokens && user.usedTokens.includes(token)) { - throw new InvalidTokenError('Token already used'); + //Send out credentials changed email + mailer + .load('user/credentials-changed', req) + .compose(user) + .then(email => email.send()) + .catch(error => errors.handler(error, req)); + + //Mark token as used + if (jti) { + UsedToken + .create({jti}) + .catch(error => errors.handler(error, req)); } - //Update password, mark token as used - user.password = req.body.password; - user.usedTokens.push(token); - return user; - }) - .then(user => user.save()) - .then(user => { - passwordHasChangedEmail(user) - .then(email => mailer.send(email)) - .catch(error => errors.handler(error, req)); + //Rend request res.end(); }) .catch(next); }, + /** + * Send usernames email + */ + sendUsernamesEmail(req, res, next) { + + //Get email and users + const email = req.body.email; + const users = req.users; + + //Send email + mailer + .load('user/recover-username', req) + .compose(email, users) + .then(email => email.send()) + .catch(next); + }, + /** * Send verification email */ sendVerificationEmail(req, res, next) { - let user = req.me; - verifyEmailAddressEmail(user) - .then(email => mailer.send(email)) - .then(() => res.end()) + + //Get user + const user = req.me; + + //Send email + mailer + .load('user/verify-email-address', req) + .compose(user) + .then(email => email.send()) .catch(next); }, @@ -202,17 +297,14 @@ module.exports = { */ verifyEmail(req, res, next) { - //Get token from body - let token = req.body.token; + //Get user + const user = req.me; - //Validate token - jwt.validate('verifyEmail', token) - .then(jwt.getId) - .then(id => User.findOneAndUpdate({ - _id: id, - }, { - isEmailVerified: true, - })) + //Mark as email verified + user.isEmailVerified = true; + + //Save user + user.save() .then(() => res.json({isValid: true})) .catch(next); }, @@ -222,44 +314,169 @@ module.exports = { ***/ /** - * Find by ID + * Set user for avatar controller */ - findById(req, res, next, id) { + setUser(req, res, next) { + req.user = req.me; + next(); + }, - //Validate ID - if (!mongoose.Types.ObjectId.isValid(id)) { + /** + * Set patch property + */ + setProperty(req, res, next, property) { + + //Valid properties + const properties = [ + 'name', + ]; + + //Invalid? + if (properties.indexOf(property) === -1) { return next(new BadRequestError()); } - //Find by ID - User.findById(id) + //Set in request + req.property = property; + next(); + }, + + /** + * Find by username (doesn't trigger 404's) + */ + findByUsername(req, res, next) { + + //Get data + const username = req.body.username; + if (!username) { + return next(); + } + + //Find by username + User.findOne({username}) .then(user => { - if (!user) { - return next(new NotFoundError()); + + //Found? + if (user) { + + //Check if suspended + if (user.isSuspended) { + throw new UserSuspendedError(); + } } + + //Set in request req.me = user; - next(); }) + .then(next) .catch(next); }, /** - * Find by email (doesn't trigger 404's) + * Find users by email */ findByEmail(req, res, next) { + //Get data + const email = req.body.email; + //No email? - if (!req.body.email) { + if (!email) { return next(); } //Find by email - User.findOne({ - email: req.body.email, - }).then(user => { - req.me = user; - next(); - }).catch(next); + User.find({email}) + .select('username firstName lastName') + .then(users => { + + //Nothing found? + if (users.length === 0) { + throw new NotFoundError(); + } + + //Set in request + req.users = users; + }) + .then(next) + .catch(next); + }, + + /** + * Find user by token + */ + findByToken(req, res, next) { + + //Get token and token type + const token = req.query.token || req.body.token; + const type = req.tokenType || req.query.type || req.body.type; + + //Must have token and type + if (!token || !type) { + return next(new BadRequestError()); + } + + //Validate token + jwt.validate(type, token) + .then(payload => { + if (payload.jti) { + return UsedToken + .findOne({jti: payload.jti}) + .then(used => { + if (used) { + throw new ExpiredTokenError('Already used'); + } + req.jti = payload.jti; + return payload.id; + }); + } + return payload.id; + }) + .then(id => User.findById(id)) + .then(user => { + if (!user) { + throw new InvalidTokenError('No matching user found'); + } + req.me = user; + }) + .then(next) + .catch(next); + }, + + /** + * Ensure username not in use + */ + ensureUsernameNotInUse(req, res, next) { + + //Get data + const userId = req.me._id; + const username = req.body.username; + + //Prepare filter + const filter = {username}; + if (userId) { + filter._id = { + $ne: userId, + }; + } + + //Check if doesn't exist + User + .findOne(filter) + .then(user => { + if (user) { + throw new ValidationError({ + fields: { + username: { + type: 'exists', + message: 'Username already in use', + }, + }, + }); + } + }) + .then(next) + .catch(next); }, /** @@ -268,17 +485,18 @@ module.exports = { collectData(req, res, next) { //Extract posted data and collect other data from request - let {firstName, lastName, email, phone, address, password} = req.body; - let user = req.me; + const user = req.me; + const { + firstName, lastName, username, password, email, phone, address, + } = req.body; //Prepare data object - req.data = { - firstName, lastName, email, phone, address, - }; + req.data = {firstName, lastName, email, phone, address}; - //Password is only appended when creating a new user. For editing, we - //use a separate route to change password with higher security. - if (!user) { + //Username and password are only appended when creating a new user + //For editing, we use a separate route with higher security. + if (!user || !user.password) { + req.data.username = username; req.data.password = password; } diff --git a/app/components/user/user.model.js b/app/components/user/user.model.js index a685870..e94535e 100644 --- a/app/components/user/user.model.js +++ b/app/components/user/user.model.js @@ -3,29 +3,30 @@ /** * Dependencies */ -let mongoose = require('mongoose'); -let Promise = require('bluebird'); -let bcrypt = require('bcryptjs'); -let Schema = mongoose.Schema; -let config = require('../../config'); +const mongoose = require('mongoose'); +const bcrypt = require('bcrypt'); +const errors = require('meanie-express-error-handling'); +const Schema = mongoose.Schema; +const ValidationError = errors.ValidationError; +const config = require('../../config'); +const roles = require('../../constants/roles'); /** * Schemas */ -let AddressSchema = require('./address.schema'); -let FileSchema = require('../file/file.schema'); +const AddressSchema = require('./address.schema'); +const FileSchema = require('../file/file.schema'); /** * Configuration */ const DEFAULT_LOCALE = config.I18N_DEFAULT_LOCALE; const BCRYPT_ROUNDS = config.BCRYPT_ROUNDS; -const PASSWORD_MIN_LENGTH = config.USER_PASSWORD_MIN_LENGTH; /** * User schema */ -let UserSchema = new Schema({ +const UserSchema = new Schema({ //Personal details firstName: { @@ -38,6 +39,9 @@ let UserSchema = new Schema({ required: true, trim: true, }, + fullName: { + type: String, + }, avatar: FileSchema, locale: { type: String, @@ -48,97 +52,196 @@ let UserSchema = new Schema({ email: { type: String, trim: true, - required: true, - unique: true, }, phone: { type: String, + trim: true, }, address: AddressSchema, //Security + username: { + type: String, + trim: true, + }, password: { type: String, - required: true, trim: true, }, roles: { type: [{ type: String, - enum: ['user', 'admin'], + enum: Object.values(roles), }], - default: ['user'], + default: [roles.USER], }, isSuspended: { type: Boolean, default: false, }, - isPending: { - type: Boolean, - default: false, - }, isEmailVerified: { type: Boolean, default: false, }, - usedTokens: [String], + lastActive: { + type: Date, + }, }); +//Index for logging in, looking up users and finding existing usernames +UserSchema.index({username: 1}, {unique: true}); + +/** + * Data pre-parser + */ +UserSchema.statics.parseData = function(data) { + return data; +}; + +/** + * Name cleaner + */ +UserSchema.statics.cleanName = function(name) { + return name + .replace(/\'/g, '’') + .replace(/—/g, '-') + .replace(/[\\\/]/g, ''); +}; + +/** + * Helper to create full name + */ +UserSchema.statics.createFullName = function(firstName, lastName) { + return String(firstName + ' ' + lastName).trim(); +}; + +/** + * Generate a unique username based on user data + */ +UserSchema.statics.uniqueUsername = function(data) { + + //Extract data + const {email, firstName, lastName} = data; + const name = String(firstName + lastName).toLowerCase(); + + //Random number generator 1-100 + function random() { + return String(Math.floor(Math.random() * 100) + 1); + } + + //Possible usernames + const usernames = [ + name, + name + random(), + name + random(), + name + random(), + name + random(), + name + random(), + ]; + + //Email first + if (email) { + usernames.unshift(email.toLowerCase()); + } + + //Find existing users + return this + .find({username: {$in: usernames}}) + .select('username') + .then(users => { + + //Find first one that didn't exist + const username = usernames.find(username => { + return !users.some(user => user.username === username); + }); + + //Still nothing found? Give up + if (!username) { + throw new Error('Unable to find unique username for user'); + } + + //Return username + return username; + }); +}; + /** - * Pre save hook to hash passwords + * Clean up names */ UserSchema.pre('save', function(next) { - //Check if email address modified - if (this.isModified('email')) { - this.isEmailVerified = false; + //Clean up names + if (this.isModified('firstName')) { + this.firstName = this.constructor.cleanName(this.firstName); + } + if (this.isModified('lastName')) { + this.lastName = this.constructor.cleanName(this.lastName); + } + + //Create full name + if (this.isModified('firstName') || this.isModified('lastName')) { + this.fullName = this.constructor + .createFullName(this.firstName, this.lastName); } - //Check if password modified and present + //Next middleware + next(); +}); + +/** + * Hash password + */ +UserSchema.pre('save', function(next) { + + //Check if password modified if (!this.isModified('password')) { return next(); } //Validate password - if (!this.password || this.password.length < PASSWORD_MIN_LENGTH) { - return next('Invalid password'); - //TODO use proper error format for validation errors + if (!this.password) { + return next(new ValidationError({ + fields: { + password: { + type: 'required', + }, + }, + })); } - //Get self - let self = this; - //Generate salt - bcrypt.genSalt(BCRYPT_ROUNDS, function(error, salt) { - if (error) { - return next(error); - } - - //Hash password - bcrypt.hash(self.password, salt, function(error, hash) { - if (error) { - return next(error); - } + bcrypt + .genSalt(BCRYPT_ROUNDS) + .then(salt => bcrypt.hash(this.password, salt)) + .then(hash => { + this.password = hash; + }) + .then(next) + .catch(next); +}); - //Set hashed password - self.password = hash; - next(); - }); - }); +/** + * Email with name + */ +UserSchema.virtual('emailWithName').get(function() { + if (!this.email) { + return ''; + } + if (this.fullName) { + return this.fullName + ' <' + this.email + '>'; + } + else if (this.firstName || this.lastName) { + return String(this.firstName + ' ' + this.lastName).trim() + + ' <' + this.email + '>'; + } + return this.email; }); /** * Password validation helper */ UserSchema.methods.comparePassword = function(candidatePassword) { - return new Promise((resolve, reject) => { - bcrypt.compare(candidatePassword, this.password, function(error, isMatch) { - if (error) { - return reject(error); - } - resolve(isMatch); - }); - }); + return bcrypt.compare(candidatePassword, this.password); }; /** @@ -175,7 +278,9 @@ UserSchema.options.toJSON = { //Delete sensitive data delete ret.password; - delete ret.usedTokens; + + //Delete unnecessary data + delete ret.fullName; }, }; diff --git a/app/components/user/user.routes.js b/app/components/user/user.routes.js index f9649f0..07fc3dc 100644 --- a/app/components/user/user.routes.js +++ b/app/components/user/user.routes.js @@ -3,56 +3,70 @@ /** * Dependencies */ -let express = require('express'); +const express = require('express'); +const userCtrl = require('./user.ctrl'); +const avatarCtrl = require('./avatar.ctrl'); +const fileCtrl = require('../file/file.ctrl'); +const authCtrl = require('../auth/auth.ctrl'); /** * User routes */ module.exports = function(app) { - //Get controllers and middleware - let userCtrl = require('./user.ctrl'); - let avatarCtrl = require('./avatar.ctrl'); - let fileCtrl = require('../file/file.ctrl'); - let ensureAuthenticated = require('../auth/auth.ctrl').ensureAuthenticated; + //Extract middleware + const {ensureAuthenticated} = authCtrl; //Create new router - let router = express.Router(); + const router = express.Router(); //Parameter handling - router.param('userId', userCtrl.findById); + router.param('property', userCtrl.setProperty); - //Create user + //Register user router.post( '/', + userCtrl.ensureUsernameNotInUse, userCtrl.collectData, - userCtrl.create + userCtrl.create, + userCtrl.get ); - //Edit logged in user + //Update logged in user router.put( '/', - ensureAuthenticated, + ensureAuthenticated(), userCtrl.collectData, - userCtrl.update + userCtrl.update, + userCtrl.get + ); + + //Change credentials + router.patch( + '/credentials', + ensureAuthenticated(), + userCtrl.ensureUsernameNotInUse, + userCtrl.changeCredentials + ); + + //Patch logged in user + router.patch( + '/:property', + ensureAuthenticated(), + userCtrl.collectData, + userCtrl.patch ); //Get logged in user data router.get( '/me', - ensureAuthenticated, - userCtrl.me - ); - - //Change password - router.post( - '/changePassword', - ensureAuthenticated, - userCtrl.changePassword + ensureAuthenticated(), + userCtrl.me, + userCtrl.get ); //Check if a user exists - router.post( + router.get( '/exists', userCtrl.exists ); @@ -60,40 +74,69 @@ module.exports = function(app) { //Verify an email address verification token router.post( '/verifyEmail', + function(req, res, next) { + req.tokenType = 'verifyEmail'; + next(); + }, + userCtrl.findByToken, userCtrl.verifyEmail ); //Send out an email address verification token router.get( '/verifyEmail', - ensureAuthenticated, + ensureAuthenticated(), userCtrl.sendVerificationEmail ); - //Sent out a password reset email + //Send out a password reset email router.post( '/forgotPassword', - userCtrl.findByEmail, + userCtrl.findByUsername, userCtrl.sendPasswordResetEmail ); + //Send out an email with username + router.post( + '/forgotUsername', + userCtrl.findByEmail, + userCtrl.sendUsernamesEmail + ); + + //Check user for reset password + router.get( + '/checkResetPassword', + function(req, res, next) { + req.tokenType = 'resetPassword'; + next(); + }, + userCtrl.findByToken, + userCtrl.get + ); + //Reset a user's password router.post( '/resetPassword', + function(req, res, next) { + req.tokenType = 'resetPassword'; + next(); + }, + userCtrl.findByToken, userCtrl.resetPassword ); - //Change a user's password + //Change a user's credentials router.post( - '/changePassword', - ensureAuthenticated, - userCtrl.changePassword + '/changeCredentials', + ensureAuthenticated(), + userCtrl.changeCredentials ); - //Upload new avatar + //Upload an avatar router.post( - '/:userId/avatar', - ensureAuthenticated, + '/avatar', + ensureAuthenticated(), + userCtrl.setUser, avatarCtrl.configure, fileCtrl.deleteFromCloud, fileCtrl.upload, @@ -101,10 +144,11 @@ module.exports = function(app) { avatarCtrl.save ); - //Delete avatar + //Delete an avatar router.delete( - '/:userId/avatar', - ensureAuthenticated, + '/avatar', + ensureAuthenticated(), + userCtrl.setUser, avatarCtrl.configure, fileCtrl.deleteFromCloud, avatarCtrl.delete diff --git a/app/components/user/user.service.js b/app/components/user/user.service.js index 8efa12c..6082c46 100644 --- a/app/components/user/user.service.js +++ b/app/components/user/user.service.js @@ -3,19 +3,19 @@ /** * Dependencies */ -let mongoose = require('mongoose'); -let errors = require('meanie-express-error-handling'); -let InvalidTokenError = errors.InvalidTokenError; +const mongoose = require('mongoose'); +const errors = require('meanie-express-error-handling'); +const InvalidTokenError = errors.InvalidTokenError; /** * Models */ -let User = mongoose.model('User'); +const User = mongoose.model('User'); /** * User service */ -let UserService = module.exports = { +const UserService = module.exports = { /** * Find user by token payload @@ -28,17 +28,24 @@ let UserService = module.exports = { } //Get ID - let id = payload.id; + const id = payload.id; //Find user by ID return UserService.findById(id); }, /** - * Find user by email and password + * Find user by username and password */ - findByEmailAndPassword(req, email, password) { - return UserService.findByEmail(email) + findByUsernameAndPassword(req, username, password) { + + //No username or no password given? + if (!username || !password) { + return Promise.resolve(null); + } + + //Find by username + return UserService.findByUsername(username) .then(user => { //No user? @@ -60,9 +67,9 @@ let UserService = module.exports = { }, /** - * Find user by email + * Find user by username */ - findByEmail(email) { - return User.findOne({email}); + findByUsername(username) { + return User.findOne({username}); }, }; diff --git a/app/config.js b/app/config.js index 50a0146..17680cf 100644 --- a/app/config.js +++ b/app/config.js @@ -3,9 +3,9 @@ /** * Dependencies */ -let path = require('path'); -let chalk = require('chalk'); -let argv = require('yargs').argv; +const path = require('path'); +const chalk = require('chalk'); +const argv = require('yargs').argv; /** * Determine environment and paths @@ -17,9 +17,9 @@ const CONFIG_PATH = path.join(BASE_PATH, 'config'); /** * Load and merge environment configuration files */ -let envCfg = loadConfig(ENV); -let localCfg = loadConfig('local'); -let mergedCfg = Object.assign(envCfg, localCfg, {ENV}); +const envCfg = loadConfig(ENV); +const localCfg = loadConfig('local'); +const mergedCfg = Object.assign(envCfg, localCfg, {ENV}); /** * Export merged config diff --git a/app/constants/roles.js b/app/constants/roles.js new file mode 100644 index 0000000..b6e0ed3 --- /dev/null +++ b/app/constants/roles.js @@ -0,0 +1,9 @@ +'use strict'; + +/** + * Available roles + */ +module.exports = { + USER: 'user', + ADMIN: 'admin', +}; diff --git a/app/helpers/load-partial.js b/app/helpers/load-partial.js new file mode 100644 index 0000000..82d5651 --- /dev/null +++ b/app/helpers/load-partial.js @@ -0,0 +1,40 @@ +'use strict'; + +/** + * Dependencies + */ +const fs = require('fs'); +const readFileSync = fs.readFileSync; + +/** + * Partials cache + */ +const cache = new Map(); + +/** + * Load a file helper + */ +function loadFile(BASE_PATH, path) { + + //Check if we have in cache + if (!cache.has(path)) { + const contents = readFileSync(BASE_PATH + path, 'utf8'); + cache.set(path, contents); + } + + //Return from cache + return cache.get(path); +} + +/** + * Load a single partial + */ +module.exports = function loadPartial(BASE_PATH, path, type) { + + //Load template and partial + const template = loadFile(BASE_PATH, 'template.' + type); + const partial = loadFile(BASE_PATH, path + '.' + type); + + //Return embedded + return template.replace('{{partial}}', partial); +}; diff --git a/app/helpers/strip-object.js b/app/helpers/strip-object.js deleted file mode 100644 index f8ed21e..0000000 --- a/app/helpers/strip-object.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -let chalk = require('chalk'); -let ObjectId = require('mongoose').Types.ObjectId; - -/** - * Helper to strip an object to only certain properties - */ -module.exports = function stripObject(obj, ...properties) { - if (Array.isArray(obj)) { - return obj.map(obj => stripObject.apply(null, [obj].concat(properties))); - } - if (!obj || typeof obj !== 'object') { - return obj; - } - if (obj instanceof ObjectId) { - console.warn(chalk.yellow('ObjectID passed to stripObject helper')); - console.warn(chalk.yellow('Asking for properties:', properties)); - return obj.toString(); - } - let stripped = {}; - properties.forEach(property => { - if (obj.hasOwnProperty(property)) { - stripped[property] = obj[property]; - } - }); - return stripped; -}; diff --git a/app/helpers/transform/currency.js b/app/helpers/transform/currency.js new file mode 100644 index 0000000..c4f84f4 --- /dev/null +++ b/app/helpers/transform/currency.js @@ -0,0 +1,20 @@ +'use strict'; + +/** + * Helper to format an amount into currency + */ +module.exports = function(amount, symbol, absolute) { + console.log(amount, symbol, absolute); + if (typeof symbol !== 'string') { + symbol = '$'; + } + if (absolute === true) { + amount = Math.abs(amount); + } + return symbol + amount.toLocaleString('en-NZ', { + style: 'decimal', + useGrouping: true, + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }); +}; diff --git a/app/helpers/transform/diff-now.js b/app/helpers/transform/diff-now.js new file mode 100644 index 0000000..9b90923 --- /dev/null +++ b/app/helpers/transform/diff-now.js @@ -0,0 +1,27 @@ +'use strict'; + +/** + * Dependencies + */ +const moment = require('moment'); + +/** + * Helper to format a moment into a date + */ +module.exports = function(date) { + if (!moment.isMoment(date)) { + return ''; + } + + //Get difference in days + const days = date.diff(moment(), 'days'); + + //If more than a day away, use relative time + if (days > 1) { + return date.fromNow(); + } + if (days < -1) { + return date.toNow(); + } + return 'today'; +}; diff --git a/app/helpers/transform/moment.js b/app/helpers/transform/moment.js new file mode 100644 index 0000000..2b75c88 --- /dev/null +++ b/app/helpers/transform/moment.js @@ -0,0 +1,31 @@ +'use strict'; + +/** + * Dependencies + */ +const moment = require('moment'); + +/** + * Helper to format a moment into a date + */ +module.exports = function(date, format, relative) { + if (typeof format !== 'string') { + format = ''; + } + if (typeof relative !== 'boolean') { + relative = false; + } + if (!moment.isMoment(date)) { + date = moment(date); + } + if (relative) { + let now = moment(); + if (now.isSame(date, 'day')) { + return 'Today'; + } + if (now.add(1, 'day').isSame(date, 'day')) { + return 'Tomorrow'; + } + } + return date.format(format || 'DD-MM-YYYY'); +}; diff --git a/app/helpers/transform/nl2br.js b/app/helpers/transform/nl2br.js new file mode 100644 index 0000000..a8a93b5 --- /dev/null +++ b/app/helpers/transform/nl2br.js @@ -0,0 +1,17 @@ +'use strict'; + +/** + * Helper to convert newlines to break tags + */ +module.exports = function(text) { + if (typeof text === 'number') { + return String(text); + } + else if (typeof text !== 'string') { + return ''; + } + if ((text = String(text)) === '') { + return ''; + } + return text.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1
+ {{app.title}}+ |
+
---|
+
+ {{partial}}
+
+ |
+
+ You are receiving this email because you are a user of {{app.title}}. To update your contact details or email preferences, please sign in to {{app.title}}. As this is an automated email you cannot reply to it directly. + Copyright © {{moment now 'YYYY'}} — {{app.title}}, v{{app.version}} + |
+
Hi {{user.firstName}}, this email was sent to let you know that your username and/or password for {{app.title}} has been changed.
+If you did not change your username or password recently, and have not asked an administrator to change it for you, please contact us.
diff --git a/emails/user/credentials-changed.js b/emails/user/credentials-changed.js new file mode 100644 index 0000000..7af9b63 --- /dev/null +++ b/emails/user/credentials-changed.js @@ -0,0 +1,15 @@ +'use strict'; + +/** + * Email generator + */ +module.exports = function credentialsChangedEmail(req, user) { + + //Prepare data + const to = user.email; + const subject = 'Your login details have changed'; + const data = {user}; + + //Return + return {to, subject, data}; +}; diff --git a/emails/user/credentials-changed.txt b/emails/user/credentials-changed.txt new file mode 100644 index 0000000..d27494c --- /dev/null +++ b/emails/user/credentials-changed.txt @@ -0,0 +1,3 @@ +Hi {{user.firstName}}, this email was sent to let you know that your username and/or password for {{app.title}} has been changed. + +If you did not change your username or password recently, and have not asked an administrator to change it for you, please contact us. diff --git a/emails/user/recover-username.hbs b/emails/user/recover-username.hbs new file mode 100644 index 0000000..5e7d831 --- /dev/null +++ b/emails/user/recover-username.hbs @@ -0,0 +1,10 @@ +Hello, we’ve received a request to recover the username of your {{app.title}} account. We found the following username{{#if isMultiple}}s{{/if}} linked to this email address:
+To login to {{app.title}} with your username now, click on the following link:
+ +If you did not request this email, please contact us.
diff --git a/emails/user/recover-username.js b/emails/user/recover-username.js new file mode 100644 index 0000000..514f5a5 --- /dev/null +++ b/emails/user/recover-username.js @@ -0,0 +1,19 @@ +'use strict'; + +/** + * Email generator + */ +module.exports = function recoverUsernameEmail(req, email, users) { + + //Check if multiple + const isMultiple = (users.length > 1); + const link = req.locals.appUrl + '/login'; + + //Prepare data + const to = email; + const subject = 'Your username' + (isMultiple ? 's' : ''); + const data = {users, link, isMultiple}; + + //Return + return {to, subject, data}; +}; diff --git a/emails/user/recover-username.txt b/emails/user/recover-username.txt new file mode 100644 index 0000000..b1e98c0 --- /dev/null +++ b/emails/user/recover-username.txt @@ -0,0 +1,11 @@ +Hello, we’ve received a request to recover the username of your {{app.title}} account. We found the following username{{#if isMultiple}}s{{/if}} linked to this email address: + +{{#each users as |user|}} + {{user.username}} ({{user.firstName}} {{user.lastName}}) +{{/each}} + +To login to {{app.title}} with your username now, click on the following link: + +{{link}} + +If you did not request this email, please contact us. diff --git a/emails/user/reset-password.hbs b/emails/user/reset-password.hbs new file mode 100644 index 0000000..80dde7f --- /dev/null +++ b/emails/user/reset-password.hbs @@ -0,0 +1,5 @@ +Hi {{user.firstName}}, we’ve received a request to reset the password of your {{app.title}} account. To reset your password now, click on the following link:
+ +This link is only valid for {{numHours}} hours.
+If you did not request this email, please contact us.
diff --git a/emails/user/reset-password.js b/emails/user/reset-password.js new file mode 100644 index 0000000..0926e57 --- /dev/null +++ b/emails/user/reset-password.js @@ -0,0 +1,34 @@ +'use strict'; + +/** + * Dependencies + */ +const jwt = require('meanie-express-jwt-service'); +const mongoose = require('mongoose'); +const ObjectId = mongoose.Types.ObjectId; + +/** + * Email generator + */ +module.exports = function resetPasswordEmail(req, user) { + + //Generate unique token identifier + const jti = new ObjectId(); + const expiration = jwt.getExpiration('resetPassword'); + + //Generate a password reset token + const token = jwt.generate('resetPassword', { + id: user._id.toString(), + jti: jti.toString(), + }); + const link = req.locals.appUrl + '/reset/password/' + token; + const numHours = Math.floor(expiration / 3600); + + //Prepare data + const to = user.email; + const subject = 'Reset your password'; + const data = {user, link, numHours}; + + //Return + return {to, subject, data}; +}; diff --git a/emails/user/reset-password.txt b/emails/user/reset-password.txt new file mode 100644 index 0000000..37841f6 --- /dev/null +++ b/emails/user/reset-password.txt @@ -0,0 +1,7 @@ +Hi {{user.firstName}}, we’ve received a request to reset the password of your {{app.title}} account. To reset your password now, click on the following link: + +{{link}} + +This link is only valid for {{numHours}} hours. + +If you did not request this email, please contact us. diff --git a/emails/user/verify-email-address.hbs b/emails/user/verify-email-address.hbs new file mode 100644 index 0000000..bc2d002 --- /dev/null +++ b/emails/user/verify-email-address.hbs @@ -0,0 +1,3 @@ +Hi {{user.firstName}}, thank you for signing up for {{app.title}}. Please verify your email address by clicking on the link below:
+ diff --git a/emails/user/verify-email-address.js b/emails/user/verify-email-address.js new file mode 100644 index 0000000..6cde005 --- /dev/null +++ b/emails/user/verify-email-address.js @@ -0,0 +1,24 @@ +'use strict'; + +/** + * Dependencies + */ +const jwt = require('meanie-express-jwt-service'); + +/** + * Email generator + */ +module.exports = function verifyEmailAddressEmail(req, user) { + + //Generate a verify email token + const token = jwt.generate('verifyEmail', {id: user._id.toString()}); + const link = req.locals.appUrl + '/email/verify/' + token; + + //Prepare data + const to = user.email; + const subject = 'Verify your email address'; + const data = {user, link}; + + //Return + return {to, subject, data}; +}; diff --git a/emails/user/verify-email-address.txt b/emails/user/verify-email-address.txt new file mode 100644 index 0000000..698eb30 --- /dev/null +++ b/emails/user/verify-email-address.txt @@ -0,0 +1,3 @@ +Hi {{user.firstName}}, thank you for signing up for {{app.title}}. Please verify your email address by clicking on the link below: + +{{link}} diff --git a/migrations/populate-users.js b/migrations/populate-users.js deleted file mode 100644 index 37eb52c..0000000 --- a/migrations/populate-users.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; - -/** - * Dependencies - */ -let mongoose = require('mongoose'); -let User = mongoose.model('User'); -let users = require('./mock/users'); - -/** - * Migration - */ -module.exports = { - - /** - * Migrate up - */ - up() { - return User.create(users); - }, - - /** - * Migrate down - */ - down() { - let emails = users.map((user) => user.email); - return User.remove({ - email: { - $in: emails, - }, - }); - }, -}; diff --git a/migrations/mock/ids.js b/migrations/populate/mock/ids.js similarity index 74% rename from migrations/mock/ids.js rename to migrations/populate/mock/ids.js index 65573ec..584e129 100644 --- a/migrations/mock/ids.js +++ b/migrations/populate/mock/ids.js @@ -3,7 +3,7 @@ /** * Dependencies */ -let ObjectId = require('mongoose').Types.ObjectId; +const ObjectId = require('mongoose').Types.ObjectId; /** * Some fixed ID's diff --git a/migrations/mock/users.js b/migrations/populate/mock/users.js similarity index 69% rename from migrations/mock/users.js rename to migrations/populate/mock/users.js index f16bdf3..01a7ec4 100644 --- a/migrations/mock/users.js +++ b/migrations/populate/mock/users.js @@ -3,7 +3,8 @@ /** * Dependencies */ -let ids = require('./ids'); +const ids = require('./ids'); +const roles = require('../../../app/constants/roles'); /** * Users @@ -17,6 +18,6 @@ module.exports = [ password: 'test123', isSuspended: false, isEmailVerified: true, - roles: ['user', 'admin'], + roles: [roles.USER, roles.ADMIN], }, ]; diff --git a/migrations/populate/populate-users.js b/migrations/populate/populate-users.js new file mode 100644 index 0000000..61b43f3 --- /dev/null +++ b/migrations/populate/populate-users.js @@ -0,0 +1,23 @@ +'use strict'; + +/** + * Dependencies + */ +const mongoose = require('mongoose'); +const User = mongoose.model('User'); + +/** + * Migration + */ +module.exports = function(argv) { + + //Determine data set to use + const data = argv.data || 'mock'; + + //Get data + const users = require('./' + data + '/users'); + + //Remove and then add users + return User.remove({}) + .then(() => User.create(users)); +}; diff --git a/nodemon.json b/nodemon.json index 1a5f609..ac1ce4d 100644 --- a/nodemon.json +++ b/nodemon.json @@ -8,7 +8,8 @@ "verbose": false, "watch": [ "app", - "config" + "config", + "emails" ], "ext": "js json", "env": { diff --git a/package.json b/package.json index 23d3443..669b562 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,9 @@ "version": "1.0.0", "homepage": "https://github.com/meanie/express-seed", "author": { - "name": "Adam Buczynski", - "email": "me@adambuczynski.com", - "url": "http://adambuczynski.com/" + "name": "Adam Reis", + "email": "adam@reis.nz", + "url": "http://adam.reis.nz/" }, "contributors": [], "license": "SEE LICENSE IN LICENSE.md", @@ -20,75 +20,78 @@ }, "keywords": [], "engines": { - "node": ">=6.3.0", - "npm": ">=3.10.3" + "node": "^7.2.1", + "npm": "^4.0.2" }, "main": "scripts/server.js", "scripts": { - "reinstall": "rm -rf node_modules && npm cache clean && npm install", - "start": "node scripts/server.js", - "dev": "nodemon --inspect scripts/server.js", - "lint": "eslint .", - "pretest": "npm run lint -s", - "istanbul": "babel-node ./node_modules/istanbul/lib/cli cover ./node_modules/mocha/bin/_mocha", + "clean": "rm -rf node_modules", + "start": "if [ $NODE_ENV == 'dev' ]; then npm run dev; else npm run prod; fi", + "prod": "node scripts/server.js", + "predev": "lsof -n -i:9229 | grep LISTEN | awk '{print $2}' | xargs kill -9", + "dev": "nodemon scripts/server.js", + "inspect": "nodemon --inspect scripts/server.js", + "lint": "eslint . --fix", + "istanbul": "babel-node ./node_modules/istanbul/lib/cli cover ./node_modules/mocha/bin/_mocha \"app/**/*.spec.js\"", "test": "npm run istanbul -s", "coverage": "open -a \"Google Chrome\" ./coverage/lcov-report/index.html", "posttest": "npm run coverage -s", - "preversion": "npm run test -s", - "postversion": "git push && git push --tags", - "migrate:up": "node scripts/migrate.js up", - "migrate:down": "node scripts/migrate.js down", - "refresh": "node scripts/migrate.js refresh", + "postversion": "git commit -a -m \"[bump] $npm_package_version\"", + "populate": "node scripts/migrate.js populate --data mock", + "update": "node scripts/migrate.js update/$npm_package_version", + "update:remote": "heroku run --app my-application npm run update", "dump:local": "mongodump -d DB_NAME_LOCAL -o ./migrations/dump", "dump:remote": "mongodump -h DB_HOST -d DB_NAME -u DB_USER -p DB_PASS -o ./migrations/dump", - "restore:remote": "mongorestore -h DB_HOST -d DB_NAME -u DB_USER -p DB_PASS ./migrations/dump/DB_NAME_LOCAL --drop", - "deploy:heroku": "git subtree push --prefix server heroku master", - "deploy:gcloud": "gcloud preview app deploy" + "restore:local": "mongorestore -d DB_NAME_LOCAL ./migrations/dump/DB_NAME --drop --noIndexRestore", + "restore:remote": "mongorestore -h DB_HOST -d DB_NAME -u DB_USER -p DB_PASS ./migrations/dump/DB_NAME_LOCAL --drop" }, "dependencies": { - "bcryptjs": "^2.3.0", - "bluebird": "^3.4.1", + "bcrypt": "^1.0.1", + "bluebird": "^3.4.6", "body-parser": "^1.15.2", "chalk": "^1.1.3", "compression": "^1.6.2", "cookie-parser": "^1.4.3", - "cors": "^2.7.1", + "cors": "^2.8.1", "express": "^4.14.0", - "gcloud": "^0.36.0", - "glob": "^7.0.5", + "glob": "^7.1.1", + "google-cloud": "^0.45.0", + "handlebars": "^4.0.6", "i18n": "^0.8.3", - "meanie-express-error-handling": "^1.1.1", - "meanie-express-github-service": "^1.0.0", - "meanie-express-jwt-service": "^1.0.1", - "meanie-mongoose-only-id": "^1.0.0", - "meanie-mongoose-set-properties": "^1.0.0", - "meanie-mongoose-to-json": "^1.0.3", - "meanie-multer-mime-types-filter": "^1.0.0", - "meanie-passport-refresh-strategy": "^1.0.0", - "moment": "^2.14.1", - "mongoose": "^4.5.6", + "meanie-express-error-handling": "^1.8.2", + "meanie-express-github-service": "^2.0.2", + "meanie-express-jwt-service": "^1.0.2", + "meanie-express-raven-service": "^1.0.1", + "meanie-mongoose-only-id": "^1.0.1", + "meanie-mongoose-set-properties": "^1.0.1", + "meanie-mongoose-to-json": "^1.0.6", + "meanie-multer-mime-types-filter": "^1.0.1", + "meanie-passport-refresh-strategy": "^1.1.2", + "moment": "^2.17.1", + "mongoose": "^4.7.2", "morgan": "^1.7.0", "multer": "^1.1.0", "passport": "^0.3.2", "passport-http-bearer": "^1.0.1", "passport-local": "^1.0.0", - "sendgrid": "^3.0.10", - "serve-static": "^1.11.1", - "yargs": "^4.8.1" + "sendgrid": "^4.7.1", + "sendgrid-mailer": "^1.0.5", + "yargs": "^6.5.0" }, "devDependencies": { - "babel-cli": "^6.11.4", - "babel-preset-es2015": "^6.9.0", + "babel-cli": "^6.16.0", + "babel-preset-es2015": "^6.18.0", "chai": "^3.5.0", - "chai-as-promised": "^5.3.0", + "chai-as-promised": "^6.0.0", "dirty-chai": "^1.2.2", - "eslint": "3.1.0", + "eslint": "^3.11.1", "express-simulate-latency": "0.0.2", - "istanbul": "^1.1.0-alpha.1", - "mocha": "^2.5.3", + "istanbul": "^1.0.0-alpha.2", + "mocha": "^3.2.0", "mocha-clean": "^1.0.0", - "nodemon": "^1.9.2", - "sinon": "^1.17.4", - "sinon-mongoose": "^1.2.1" + "nodemon": "^1.11.0", + "sinon": "^1.17.6", + "sinon-as-promised": "^4.0.0", + "sinon-mongoose": "^1.3.0" } } diff --git a/release.sh b/release.sh new file mode 100644 index 0000000..d83371e --- /dev/null +++ b/release.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash + +# Assuming you have a master and dev branch, and that you make new +# release branches named as the version they correspond to, e.g. 1.0.3 +# Usage: ./release.sh -v 1.0.3 +# Use the -b or --bump parameter to only bump + +# Default values +bump=false + +# Get arguments +while [[ $# -gt 0 ]] +do + key="$1" + +case $key in + -v|--version) + version="$2" + shift + ;; + -b|--bump) + bump=true + ;; + *) + # unknown option + ;; +esac +shift +done + +# Version must be given +if [ -z "$version" ]; then + echo "Please specify a version with -v or --version" + exit +fi + +# Output +if [ "$bump" = true ]; then + echo "Bumping to version $version" +else + echo "Releasing version $version" +fi +echo "-------------------------------------------------------------------------" + +# Bump only simply bumps the version on master and releases it +if [ "$bump" = true ]; then + + # Checkout master and run version script + git checkout master + npm version $version + + # Checkout dev branch and merge master into dev + git checkout dev + git merge master --no-ff --no-edit + + # Push everything to remote + git push --all + git push --tags + + # Done + echo "-------------------------------------------------------------------------" + echo "Bump to $version complete" + exit; +fi + +# Get current branch and checkout if needed +branch=$(git symbolic-ref --short -q HEAD) +if [ "$branch" != "$version" ]; then + git checkout $version +fi + +# Ensure working directory in version branch clean +git update-index -q --refresh +if ! git diff-index --quiet HEAD --; then + echo "Working directory not clean, please commit your changes first" + exit +fi + +# Checkout master branch and merge version branch into master +git checkout master +git merge $version --no-ff --no-edit -m "$version" + +# Create a version tag +git tag v$version + +# Delete version branch locally and on remote +git branch -D $version +git push origin --delete $version + +# Checkout dev branch and merge master into dev (to ensure we have the version) +git checkout dev +git merge master --no-ff --no-edit + +# Push everything to remote +git push --all +git push --tags + +# Success +echo "-------------------------------------------------------------------------" +echo "Release $version complete" diff --git a/scripts/lib/log.js b/scripts/lib/log.js index f97344a..7bc2c6a 100644 --- a/scripts/lib/log.js +++ b/scripts/lib/log.js @@ -3,8 +3,8 @@ /** * Dependencies */ -let chalk = require('chalk'); -let ValidationError = require('mongoose').Error.ValidationError; +const chalk = require('chalk'); +const ValidationError = require('mongoose').Error.ValidationError; /** * Helper to log an error @@ -55,5 +55,4 @@ function logSuccess(message) { module.exports = { success: logSuccess, error: logError, - validationError: logValidationError, }; diff --git a/scripts/lib/run.js b/scripts/lib/run.js index 9b3136a..7e1dfb1 100644 --- a/scripts/lib/run.js +++ b/scripts/lib/run.js @@ -3,87 +3,38 @@ /** * Dependencies */ -let path = require('path'); -let Promise = require('bluebird'); -let status = require('./status'); +const path = require('path'); +const status = require('./status'); +const argv = require('yargs').argv; /** - * Invalid method error + * Helper to run scripts */ -function MethodInvalidError() {} -MethodInvalidError.prototype = Object.create(Error.prototype); +function run(scripts) { -/** - * Helper to load a migration script - */ -function loadScript(file) { - return Promise.try(() => { - return require(path.resolve(file)); - }); -} - -/** - * Helper to check if a script method is present - */ -function checkHasMethod(script, method) { - if (typeof script[method] !== 'function') { - throw new MethodInvalidError('No `' + method + '` method present'); + //Convert to array if single script given + if (!Array.isArray(scripts)) { + scripts = [scripts]; } - return script[method]; -} - -/** - * Helper to run down migrations one by one - */ -function runDownMigrations(migrations) { - - //Done - if (migrations.length === 0) { - return Promise.resolve('Finished all migrations'); - } - - //Get migration - let migration = migrations.shift(); - status.start('Rolling back migration', migration); - - //Load the script and run the migration - return loadScript(migration) - .then(script => checkHasMethod(script, 'down')) - .then(runner => runner()) - .then(() => status.ok()) - .catch(MethodInvalidError, error => status.skip(error.message)) - .catch(error => status.error(error)) - .then(() => runDownMigrations(migrations)); -} - -/** - * Helper to run up migrations one by one - */ -function runUpMigrations(migrations) { //Done - if (migrations.length === 0) { - return Promise.resolve('Finished all migrations'); + if (scripts.length === 0) { + return Promise.resolve(); } - //Get migration - let migration = migrations.shift(); - status.start('Running migration', migration); + //Get script file + const file = scripts.shift(); + status.start('Running', path.basename(file)); - //Run migration - return loadScript(migration) - .then(script => checkHasMethod(script, 'up')) - .then(runner => runner()) + //Load script and run it + return Promise.try(() => require(path.resolve(file))) + .then(script => script(argv)) .then(() => status.ok()) - .catch(MethodInvalidError, error => status.skip(error.message)) .catch(error => status.error(error)) - .then(() => runUpMigrations(migrations)); + .then(() => run(scripts)); } /** * Export interface */ -module.exports = { - up: runUpMigrations, - down: runDownMigrations, -}; +module.exports = run; diff --git a/scripts/lib/status.js b/scripts/lib/status.js index 5162146..cea4e2e 100644 --- a/scripts/lib/status.js +++ b/scripts/lib/status.js @@ -3,17 +3,14 @@ /** * Dependencies */ -let path = require('path'); -let chalk = require('chalk'); -let log = require('./log'); +const chalk = require('chalk'); +const log = require('./log'); /** * Helpers to output status messages */ function statusStart(message, file) { - process.stdout.write(chalk.grey( - message + ' ' + path.basename(file) + '... ' - )); + process.stdout.write(chalk.grey(message + ' ' + file + '... ')); } function statusOk() { process.stdout.write(chalk.green('OK\n')); @@ -22,12 +19,6 @@ function statusError(error) { process.stdout.write(chalk.red('ERROR\n')); log.error(error); } -function statusSkip(reason) { - process.stdout.write(chalk.yellow('SKIP\n')); - if (reason) { - console.log(chalk.yellow(reason)); - } -} /** * Export interface @@ -36,5 +27,4 @@ module.exports = { start: statusStart, ok: statusOk, error: statusError, - skip: statusSkip, }; diff --git a/scripts/migrate.js b/scripts/migrate.js index d38ae16..0f60558 100644 --- a/scripts/migrate.js +++ b/scripts/migrate.js @@ -1,21 +1,25 @@ 'use strict'; +/** + * Use bluebird for promises globally + */ +global.Promise = require('bluebird'); + /** * Dependencies */ -let path = require('path'); -let glob = require('glob'); -let chalk = require('chalk'); -let argv = require('yargs').argv; -let Promise = require('bluebird'); -let db = require('../app/services/db'); -let log = require('./lib/log'); -let run = require('./lib/run'); +const path = require('path'); +const chalk = require('chalk'); +const argv = require('yargs').argv; +const glob = require('glob'); +const db = require('../app/services/db'); +const log = require('./lib/log'); +const run = require('./lib/run'); /** * Fix CWD if run from scripts path */ -let cwd = process.cwd().split(path.sep); +const cwd = process.cwd().split(path.sep); if (cwd.length && cwd[cwd.length - 1] === 'scripts') { cwd.pop(); process.chdir(cwd.join(path.sep)); @@ -27,64 +31,25 @@ if (cwd.length && cwd[cwd.length - 1] === 'scripts') { const MIGRATIONS_PATH = './migrations/'; /** - * Available commands + * Get parameters */ -let commands = { - - /** - * Migrate up - */ - up() { - - //Load all migrations from the migrations path - let migrations = glob.sync(MIGRATIONS_PATH + '*.js'); - if (migrations.length === 0) { - return Promise.resolve('No migrations found'); - } - - //Run up migrations - return run.up(migrations); - }, - - /** - * Migrate down - */ - down() { - - //Load all migrations from the migrations path - let migrations = glob.sync(MIGRATIONS_PATH + '*.js'); - if (migrations.length === 0) { - return Promise.resolve('No migrations found'); - } - - //Run down migrations - return run.down(migrations); - }, - - /** - * Refresh database (migrate down and up again) - */ - refresh() { - return this.down() - .then(() => this.up()) - .then(() => 'Database refreshed'); - }, -}; +const folder = path.join(MIGRATIONS_PATH, (argv._.length ? argv._[0] : '')); +const debug = (typeof argv.debug !== 'undefined'); -//Defaults -let command = (argv._.length ? argv._[0] : 'up'); -let debug = (typeof argv.debug !== 'undefined'); +//Log +console.log(chalk.grey('Loading migrations from'), chalk.magenta(folder)); -//Validate it -if (!command || !commands[command]) { - console.log(chalk.red('Unknown migration command:', command)); +//Get the migrations +let migrations = glob.sync(path.join(folder, '*.js')); +if (migrations.length === 0) { + console.warn(chalk.yellow('No migrations found!')); process.exit(0); } //Run when DB connected -db(null, {debug: debug}).connection.on('connected', () => { - commands[command]() - .then(log.success) +db(null, {debug}).connection.on('connected', () => { + run(migrations) + .then(() => log.success('Finished all migrations')) .catch(log.error) .finally(() => process.exit(0)); }); diff --git a/scripts/server.js b/scripts/server.js index b4f0875..fc0caa5 100644 --- a/scripts/server.js +++ b/scripts/server.js @@ -1,28 +1,32 @@ 'use strict'; /** - * Dependencies + * Use bluebird for promises globally */ -let path = require('path'); -let chalk = require('chalk'); +global.Promise = require('bluebird'); /** - * Fix CWD if run from scripts path + * Dependencies */ -let cwd = process.cwd().split(path.sep); -if (cwd.length && cwd[cwd.length - 1] === 'scripts') { - cwd.pop(); - process.chdir(cwd.join(path.sep)); -} +const path = require('path'); +const chalk = require('chalk'); +const config = require('../app/config'); /** * Configuration */ -let config = require('../app/config'); const ENV = config.ENV; const APP_NAME = config.APP_NAME; const SERVER_PORT = config.SERVER_PORT; -const SERVER_HTTPS = config.SERVER_HTTPS; + +/** + * Fix CWD if run from scripts path + */ +const cwd = process.cwd().split(path.sep); +if (cwd.length && cwd[cwd.length - 1] === 'scripts') { + cwd.pop(); + process.chdir(cwd.join(path.sep)); +} /** * Error handler @@ -48,8 +52,8 @@ console.log('Running application', chalk.magenta(APP_NAME), * Initialize express application */ console.log('Starting Express server...'); -let app = require('../app/app')(); -let server = app.listen(SERVER_PORT, function() { +const app = require('../app/app')(); +const server = app.listen(SERVER_PORT, function() { //Skip if no address if (!this.address()) { @@ -57,10 +61,9 @@ let server = app.listen(SERVER_PORT, function() { } //Determine address - let host = this.address().address.replace('::', 'localhost'); - let port = this.address().port; - let protocol = SERVER_HTTPS ? 'https://' : 'http://'; - let address = protocol + host + ':' + port; + const host = this.address().address.replace('::', 'localhost'); + const port = this.address().port; + const address = host + ':' + port; //Output success message console.log(chalk.green('Express server started @ '), chalk.magenta(address)); diff --git a/scripts/task.js b/scripts/task.js new file mode 100644 index 0000000..121ade1 --- /dev/null +++ b/scripts/task.js @@ -0,0 +1,47 @@ +'use strict'; + +/** + * Use bluebird for promises globally + */ +global.Promise = require('bluebird'); + +/** + * Dependencies + */ +const path = require('path'); +const chalk = require('chalk'); +const argv = require('yargs').argv; +const db = require('../app/services/db'); +const log = require('./lib/log'); +const run = require('./lib/run'); + +/** + * Fix CWD if run from scripts path + */ +const cwd = process.cwd().split(path.sep); +if (cwd.length && cwd[cwd.length - 1] === 'scripts') { + cwd.pop(); + process.chdir(cwd.join(path.sep)); +} + +/** + * Define tasks path + */ +const TASKS_PATH = './tasks/'; + +/** + * Get parameters + */ +const task = path.join(TASKS_PATH, (argv._.length ? argv._[0] : '')); +const debug = (typeof argv.debug !== 'undefined'); + +//Log +console.log(chalk.grey('Running task'), chalk.magenta(task)); + +//Run when DB connected +db(null, {debug}).connection.on('connected', () => { + run(task) + .then(() => log.success('Task completed')) + .catch(log.error) + .finally(() => process.exit(0)); +}); diff --git a/tasks/example.js b/tasks/example.js new file mode 100644 index 0000000..d25221b --- /dev/null +++ b/tasks/example.js @@ -0,0 +1,19 @@ +'use strict'; + +/** + * Dependencies + */ +const mongoose = require('mongoose'); +const User = mongoose.model('User'); + +/** + * Task + */ +module.exports = function() { + return User + .find({}) + .then(users => { + //Do something with users + console.log(users); + }); +}; diff --git a/test/helpers/setup.js b/test/helpers/setup.js index 12e4bf9..49dd863 100644 --- a/test/helpers/setup.js +++ b/test/helpers/setup.js @@ -1,9 +1,15 @@ 'use strict'; //Load dependencies -let chai = require('chai'); -let dirtyChai = require('dirty-chai'); -let chaiAsPromised = require('chai-as-promised'); +const chai = require('chai'); +const sinon = require('sinon'); +const Promise = require('bluebird'); +const dirtyChai = require('dirty-chai'); +const chaiAsPromised = require('chai-as-promised'); + +//Load sinon extensions +require('sinon-mongoose'); +require('sinon-as-promised')(Promise); //Enable should assertion style for usage with chai-as-promised chai.should(); @@ -14,3 +20,4 @@ chai.use(chaiAsPromised); //Expose globals global.expect = chai.expect; +global.sinon = sinon; diff --git a/test/mocha.opts b/test/mocha.opts index 1f393e6..7ecbf32 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,3 +1,3 @@ +--recursive --require test/helpers/setup --require mocha-clean -app/**/*.spec.js diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..19faa2d --- /dev/null +++ b/yarn.lock @@ -0,0 +1,4692 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@google-cloud/bigquery@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@google-cloud/bigquery/-/bigquery-0.6.0.tgz#18014469a7b4bd94450753d37afeb7b57096096e" + dependencies: + "@google-cloud/common" "^0.9.0" + arrify "^1.0.0" + duplexify "^3.2.0" + extend "^3.0.0" + is "^3.0.1" + stream-events "^1.0.1" + string-format-obj "^1.0.0" + +"@google-cloud/bigtable@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@google-cloud/bigtable/-/bigtable-0.7.0.tgz#a482215315b0c8c743a871930d51aa80ff5bf7b5" + dependencies: + "@google-cloud/common" "^0.9.0" + arrify "^1.0.0" + concat-stream "^1.5.0" + create-error-class "^3.0.2" + dot-prop "^3.0.0" + extend "^3.0.0" + google-proto-files "^0.8.0" + is "^3.0.1" + lodash.flatten "^4.2.0" + node-int64 "^0.4.0" + prop-assign "^1.0.0" + pumpify "^1.3.3" + string-format-obj "^1.0.0" + through2 "^2.0.0" + +"@google-cloud/common@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@google-cloud/common/-/common-0.9.0.tgz#d239e48d8943994082894bdd78aaf8a79a1492a8" + dependencies: + array-uniq "^1.0.2" + arrify "^1.0.0" + concat-stream "^1.5.0" + create-error-class "^3.0.2" + dot-prop "^2.4.0" + duplexify "^3.2.0" + ent "^2.2.0" + extend "^3.0.0" + google-auto-auth "^0.5.0" + google-proto-files "^0.8.0" + grpc "^1.0.0" + is "^3.0.1" + methmeth "^1.0.0" + modelo "^4.2.0" + request "^2.70.0" + retry-request "^1.3.0" + split-array-stream "^1.0.0" + stream-events "^1.0.1" + string-format-obj "^1.0.0" + through2 "^2.0.0" + +"@google-cloud/compute@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@google-cloud/compute/-/compute-0.4.0.tgz#ce56278f2eef7f9ec1946035b3349abbe4303982" + dependencies: + "@google-cloud/common" "^0.9.0" + arrify "^1.0.0" + async "^2.0.1" + create-error-class "^3.0.2" + extend "^3.0.0" + gce-images "^0.3.0" + is "^3.0.1" + string-format-obj "^1.0.0" + +"@google-cloud/datastore@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@google-cloud/datastore/-/datastore-0.6.0.tgz#ffaf78ba24efb086315044beb944d818c05bd724" + dependencies: + "@google-cloud/common" "^0.9.0" + arrify "^1.0.0" + concat-stream "^1.5.0" + create-error-class "^3.0.2" + extend "^3.0.0" + is "^3.0.1" + lodash.flatten "^4.2.0" + modelo "^4.2.0" + prop-assign "^1.0.0" + propprop "^0.3.0" + split-array-stream "^1.0.0" + +"@google-cloud/dns@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@google-cloud/dns/-/dns-0.4.0.tgz#5b068993ea3096d889aeb7dc7acf5afcb69f5ee5" + dependencies: + "@google-cloud/common" "^0.9.0" + arrify "^1.0.0" + dns-zonefile "0.1.18" + extend "^3.0.0" + is "^3.0.1" + methmeth "^1.0.0" + string-format-obj "^1.0.0" + +"@google-cloud/language@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@google-cloud/language/-/language-0.7.0.tgz#3874aa0243cb47d5a51d01461a6de66aff35d429" + dependencies: + "@google-cloud/common" "^0.9.0" + arrify "^1.0.1" + extend "^3.0.0" + google-gax "^0.10.0" + google-proto-files "^0.8.5" + is "^3.0.1" + propprop "^0.3.1" + string-format-obj "^1.1.0" + +"@google-cloud/logging@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@google-cloud/logging/-/logging-0.6.0.tgz#96f55e56f90aaa8e81ae25e13deacad90c5112bc" + dependencies: + "@google-cloud/common" "^0.9.0" + arrify "^1.0.0" + async "^2.1.4" + extend "^3.0.0" + google-gax "^0.10.0" + google-proto-files "^0.8.0" + is "^3.0.1" + is-circular "^1.0.1" + string-format-obj "^1.0.0" + +"@google-cloud/monitoring@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@google-cloud/monitoring/-/monitoring-0.1.3.tgz#d8e9ac0bb5eece45657b9f0ee94d62935225fc54" + dependencies: + extend "^3.0.0" + google-gax "^0.10.0" + google-proto-files "^0.8.3" + +"@google-cloud/prediction@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@google-cloud/prediction/-/prediction-0.4.0.tgz#5fb504a69bf1df6dfa22a12f74767e40b111558a" + dependencies: + "@google-cloud/common" "^0.9.0" + JSONStream "^1.0.7" + arrify "^1.0.0" + extend "^3.0.0" + is "^3.0.1" + pumpify "^1.3.3" + stream-events "^1.0.1" + string-format-obj "^1.0.0" + through2 "^2.0.0" + +"@google-cloud/pubsub@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@google-cloud/pubsub/-/pubsub-0.7.0.tgz#e056a1ccdcadbd1cc96655d421345ebb3511fc6e" + dependencies: + "@google-cloud/common" "^0.9.0" + arrify "^1.0.0" + extend "^3.0.0" + google-gax "^0.10.0" + google-proto-files "^0.8.0" + is "^3.0.1" + modelo "^4.2.0" + propprop "^0.3.0" + uuid "^3.0.1" + +"@google-cloud/resource@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@google-cloud/resource/-/resource-0.5.0.tgz#79f4f00c28988892faae30534d3b2f5d170d4634" + dependencies: + "@google-cloud/common" "^0.9.0" + extend "^3.0.0" + is "^3.0.1" + +"@google-cloud/speech@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@google-cloud/speech/-/speech-0.5.0.tgz#67f9adad2a67027f5ef2c1b16f13cf276763ac63" + dependencies: + "@google-cloud/common" "^0.9.0" + events-intercept "^2.0.0" + extend "^3.0.0" + google-gax "^0.10.2" + google-proto-files "^0.8.0" + is "^3.1.0" + propprop "^0.3.1" + pumpify "^1.3.5" + request "^2.74.0" + stream-events "^1.0.1" + string-format-obj "^1.1.0" + through2 "^2.0.1" + +"@google-cloud/storage@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-0.6.0.tgz#74e9be567b60ba062fda7aab9f0564dadca44cf0" + dependencies: + "@google-cloud/common" "^0.9.0" + arrify "^1.0.0" + async "^2.0.1" + concat-stream "^1.5.0" + create-error-class "^3.0.2" + duplexify "^3.2.0" + extend "^3.0.0" + gcs-resumable-upload "^0.7.1" + hash-stream-validation "^0.2.1" + is "^3.0.1" + mime-types "^2.0.8" + once "^1.3.1" + pumpify "^1.3.3" + stream-events "^1.0.1" + string-format-obj "^1.0.0" + through2 "^2.0.0" + +"@google-cloud/translate@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@google-cloud/translate/-/translate-0.6.0.tgz#97856994eeb68bef5a3b3c8287d3feb7135d610c" + dependencies: + "@google-cloud/common" "^0.9.0" + arrify "^1.0.0" + extend "^3.0.0" + is "^3.0.1" + is-html "^1.0.0" + propprop "^0.3.0" + +"@google-cloud/vision@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@google-cloud/vision/-/vision-0.7.0.tgz#286a4cde76235b9178a462041f4b7c861a242cd0" + dependencies: + "@google-cloud/common" "^0.9.0" + arrify "^1.0.0" + async "^2.0.1" + extend "^3.0.0" + google-gax "^0.10.0" + google-proto-files "^0.8.0" + is "^3.0.1" + propprop "^0.3.0" + request "^2.70.0" + rgb-hex "^1.0.0" + string-format-obj "^1.0.0" + +JSONStream@^1.0.7: + version "1.2.1" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.2.1.tgz#32aa5790e799481083b49b4b7fa94e23bae69bf9" + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abbrev@1, abbrev@1.0.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + +accepts@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" + dependencies: + mime-types "~2.1.11" + negotiator "0.6.1" + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +acorn@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.3.tgz#1a3e850b428e73ba6b09d1cc527f5aaad4d03ef1" + +agent-base@2: + version "2.0.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.0.1.tgz#bd8f9e86a8eb221fffa07bd14befd55df142815e" + dependencies: + extend "~3.0.0" + semver "~5.0.1" + +ajv-keywords@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.2.0.tgz#676c4f087bfe1e8b12dca6fda2f3c74f417b099c" + +ajv@^4.7.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.9.2.tgz#3f7dcda95b0c34bceb2d69945117d146219f1a2c" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +ambi@^2.2.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/ambi/-/ambi-2.5.0.tgz#7c8e372be48891157e7cea01cb6f9143d1f74220" + dependencies: + editions "^1.1.1" + typechecker "^4.3.0" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + +ansi-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.0.0.tgz#c5061b6e0ef8a81775e50f5d66151bf6bf371107" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +anymatch@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507" + dependencies: + arrify "^1.0.0" + micromatch "^2.1.5" + +append-field@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/append-field/-/append-field-0.1.0.tgz#6ddc58fa083c7bc545d3c5995b2830cc2366d44a" + +append-transform@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.3.0.tgz#d6933ce4a85f09445d9ccc4cc119051b7381a813" + +aproba@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.0.4.tgz#2713680775e7614c8ba186c065d4e2e52d1072c0" + +are-we-there-yet@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz#80e470e95a084794fe1899262c5667c6e88de1b3" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.0 || ^1.1.13" + +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +arguejs@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/arguejs/-/arguejs-0.2.3.tgz#b6f939f5fe0e3cd1f3f93e2aa9262424bf312af7" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1, array-uniq@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +arrify@^1.0.0, arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +ascli@~1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ascli/-/ascli-1.0.1.tgz#bcfa5974a62f18e81cabaeb49732ab4a88f906bc" + dependencies: + colour "~0.7.1" + optjs "~3.2.2" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assertion-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + +async.ensureasync@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/async.ensureasync/-/async.ensureasync-0.5.2.tgz#c3c7e4a4e9b31d96875d56b8504598446e1e305d" + dependencies: + async.util.ensureasync "0.5.2" + +async.queue@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/async.queue/-/async.queue-0.5.2.tgz#8d5d90812e1481066bc0904e8cc1712b17c3bd7c" + dependencies: + async.util.queue "0.5.2" + +async.util.arrayeach@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/async.util.arrayeach/-/async.util.arrayeach-0.5.2.tgz#58c4e98028d55d69bfb05aeb3af44e0a555a829c" + +async.util.ensureasync@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/async.util.ensureasync/-/async.util.ensureasync-0.5.2.tgz#10907f2cbd067a061f99ae6d22e08ced30db0d68" + dependencies: + async.util.restparam "0.5.2" + async.util.setimmediate "0.5.2" + +async.util.isarray@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/async.util.isarray/-/async.util.isarray-0.5.2.tgz#e62dac8f2636f65875dcf7521c2d24d0dfb2bbdf" + +async.util.map@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/async.util.map/-/async.util.map-0.5.2.tgz#e588ef86e0b3ab5f027d97af4d6835d055ca69d6" + +async.util.noop@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/async.util.noop/-/async.util.noop-0.5.2.tgz#bdd62b97cb0aa3f60b586ad148468698975e58b9" + +async.util.onlyonce@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/async.util.onlyonce/-/async.util.onlyonce-0.5.2.tgz#b8e6fc004adc923164d79e32f2813ee465c24ff2" + +async.util.queue@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/async.util.queue/-/async.util.queue-0.5.2.tgz#57f65abe1a3cdf273d31abd28ab95425f8222ee5" + dependencies: + async.util.arrayeach "0.5.2" + async.util.isarray "0.5.2" + async.util.map "0.5.2" + async.util.noop "0.5.2" + async.util.onlyonce "0.5.2" + async.util.setimmediate "0.5.2" + +async.util.restparam@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/async.util.restparam/-/async.util.restparam-0.5.2.tgz#03efebf3c0277b97220e525aba750f5e04fc80cd" + +async.util.setimmediate@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/async.util.setimmediate/-/async.util.setimmediate-0.5.2.tgz#2812ebabf2a58027758d4bc7793d1ccfaf10255f" + +async@1.x, async@^1.4.0, async@^1.4.2, async@~1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + +async@2.1.4, async@^2.0.1, async@^2.1.2, async@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" + dependencies: + lodash "^4.14.0" + +async@~0.2.6: + version "0.2.10" + resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" + +async@~1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.4.2.tgz#6c9edcb11ced4f0dd2f2d40db0d49a109c088aab" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws4@^1.2.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.5.0.tgz#0a29ffb79c31c9e712eeb087e8e7a64b4a56d755" + +babel-cli@^6.16.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.18.0.tgz#92117f341add9dead90f6fa7d0a97c0cc08ec186" + dependencies: + babel-core "^6.18.0" + babel-polyfill "^6.16.0" + babel-register "^6.18.0" + babel-runtime "^6.9.0" + commander "^2.8.1" + convert-source-map "^1.1.0" + fs-readdir-recursive "^1.0.0" + glob "^5.0.5" + lodash "^4.2.0" + output-file-sync "^1.1.0" + path-is-absolute "^1.0.0" + slash "^1.0.0" + source-map "^0.5.0" + v8flags "^2.0.10" + optionalDependencies: + chokidar "^1.0.0" + +babel-code-frame@^6.16.0, babel-code-frame@^6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.20.0.tgz#b968f839090f9a8bc6d41938fb96cb84f7387b26" + dependencies: + chalk "^1.1.0" + esutils "^2.0.2" + js-tokens "^2.0.0" + +babel-core@^6.18.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.20.0.tgz#ab0d7176d9dea434e66badadaf92237865eab1ec" + dependencies: + babel-code-frame "^6.20.0" + babel-generator "^6.20.0" + babel-helpers "^6.16.0" + babel-messages "^6.8.0" + babel-register "^6.18.0" + babel-runtime "^6.20.0" + babel-template "^6.16.0" + babel-traverse "^6.20.0" + babel-types "^6.20.0" + babylon "^6.11.0" + convert-source-map "^1.1.0" + debug "^2.1.1" + json5 "^0.5.0" + lodash "^4.2.0" + minimatch "^3.0.2" + path-is-absolute "^1.0.0" + private "^0.1.6" + slash "^1.0.0" + source-map "^0.5.0" + +babel-generator@^6.18.0, babel-generator@^6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.20.0.tgz#fee63614e0449390103b3097f3f6a118016c6766" + dependencies: + babel-messages "^6.8.0" + babel-runtime "^6.20.0" + babel-types "^6.20.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.2.0" + source-map "^0.5.0" + +babel-helper-call-delegate@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.18.0.tgz#05b14aafa430884b034097ef29e9f067ea4133bd" + dependencies: + babel-helper-hoist-variables "^6.18.0" + babel-runtime "^6.0.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-helper-define-map@^6.18.0, babel-helper-define-map@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.18.0.tgz#8d6c85dc7fbb4c19be3de40474d18e97c3676ec2" + dependencies: + babel-helper-function-name "^6.18.0" + babel-runtime "^6.9.0" + babel-types "^6.18.0" + lodash "^4.2.0" + +babel-helper-function-name@^6.18.0, babel-helper-function-name@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.18.0.tgz#68ec71aeba1f3e28b2a6f0730190b754a9bf30e6" + dependencies: + babel-helper-get-function-arity "^6.18.0" + babel-runtime "^6.0.0" + babel-template "^6.8.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-helper-get-function-arity@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.18.0.tgz#a5b19695fd3f9cdfc328398b47dafcd7094f9f24" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-helper-hoist-variables@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.18.0.tgz#a835b5ab8b46d6de9babefae4d98ea41e866b82a" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-helper-optimise-call-expression@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.18.0.tgz#9261d0299ee1a4f08a6dd28b7b7c777348fd8f0f" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-helper-regex@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.18.0.tgz#ae0ebfd77de86cb2f1af258e2cc20b5fe893ecc6" + dependencies: + babel-runtime "^6.9.0" + babel-types "^6.18.0" + lodash "^4.2.0" + +babel-helper-replace-supers@^6.18.0, babel-helper-replace-supers@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.18.0.tgz#28ec69877be4144dbd64f4cc3a337e89f29a924e" + dependencies: + babel-helper-optimise-call-expression "^6.18.0" + babel-messages "^6.8.0" + babel-runtime "^6.0.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-helpers@^6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.16.0.tgz#1095ec10d99279460553e67eb3eee9973d3867e3" + dependencies: + babel-runtime "^6.0.0" + babel-template "^6.16.0" + +babel-messages@^6.8.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.8.0.tgz#bf504736ca967e6d65ef0adb5a2a5f947c8e0eb9" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-check-es2015-constants@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.8.0.tgz#dbf024c32ed37bfda8dee1e76da02386a8d26fe7" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-arrow-functions@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.8.0.tgz#5b63afc3181bdc9a8c4d481b5a4f3f7d7fef3d9d" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.8.0.tgz#ed95d629c4b5a71ae29682b998f70d9833eb366d" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-block-scoping@^6.18.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.20.0.tgz#5d8f3e83b1a1ae1064e64a9e5bb83108d8e73be3" + dependencies: + babel-runtime "^6.20.0" + babel-template "^6.15.0" + babel-traverse "^6.20.0" + babel-types "^6.20.0" + lodash "^4.2.0" + +babel-plugin-transform-es2015-classes@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.18.0.tgz#ffe7a17321bf83e494dcda0ae3fc72df48ffd1d9" + dependencies: + babel-helper-define-map "^6.18.0" + babel-helper-function-name "^6.18.0" + babel-helper-optimise-call-expression "^6.18.0" + babel-helper-replace-supers "^6.18.0" + babel-messages "^6.8.0" + babel-runtime "^6.9.0" + babel-template "^6.14.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-plugin-transform-es2015-computed-properties@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.8.0.tgz#f51010fd61b3bd7b6b60a5fdfd307bb7a5279870" + dependencies: + babel-helper-define-map "^6.8.0" + babel-runtime "^6.0.0" + babel-template "^6.8.0" + +babel-plugin-transform-es2015-destructuring@^6.18.0: + version "6.19.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.19.0.tgz#ff1d911c4b3f4cab621bd66702a869acd1900533" + dependencies: + babel-runtime "^6.9.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.6.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.8.0.tgz#fd8f7f7171fc108cc1c70c3164b9f15a81c25f7d" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.8.0" + +babel-plugin-transform-es2015-for-of@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.18.0.tgz#4c517504db64bf8cfc119a6b8f177211f2028a70" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-function-name@^6.9.0: + version "6.9.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.9.0.tgz#8c135b17dbd064e5bba56ec511baaee2fca82719" + dependencies: + babel-helper-function-name "^6.8.0" + babel-runtime "^6.9.0" + babel-types "^6.9.0" + +babel-plugin-transform-es2015-literals@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.8.0.tgz#50aa2e5c7958fc2ab25d74ec117e0cc98f046468" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-modules-amd@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.18.0.tgz#49a054cbb762bdf9ae2d8a807076cfade6141e40" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.18.0" + babel-runtime "^6.0.0" + babel-template "^6.8.0" + +babel-plugin-transform-es2015-modules-commonjs@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.18.0.tgz#c15ae5bb11b32a0abdcc98a5837baa4ee8d67bcc" + dependencies: + babel-plugin-transform-strict-mode "^6.18.0" + babel-runtime "^6.0.0" + babel-template "^6.16.0" + babel-types "^6.18.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.18.0: + version "6.19.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.19.0.tgz#50438136eba74527efa00a5b0fefaf1dc4071da6" + dependencies: + babel-helper-hoist-variables "^6.18.0" + babel-runtime "^6.11.6" + babel-template "^6.14.0" + +babel-plugin-transform-es2015-modules-umd@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.18.0.tgz#23351770ece5c1f8e83ed67cb1d7992884491e50" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.18.0" + babel-runtime "^6.0.0" + babel-template "^6.8.0" + +babel-plugin-transform-es2015-object-super@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.8.0.tgz#1b858740a5a4400887c23dcff6f4d56eea4a24c5" + dependencies: + babel-helper-replace-supers "^6.8.0" + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-parameters@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.18.0.tgz#9b2cfe238c549f1635ba27fc1daa858be70608b1" + dependencies: + babel-helper-call-delegate "^6.18.0" + babel-helper-get-function-arity "^6.18.0" + babel-runtime "^6.9.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + +babel-plugin-transform-es2015-shorthand-properties@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.18.0.tgz#e2ede3b7df47bf980151926534d1dd0cbea58f43" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-plugin-transform-es2015-spread@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.8.0.tgz#0217f737e3b821fa5a669f187c6ed59205f05e9c" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-sticky-regex@^6.3.13: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.8.0.tgz#e73d300a440a35d5c64f5c2a344dc236e3df47be" + dependencies: + babel-helper-regex "^6.8.0" + babel-runtime "^6.0.0" + babel-types "^6.8.0" + +babel-plugin-transform-es2015-template-literals@^6.6.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.8.0.tgz#86eb876d0a2c635da4ec048b4f7de9dfc897e66b" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.18.0.tgz#0b14c48629c90ff47a0650077f6aa699bee35798" + dependencies: + babel-runtime "^6.0.0" + +babel-plugin-transform-es2015-unicode-regex@^6.3.13: + version "6.11.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.11.0.tgz#6298ceabaad88d50a3f4f392d8de997260f6ef2c" + dependencies: + babel-helper-regex "^6.8.0" + babel-runtime "^6.0.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-regenerator@^6.16.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.20.0.tgz#a546cd2aa1c9889929d5c427a31303847847ab75" + dependencies: + regenerator-transform "0.9.8" + +babel-plugin-transform-strict-mode@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.18.0.tgz#df7cf2991fe046f44163dcd110d5ca43bc652b9d" + dependencies: + babel-runtime "^6.0.0" + babel-types "^6.18.0" + +babel-polyfill@^6.16.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.20.0.tgz#de4a371006139e20990aac0be367d398331204e7" + dependencies: + babel-runtime "^6.20.0" + core-js "^2.4.0" + regenerator-runtime "^0.10.0" + +babel-preset-es2015@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.18.0.tgz#b8c70df84ec948c43dcf2bf770e988eb7da88312" + dependencies: + babel-plugin-check-es2015-constants "^6.3.13" + babel-plugin-transform-es2015-arrow-functions "^6.3.13" + babel-plugin-transform-es2015-block-scoped-functions "^6.3.13" + babel-plugin-transform-es2015-block-scoping "^6.18.0" + babel-plugin-transform-es2015-classes "^6.18.0" + babel-plugin-transform-es2015-computed-properties "^6.3.13" + babel-plugin-transform-es2015-destructuring "^6.18.0" + babel-plugin-transform-es2015-duplicate-keys "^6.6.0" + babel-plugin-transform-es2015-for-of "^6.18.0" + babel-plugin-transform-es2015-function-name "^6.9.0" + babel-plugin-transform-es2015-literals "^6.3.13" + babel-plugin-transform-es2015-modules-amd "^6.18.0" + babel-plugin-transform-es2015-modules-commonjs "^6.18.0" + babel-plugin-transform-es2015-modules-systemjs "^6.18.0" + babel-plugin-transform-es2015-modules-umd "^6.18.0" + babel-plugin-transform-es2015-object-super "^6.3.13" + babel-plugin-transform-es2015-parameters "^6.18.0" + babel-plugin-transform-es2015-shorthand-properties "^6.18.0" + babel-plugin-transform-es2015-spread "^6.3.13" + babel-plugin-transform-es2015-sticky-regex "^6.3.13" + babel-plugin-transform-es2015-template-literals "^6.6.0" + babel-plugin-transform-es2015-typeof-symbol "^6.18.0" + babel-plugin-transform-es2015-unicode-regex "^6.3.13" + babel-plugin-transform-regenerator "^6.16.0" + +babel-register@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.18.0.tgz#892e2e03865078dd90ad2c715111ec4449b32a68" + dependencies: + babel-core "^6.18.0" + babel-runtime "^6.11.6" + core-js "^2.4.0" + home-or-tmp "^2.0.0" + lodash "^4.2.0" + mkdirp "^0.5.1" + source-map-support "^0.4.2" + +babel-runtime@^6.0.0, babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.20.0, babel-runtime@^6.9.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.20.0.tgz#87300bdcf4cd770f09bf0048c64204e17806d16f" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.10.0" + +babel-template@^6.14.0, babel-template@^6.15.0, babel-template@^6.16.0, babel-template@^6.8.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.16.0.tgz#e149dd1a9f03a35f817ddbc4d0481988e7ebc8ca" + dependencies: + babel-runtime "^6.9.0" + babel-traverse "^6.16.0" + babel-types "^6.16.0" + babylon "^6.11.0" + lodash "^4.2.0" + +babel-traverse@^6.16.0, babel-traverse@^6.18.0, babel-traverse@^6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.20.0.tgz#5378d1a743e3d856e6a52289994100bbdfd9872a" + dependencies: + babel-code-frame "^6.20.0" + babel-messages "^6.8.0" + babel-runtime "^6.20.0" + babel-types "^6.20.0" + babylon "^6.11.0" + debug "^2.2.0" + globals "^9.0.0" + invariant "^2.2.0" + lodash "^4.2.0" + +babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.20.0, babel-types@^6.8.0, babel-types@^6.9.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.20.0.tgz#3869ecb98459533b37df809886b3f7f3b08d2baa" + dependencies: + babel-runtime "^6.20.0" + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^1.0.1" + +babylon@^6.11.0, babylon@^6.13.0: + version "6.14.1" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.14.1.tgz#956275fab72753ad9b3435d7afe58f8bf0a29815" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +base64url@2.0.0, base64url@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/base64url/-/base64url-2.0.0.tgz#eac16e03ea1438eff9423d69baa36262ed1f70bb" + +base64url@~0.0.4: + version "0.0.6" + resolved "https://registry.yarnpkg.com/base64url/-/base64url-0.0.6.tgz#9597b36b330db1c42477322ea87ea8027499b82b" + +base64url@~1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/base64url/-/base64url-1.0.6.tgz#d64d375d68a7c640d912e2358d170dca5bb54681" + dependencies: + concat-stream "~1.4.7" + meow "~2.0.0" + +basic-auth@~1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.0.4.tgz#030935b01de7c9b94a824b29f3fccb750d3a5290" + +bcrypt-pbkdf@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz#3ca76b85241c7170bf7d9703e7b9aa74630040d4" + dependencies: + tweetnacl "^0.14.3" + +bcrypt@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-1.0.1.tgz#453b7aa1e05e03fcc48b8e368865123ae3fc313f" + dependencies: + bindings "1.2.1" + nan "2.3.5" + node-pre-gyp "0.6.30" + +binary-extensions@^1.0.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774" + +bindings@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" + +bl@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.1.2.tgz#fdca871a99713aa00d19e3bbba41c44787a65398" + dependencies: + readable-stream "~2.0.5" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + dependencies: + inherits "~2.0.0" + +bluebird@2.10.2: + version "2.10.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.10.2.tgz#024a5517295308857f14f91f1106fc3b555f446b" + +bluebird@^3.4.1, bluebird@^3.4.6: + version "3.4.6" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.6.tgz#01da8d821d87813d158967e743d5fe6c62cf8c0f" + +body-parser@^1.15.2: + version "1.15.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.15.2.tgz#d7578cf4f1d11d5f6ea804cef35dc7a7ff6dae67" + dependencies: + bytes "2.4.0" + content-type "~1.0.2" + debug "~2.2.0" + depd "~1.1.0" + http-errors "~1.5.0" + iconv-lite "0.4.13" + on-finished "~2.3.0" + qs "6.2.0" + raw-body "~2.1.7" + type-is "~1.6.13" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +bottleneck@^1.12.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-1.15.0.tgz#a636f59bc2783d87d5ac7f30ff30a22e440ffbc1" + +brace-expansion@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + +bson@~0.5.4, bson@~0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/bson/-/bson-0.5.7.tgz#0d11fe0936c1fee029e11f7063f5d0ab2422ea3e" + +buffer-equal-constant-time@1.0.1, buffer-equal-constant-time@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + +buffer-equal@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" + +buffer-shims@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" + +builtin-modules@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +busboy@^0.2.11: + version "0.2.13" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.13.tgz#90fc4f6a3967d815616fc976bfa8e56aed0c58b6" + dependencies: + dicer "0.2.5" + readable-stream "1.1.x" + +bytebuffer@~5: + version "5.0.1" + resolved "https://registry.yarnpkg.com/bytebuffer/-/bytebuffer-5.0.1.tgz#582eea4b1a873b6d020a48d58df85f0bba6cfddd" + dependencies: + long "~3" + +bytes@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.3.0.tgz#d5b680a165b6201739acb611542aabc2d8ceb070" + +bytes@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + +camelcase-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-1.0.0.tgz#bd1a11bf9b31a1ce493493a930de1a0baf4ad7ec" + dependencies: + camelcase "^1.0.1" + map-obj "^1.0.0" + +camelcase@^1.0.1, camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + +capture-stack-trace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" + +caseless@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chai-as-promised@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-6.0.0.tgz#1a02a433a6f24dafac63b9c96fa1684db1aa8da6" + dependencies: + check-error "^1.0.2" + +chai@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" + dependencies: + assertion-error "^1.0.1" + deep-eql "^0.1.3" + type-detect "^1.0.0" + +chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + +chokidar@^1.0.0, chokidar@^1.4.3: + version "1.6.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2" + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + +circular-json@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" + +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + dependencies: + restore-cursor "^1.0.1" + +cli-width@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +clone@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +colour@~0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + dependencies: + delayed-stream "~1.0.0" + +commander@2.9.0, commander@^2.8.1, commander@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +compressible@~2.0.8: + version "2.0.9" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.9.tgz#6daab4e2b599c2770dd9e21e7a891b1c5a755425" + dependencies: + mime-db ">= 1.24.0 < 2" + +compression@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.6.2.tgz#cceb121ecc9d09c52d7ad0c3350ea93ddd402bc3" + dependencies: + accepts "~1.3.3" + bytes "2.3.0" + compressible "~2.0.8" + debug "~2.2.0" + on-headers "~1.0.1" + vary "~1.1.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.4.6, concat-stream@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266" + dependencies: + inherits "~2.0.1" + readable-stream "~2.0.0" + typedarray "~0.0.5" + +concat-stream@~1.4.7: + version "1.4.10" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.4.10.tgz#acc3bbf5602cb8cc980c6ac840fa7d8603e3ef36" + dependencies: + inherits "~2.0.1" + readable-stream "~1.1.9" + typedarray "~0.0.5" + +configstore@^1.0.0, configstore@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-1.4.0.tgz#c35781d0501d268c25c54b8b17f6240e8a4fb021" + dependencies: + graceful-fs "^4.1.2" + mkdirp "^0.5.0" + object-assign "^4.0.1" + os-tmpdir "^1.0.0" + osenv "^0.1.0" + uuid "^2.0.1" + write-file-atomic "^1.1.2" + xdg-basedir "^2.0.0" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +content-disposition@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.1.tgz#87476c6a67c8daa87e32e87616df883ba7fb071b" + +content-type@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed" + +convert-source-map@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.3.0.tgz#e9f3e9c6e2728efc2676696a70eb382f73106a67" + +cookie-parser@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.3.tgz#0fe31fa19d000b95f4aadf1f53fdc2b8a203baa5" + dependencies: + cookie "0.3.1" + cookie-signature "1.0.6" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + +core-js@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cors@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.1.tgz#6181aa56abb45a2825be3304703747ae4e9d2383" + dependencies: + vary "^1" + +create-error-class@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-2.0.1.tgz#a8759ed5c8d214a461e81d18e70aacb33dd63c9c" + dependencies: + capture-stack-trace "^1.0.0" + inherits "^2.0.1" + +create-error-class@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + dependencies: + capture-stack-trace "^1.0.0" + +create-thenable@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/create-thenable/-/create-thenable-1.0.2.tgz#e2031720ccc9575d8cfa31f5c146e762a80c0534" + dependencies: + object.omit "~2.0.0" + unique-concat "~0.2.2" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +csextends@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/csextends/-/csextends-1.0.3.tgz#df41407bfddb1837ecc2dd28587725d6af9550f8" + +d@^0.1.1, d@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/d/-/d-0.1.1.tgz#da184c535d18d8ee7ba2aa229b914009fae11309" + dependencies: + es5-ext "~0.10.2" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +debug@*, debug@2, debug@2.2.0, debug@^2.1.1, debug@^2.2.0, debug@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + +decamelize@^1.0.0, decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-eql@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" + dependencies: + type-detect "0.1.1" + +deep-extend@~0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +depd@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +dicer@0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f" + dependencies: + readable-stream "1.1.x" + streamsearch "0.1.2" + +diff@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" + +dirty-chai@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/dirty-chai/-/dirty-chai-1.2.2.tgz#78495e619635f7fe44219aa4c837849bf183142e" + +dns-zonefile@0.1.18: + version "0.1.18" + resolved "https://registry.yarnpkg.com/dns-zonefile/-/dns-zonefile-0.1.18.tgz#7569c7371dbdfd50bf8e53e2da0740679292299e" + +doctrine@^1.2.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +dot-prop@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-2.4.0.tgz#848e28f7f1d50740c6747ab3cb07670462b6f89c" + dependencies: + is-obj "^1.0.0" + +dot-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177" + dependencies: + is-obj "^1.0.0" + +duplexer@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + +duplexify@^3.1.2, duplexify@^3.2.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.0.tgz#1aa773002e1578457e9d9d4a50b0ccaaebcbd604" + dependencies: + end-of-stream "1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +eachr@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/eachr/-/eachr-2.0.4.tgz#466f7caa10708f610509e32c807aafe57fc122bf" + dependencies: + typechecker "^2.0.8" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +ecdsa-sig-formatter@1.0.9, ecdsa-sig-formatter@^1.0.0: + version "1.0.9" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz#4bc926274ec3b5abb5016e7e1d60921ac262b2a1" + dependencies: + base64url "^2.0.0" + safe-buffer "^5.0.1" + +editions@^1.1.1, editions@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.3.tgz#0907101bdda20fac3cbe334c27cbd0688dc99a5b" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +encodeurl@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" + +end-of-stream@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.0.0.tgz#d4596e702734a93e40e9af864319eabd99ff2f0e" + dependencies: + once "~1.3.0" + +end-of-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.1.0.tgz#e9353258baa9108965efc41cb0ef8ade2f3cfb07" + dependencies: + once "~1.3.0" + +ent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + +error-ex@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.0.tgz#e67b43f3e82c96ea3a584ffee0b9fc3325d802d9" + dependencies: + is-arrayish "^0.2.1" + +es5-ext@^0.10.7, es5-ext@^0.10.8, es5-ext@~0.10.11, es5-ext@~0.10.2, es5-ext@~0.10.7: + version "0.10.12" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.12.tgz#aa84641d4db76b62abba5e45fd805ecbab140047" + dependencies: + es6-iterator "2" + es6-symbol "~3.1" + +es6-iterator@2: + version "2.0.0" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.0.tgz#bd968567d61635e33c0b80727613c9cb4b096bac" + dependencies: + d "^0.1.1" + es5-ext "^0.10.7" + es6-symbol "3" + +es6-map@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.4.tgz#a34b147be224773a4d7da8072794cefa3632b897" + dependencies: + d "~0.1.1" + es5-ext "~0.10.11" + es6-iterator "2" + es6-set "~0.1.3" + es6-symbol "~3.1.0" + event-emitter "~0.3.4" + +es6-promise@3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4" + +es6-promise@^3.0.2: + version "3.3.1" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" + +es6-set@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.4.tgz#9516b6761c2964b92ff479456233a247dc707ce8" + dependencies: + d "~0.1.1" + es5-ext "~0.10.11" + es6-iterator "2" + es6-symbol "3" + event-emitter "~0.3.4" + +es6-symbol@3, es6-symbol@~3.1, es6-symbol@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.0.tgz#94481c655e7a7cad82eba832d97d5433496d7ffa" + dependencies: + d "~0.1.1" + es5-ext "~0.10.11" + +es6-weak-map@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.1.tgz#0d2bbd8827eb5fb4ba8f97fbfea50d43db21ea81" + dependencies: + d "^0.1.1" + es5-ext "^0.10.8" + es6-iterator "2" + es6-symbol "3" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint@^3.11.1: + version "3.12.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.12.0.tgz#1dfa4ef0082e35feed90a0fb1f7996d1d426b249" + dependencies: + babel-code-frame "^6.16.0" + chalk "^1.1.3" + concat-stream "^1.4.6" + debug "^2.1.1" + doctrine "^1.2.2" + escope "^3.6.0" + espree "^3.3.1" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.0.3" + globals "^9.14.0" + ignore "^3.2.0" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + levn "^0.3.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.7.5" + strip-bom "^3.0.0" + strip-json-comments "~1.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + +espree@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.3.2.tgz#dbf3fadeb4ecb4d4778303e50103b3d36c88b89c" + dependencies: + acorn "^4.0.1" + acorn-jsx "^3.0.0" + +esprima@^2.6.0: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + +esrecurse@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220" + dependencies: + estraverse "~4.1.0" + object-assign "^4.0.1" + +estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +estraverse@~4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +etag@~1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" + +event-emitter@~0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.4.tgz#8d63ddfb4cfe1fae3b32ca265c4c720222080bb5" + dependencies: + d "~0.1.1" + es5-ext "~0.10.7" + +event-stream@~3.3.0: + version "3.3.4" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + dependencies: + duplexer "~0.1.1" + from "~0" + map-stream "~0.1.0" + pause-stream "0.0.11" + split "0.3" + stream-combiner "~0.0.4" + through "~2.3.1" + +events-intercept@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/events-intercept/-/events-intercept-2.0.0.tgz#adbf38681c5a4b2011c41ee41f61a34cba448897" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +express-simulate-latency@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/express-simulate-latency/-/express-simulate-latency-0.0.2.tgz#6f6c3b49915c982c9cf0d7709ca44c7f345b3957" + +express@^4.14.0: + version "4.14.0" + resolved "https://registry.yarnpkg.com/express/-/express-4.14.0.tgz#c1ee3f42cdc891fb3dc650a8922d51ec847d0d66" + dependencies: + accepts "~1.3.3" + array-flatten "1.1.1" + content-disposition "0.5.1" + content-type "~1.0.2" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "~2.2.0" + depd "~1.1.0" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.7.0" + finalhandler "0.5.0" + fresh "0.3.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.1" + path-to-regexp "0.1.7" + proxy-addr "~1.1.2" + qs "6.2.0" + range-parser "~1.2.0" + send "0.14.1" + serve-static "~1.11.1" + type-is "~1.6.13" + utils-merge "1.0.0" + vary "~1.1.0" + +extend@3, extend@^3.0.0, extend@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" + +extendr@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/extendr/-/extendr-2.1.0.tgz#301aa0bbea565f4d2dc8f570f2a22611a8527b56" + dependencies: + typechecker "~2.0.1" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +extract-opts@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-2.2.0.tgz#1fa28eba7352c6db480f885ceb71a46810be6d7d" + dependencies: + typechecker "~2.0.1" + +extsprintf@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" + +fast-levenshtein@~2.0.4: + version "2.0.5" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.5.tgz#bd33145744519ab1c36c3ee9f31f08e9079b67f2" + +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +filename-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.0.tgz#996e3e80479b98b9897f15a8a58b3d084e926775" + +fileset@0.2.x: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fileset/-/fileset-0.2.1.tgz#588ef8973c6623b2a76df465105696b96aac8067" + dependencies: + glob "5.x" + minimatch "2.x" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +finalhandler@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.5.0.tgz#e9508abece9b6dba871a6942a1d7911b91911ac7" + dependencies: + debug "~2.2.0" + escape-html "~1.0.3" + on-finished "~2.3.0" + statuses "~1.3.0" + unpipe "~1.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +flat-cache@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.1.tgz#6c837d6225a7de5659323740b36d5361f71691ff" + dependencies: + circular-json "^0.3.0" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +follow-redirects@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-0.0.7.tgz#34b90bab2a911aa347571da90f22bd36ecd8a919" + dependencies: + debug "^2.2.0" + stream-consume "^0.1.0" + +for-in@^0.1.5: + version "0.1.6" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.6.tgz#c9f96e89bfad18a545af5ec3ed352a1d9e5b4dc8" + +for-own@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.4.tgz#0149b41a39088c7515f51ebe1c1386d45f935072" + dependencies: + for-in "^0.1.5" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~1.0.0-rc4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.1.tgz#ae315db9a4907fa065502304a66d7733475ee37c" + dependencies: + async "^2.0.1" + combined-stream "^1.0.5" + mime-types "^2.1.11" + +form-data@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +formatio@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" + dependencies: + samsam "~1.1" + +forwarded@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363" + +fresh@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" + +from@~0: + version "0.1.3" + resolved "https://registry.yarnpkg.com/from/-/from-0.1.3.tgz#ef63ac2062ac32acf7862e0d40b44b896f22f3bc" + +fs-readdir-recursive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz#8cd1745c8b4f8a29c8caec392476921ba195f560" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fsevents@^1.0.0: + version "1.0.15" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.0.15.tgz#fa63f590f3c2ad91275e4972a6cea545fb0aae44" + dependencies: + nan "^2.3.0" + node-pre-gyp "^0.6.29" + +fstream-ignore@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" + dependencies: + fstream "^1.0.0" + inherits "2" + minimatch "^3.0.0" + +fstream@^1.0.0, fstream@^1.0.2, fstream@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.10.tgz#604e8a92fe26ffd9f6fae30399d4984e1ab22822" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +gauge@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.2.tgz#15cecc31b02d05345a5d6b0e171cdb3ad2307774" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + supports-color "^0.2.0" + wide-align "^1.1.0" + +gce-images@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/gce-images/-/gce-images-0.3.1.tgz#fcc268ee7b2489d457bc55345c214669fcd560e9" + dependencies: + arrify "^1.0.0" + async "^1.4.2" + google-auto-auth "^0.1.0" + got "^4.1.1" + object-assign "^3.0.0" + +gcs-resumable-upload@^0.7.1: + version "0.7.4" + resolved "https://registry.yarnpkg.com/gcs-resumable-upload/-/gcs-resumable-upload-0.7.4.tgz#6633967badf7a4aed2d79337e7badfe889cfd617" + dependencies: + buffer-equal "0.0.1" + configstore "^1.2.1" + google-auto-auth "^0.2.1" + pumpify "^1.3.3" + request "^2.61.0" + stream-events "^1.0.1" + through2 "^2.0.0" + +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + +get-caller-file@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + +getpass@^0.1.1: + version "0.1.6" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" + dependencies: + assert-plus "^1.0.0" + +github@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/github/-/github-1.4.0.tgz#60aed8f16ffe381a3ca6dc6dba5bdd64445b7856" + dependencies: + follow-redirects "0.0.7" + https-proxy-agent "^1.0.0" + mime "^1.2.11" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob@5.x, glob@^5.0.10, glob@^5.0.5: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@~6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^9.0.0, globals@^9.14.0: + version "9.14.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.14.0.tgz#8859936af0038741263053b39d0e76ca241e4034" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +google-auth-library@^0.9.10, google-auth-library@^0.9.6: + version "0.9.10" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-0.9.10.tgz#4993dc07bb4834b8ca0350213a6873a32c6051b9" + dependencies: + async "~1.4.2" + gtoken "^1.1.0" + jws "~3.0.0" + lodash.noop "~3.0.0" + request "~2.74.0" + string-template "~0.2.0" + +google-auto-auth@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/google-auto-auth/-/google-auto-auth-0.1.1.tgz#69e061ac54484c11e8a971a5e76d4239dbee6910" + dependencies: + google-auth-library "^0.9.6" + object-assign "^3.0.0" + +google-auto-auth@^0.2.1: + version "0.2.4" + resolved "https://registry.yarnpkg.com/google-auto-auth/-/google-auto-auth-0.2.4.tgz#16dafbf150d353a42190979c6803ffc75f6455fa" + dependencies: + google-auth-library "^0.9.6" + object-assign "^3.0.0" + +google-auto-auth@^0.5.0, google-auto-auth@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/google-auto-auth/-/google-auto-auth-0.5.2.tgz#4c9f38574e69fb55a3c516ab0415e9fa33e67602" + dependencies: + async "^2.1.2" + google-auth-library "^0.9.10" + object-assign "^3.0.0" + request "^2.79.0" + +google-cloud@^0.45.0: + version "0.45.0" + resolved "https://registry.yarnpkg.com/google-cloud/-/google-cloud-0.45.0.tgz#c5bb5f206f4650e3d543fe78738a36a372657578" + dependencies: + "@google-cloud/bigquery" "^0.6.0" + "@google-cloud/bigtable" "^0.7.0" + "@google-cloud/compute" "^0.4.0" + "@google-cloud/datastore" "^0.6.0" + "@google-cloud/dns" "^0.4.0" + "@google-cloud/language" "^0.7.0" + "@google-cloud/logging" "^0.6.0" + "@google-cloud/monitoring" "^0.1.2" + "@google-cloud/prediction" "^0.4.0" + "@google-cloud/pubsub" "^0.7.0" + "@google-cloud/resource" "^0.5.0" + "@google-cloud/speech" "^0.5.0" + "@google-cloud/storage" "^0.6.0" + "@google-cloud/translate" "^0.6.0" + "@google-cloud/vision" "^0.7.0" + extend "^3.0.0" + +google-gax@^0.10.0, google-gax@^0.10.2: + version "0.10.2" + resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-0.10.2.tgz#9795d60437279bd1c63f2f4e8323f94d332bccd8" + dependencies: + extend "^3.0.0" + google-auto-auth "^0.5.2" + google-proto-files "^0.8.3" + grpc "~1.0" + lodash "^4.17.2" + process-nextick-args "^1.0.7" + readable-stream "^2.2.2" + +google-p12-pem@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-0.1.0.tgz#fb2523bf84ff74676e84c72b4def50961e617d1c" + dependencies: + node-forge "^0.6.33" + +google-proto-files@^0.8.0, google-proto-files@^0.8.3, google-proto-files@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/google-proto-files/-/google-proto-files-0.8.5.tgz#282a1b70864cdf22cc648a99275341f00140a430" + +got@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/got/-/got-3.3.1.tgz#e5d0ed4af55fc3eef4d56007769d98192bcb2eca" + dependencies: + duplexify "^3.2.0" + infinity-agent "^2.0.0" + is-redirect "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + nested-error-stacks "^1.0.0" + object-assign "^3.0.0" + prepend-http "^1.0.0" + read-all-stream "^3.0.0" + timed-out "^2.0.0" + +got@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/got/-/got-4.2.0.tgz#af59f461834bfafd722cba01acf4c14a9dd5da06" + dependencies: + create-error-class "^2.0.0" + duplexify "^3.2.0" + is-plain-obj "^1.0.0" + is-redirect "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + node-status-codes "^1.0.0" + object-assign "^3.0.0" + parse-json "^2.1.0" + pinkie-promise "^1.0.0" + prepend-http "^1.0.0" + read-all-stream "^3.0.0" + timed-out "^2.0.0" + unzip-response "^1.0.0" + +graceful-fs@*, graceful-fs@^4.1.2, graceful-fs@^4.1.4: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + +grpc@^1.0.0, grpc@~1.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.0.1.tgz#e965544b5e56c998058102184e2ab1f27f123afd" + dependencies: + arguejs "^0.2.3" + lodash "^4.15.0" + nan "^2.0.0" + node-pre-gyp "^0.6.0" + protobufjs "^5.0.0" + +gtoken@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-1.2.1.tgz#90153a547c2fc1cd24a4d3d2ab3b5aba0a26897a" + dependencies: + google-p12-pem "^0.1.0" + jws "^3.0.0" + mime "^1.2.11" + request "^2.72.0" + +handlebars@^4.0.3, handlebars@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.6.tgz#2ce4484850537f9c97a8026d5399b935c4ed4ed7" + dependencies: + async "^1.4.0" + optimist "^0.6.1" + source-map "^0.4.4" + optionalDependencies: + uglify-js "^2.6" + +har-validator@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" + dependencies: + chalk "^1.1.1" + commander "^2.9.0" + is-my-json-valid "^2.12.4" + pinkie-promise "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +hash-stream-validation@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/hash-stream-validation/-/hash-stream-validation-0.2.1.tgz#ecc9b997b218be5bb31298628bb807869b73dcd1" + dependencies: + through2 "^2.0.0" + +hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hooks-fixed@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/hooks-fixed/-/hooks-fixed-1.2.0.tgz#0d2772d4d7d685ff9244724a9f0b5b2559aac96b" + +hosted-git-info@^2.1.4: + version "2.1.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.1.5.tgz#0ba81d90da2e25ab34a332e6ec77936e1598118b" + +html-tags@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-1.1.1.tgz#869f43859f12d9bdc3892419e494a628aa1b204e" + +http-errors@~1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750" + dependencies: + inherits "2.0.3" + setprototypeof "1.0.2" + statuses ">= 1.3.1 < 2" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-proxy-agent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz#35f7da6c48ce4ddbfa264891ac593ee5ff8671e6" + dependencies: + agent-base "2" + debug "2" + extend "3" + +i18n@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/i18n/-/i18n-0.8.3.tgz#2d8cf1c24722602c2041d01ba6ae5eaa51388f0e" + dependencies: + debug "*" + make-plural "^3.0.3" + math-interval-parser "^1.1.0" + messageformat "^0.3.1" + mustache "*" + sprintf-js ">=1.0.3" + +iconv-lite@0.4.13: + version "0.4.13" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" + +ignore-by-default@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + +ignore@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.0.tgz#8d88f03c3002a0ac52114db25d2c673b0bf1e435" + +ignorefs@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ignorefs/-/ignorefs-1.2.0.tgz#da59fb858976e4a5e43702ccd1f282fdbc9e5756" + dependencies: + editions "^1.3.3" + ignorepatterns "^1.1.0" + +ignorepatterns@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ignorepatterns/-/ignorepatterns-1.1.0.tgz#ac8f436f2239b5dfb66d5f0d3a904a87ac67cc5e" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +indent-string@^1.1.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-1.2.2.tgz#db99bcc583eb6abbb1e48dcbb1999a986041cb6b" + dependencies: + get-stdin "^4.0.1" + minimist "^1.1.0" + repeating "^1.1.0" + +infinity-agent@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/infinity-agent/-/infinity-agent-2.0.3.tgz#45e0e2ff7a9eb030b27d62b74b3744b7a7ac4216" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + +ini@~1.3.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" + +inquirer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + figures "^1.3.5" + lodash "^4.3.0" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + +interpret@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c" + +invariant@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +ipaddr.js@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.1.1.tgz#c791d95f52b29c1247d5df80ada39b8a73647230" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.0.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-circular@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-circular/-/is-circular-1.0.1.tgz#65b0476a8588e546b8087c1d66d4c08d82a31679" + +is-dotfile@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-html@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-html/-/is-html-1.0.0.tgz#9cbbbfebd9ee11dc206683f3ecaf4df5b1633a1b" + dependencies: + html-tags "^1.0.0" + +is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4: + version "2.15.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-npm@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" + +is-number@^2.0.2, is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" + dependencies: + path-is-inside "^1.0.1" + +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + +is-redirect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + +is-resolvable@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" + dependencies: + tryit "^1.0.1" + +is-stream-ended@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.0.tgz#40f058df6b044ee598fee4df7dc1ec2bcdd8df60" + +is-stream@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +is@^3.0.1, is@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/is/-/is-3.2.0.tgz#a362e3daf7df3fd8b7114115d624c5b7e1cb90f7" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isemail@1.x.x: + version "1.2.0" + resolved "https://registry.yarnpkg.com/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a" + +isexe@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +istanbul-api@^1.0.0-alpha: + version "1.0.0-aplha.10" + resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.0.0-aplha.10.tgz#902edf5cf5404e0eba7e00ef46408488a0d3e337" + dependencies: + async "1.x" + clone "^1.0.2" + fileset "0.2.x" + istanbul-lib-coverage "^1.0.0-alpha" + istanbul-lib-hook "^1.0.0-alpha" + istanbul-lib-instrument "^1.0.0-alpha" + istanbul-lib-report "^1.0.0-alpha" + istanbul-lib-source-maps "^1.0.0-alpha" + istanbul-reports "^1.0.0-alpha" + js-yaml "3.x" + mkdirp "0.5.x" + once "1.x" + +istanbul-lib-coverage@^1.0.0, istanbul-lib-coverage@^1.0.0-alpha, istanbul-lib-coverage@^1.0.0-alpha.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.0.0.tgz#c3f9b6d226da12424064cce87fce0fb57fdfa7a2" + +istanbul-lib-hook@^1.0.0-alpha: + version "1.0.0-alpha.4" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.0-alpha.4.tgz#8c5bb9f6fbd8526e0ae6cf639af28266906b938f" + dependencies: + append-transform "^0.3.0" + +istanbul-lib-instrument@^1.0.0-alpha: + version "1.3.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.3.0.tgz#19f0a973397454989b98330333063a5b56df0e58" + dependencies: + babel-generator "^6.18.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + babylon "^6.13.0" + istanbul-lib-coverage "^1.0.0" + semver "^5.3.0" + +istanbul-lib-report@^1.0.0-alpha: + version "1.0.0-alpha.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.0.0-alpha.3.tgz#32d5f6ec7f33ca3a602209e278b2e6ff143498af" + dependencies: + async "^1.4.2" + istanbul-lib-coverage "^1.0.0-alpha" + mkdirp "^0.5.1" + path-parse "^1.0.5" + rimraf "^2.4.3" + supports-color "^3.1.2" + +istanbul-lib-source-maps@^1.0.0-alpha: + version "1.1.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.1.0.tgz#9d429218f35b823560ea300a96ff0c3bbdab785f" + dependencies: + istanbul-lib-coverage "^1.0.0-alpha.0" + mkdirp "^0.5.1" + rimraf "^2.4.4" + source-map "^0.5.3" + +istanbul-reports@^1.0.0-alpha: + version "1.0.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.0.0.tgz#24b4eb2b1d29d50f103b369bd422f6e640aa0777" + dependencies: + handlebars "^4.0.3" + +istanbul@^1.0.0-alpha.2: + version "1.0.0-alpha.2" + resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-1.0.0-alpha.2.tgz#06096bc08e98baad744aae46962d8df9fac63d08" + dependencies: + abbrev "1.0.x" + async "1.x" + istanbul-api "^1.0.0-alpha" + js-yaml "3.x" + mkdirp "0.5.x" + nopt "3.x" + which "^1.1.1" + wordwrap "^1.0.0" + +jodid25519@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" + dependencies: + jsbn "~0.1.0" + +joi@^6.10.1: + version "6.10.1" + resolved "https://registry.yarnpkg.com/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06" + dependencies: + hoek "2.x.x" + isemail "1.x.x" + moment "2.x.x" + topo "1.x.x" + +js-tokens@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-2.0.0.tgz#79903f5563ee778cc1162e6dcf1a0027c97f9cb5" + +js-yaml@3.x, js-yaml@^3.5.1: + version "3.7.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" + dependencies: + argparse "^1.0.7" + esprima "^2.6.0" + +jsbn@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@5.0.1, json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + +json5@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonparse@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.2.0.tgz#5c0c5685107160e72fe7489bddea0b44c2bc67bd" + +jsonpointer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.0.tgz#6661e161d2fc445f19f98430231343722e1fcbd5" + +jsonwebtoken@^7.1.6: + version "7.2.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.2.1.tgz#0fc7217473fc02b4c9aa1e188aa70b51bba4fccb" + dependencies: + joi "^6.10.1" + jws "^3.1.4" + lodash.once "^4.0.0" + ms "^0.7.1" + xtend "^4.0.1" + +jsprim@^1.2.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.3.1.tgz#2a7256f70412a29ee3670aaca625994c4dcff252" + dependencies: + extsprintf "1.0.2" + json-schema "0.2.3" + verror "1.3.6" + +jwa@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.1.5.tgz#a0552ce0220742cd52e153774a32905c30e756e5" + dependencies: + base64url "2.0.0" + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.9" + safe-buffer "^5.0.1" + +jwa@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.0.2.tgz#fd79609f1e772e299dce8ddb76d00659dd83511f" + dependencies: + base64url "~0.0.4" + buffer-equal-constant-time "^1.0.1" + ecdsa-sig-formatter "^1.0.0" + +jws@^3.0.0, jws@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.1.4.tgz#f9e8b9338e8a847277d6444b1464f61880e050a2" + dependencies: + base64url "^2.0.0" + jwa "^1.1.4" + safe-buffer "^5.0.1" + +jws@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.0.0.tgz#da5f267897dd4e9cf8137979db33fc54a3c05418" + dependencies: + base64url "~1.0.4" + jwa "~1.0.0" + +kareem@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/kareem/-/kareem-1.1.3.tgz#0877610d8879c38da62d1dbafde4e17f2692f041" + +kind-of@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47" + dependencies: + is-buffer "^1.0.2" + +latest-version@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-1.0.1.tgz#72cfc46e3e8d1be651e1ebb54ea9f6ea96f374bb" + dependencies: + package-json "^1.0.0" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + +lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" + +lodash._bindcallback@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" + +lodash._createassigner@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11" + dependencies: + lodash._bindcallback "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash.restparam "^3.0.0" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + +lodash.assign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa" + dependencies: + lodash._baseassign "^3.0.0" + lodash._createassigner "^3.0.0" + lodash.keys "^3.0.0" + +lodash.chunk@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.chunk/-/lodash.chunk-4.2.0.tgz#66e5ce1f76ed27b4303d8c6512e8d1216e8106bc" + +lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" + dependencies: + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" + +lodash.defaults@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-3.1.2.tgz#c7308b18dbf8bc9372d701a73493c61192bd2e2c" + dependencies: + lodash.assign "^3.0.0" + lodash.restparam "^3.0.0" + +lodash.flatten@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash.noop@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash.noop/-/lodash.noop-3.0.1.tgz#38188f4d650a3a474258439b96ec45b32617133c" + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + +lodash.restparam@^3.0.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + +lodash@^4.0.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.2.0, lodash@^4.3.0: + version "4.17.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.2.tgz#34a3055babe04ce42467b607d700072c7ff6bf42" + +lolex@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" + +long@~3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + +loose-envify@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.0.tgz#6b26248c42f6d4fa4b0d8542f78edfcde35642a8" + dependencies: + js-tokens "^2.0.0" + +lowercase-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" + +lsmod@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lsmod/-/lsmod-1.0.0.tgz#9a00f76dca36eb23fa05350afe1b585d4299e64b" + +make-plural@^3.0.3, make-plural@~3.0.3: + version "3.0.6" + resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-3.0.6.tgz#2033a03bac290b8f3bb91258f65b9df7e8b01ca7" + optionalDependencies: + minimist "^1.2.0" + +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + +map-stream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" + +math-interval-parser@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-interval-parser/-/math-interval-parser-1.1.0.tgz#dbeda5b06b3249973c6df6170fde2386f0afd893" + dependencies: + xregexp "^2.0.0" + +meanie-express-error-handling@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/meanie-express-error-handling/-/meanie-express-error-handling-1.8.2.tgz#d56c089c02975295fb2577aa9bde4849b8108e96" + dependencies: + chalk "^1.1.3" + +meanie-express-github-service@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/meanie-express-github-service/-/meanie-express-github-service-2.0.2.tgz#164b6167cb02949e0687ea567abdf28843fbed27" + dependencies: + bluebird "^3.4.1" + github "^1.1.2" + +meanie-express-jwt-service@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/meanie-express-jwt-service/-/meanie-express-jwt-service-1.0.2.tgz#141c7baeb5a99a2a3c99683155bd48507c9af2c9" + dependencies: + bluebird "^3.4.1" + jsonwebtoken "^7.1.6" + +meanie-express-raven-service@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/meanie-express-raven-service/-/meanie-express-raven-service-1.0.1.tgz#f2188d1a716350bf4c5eee6f173e81180b743aca" + dependencies: + raven "^0.12.1" + +meanie-mongoose-only-id@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/meanie-mongoose-only-id/-/meanie-mongoose-only-id-1.0.1.tgz#7fc86329b8f009ac254e65837cecec786f49c0f9" + +meanie-mongoose-set-properties@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/meanie-mongoose-set-properties/-/meanie-mongoose-set-properties-1.0.1.tgz#39f3347cf5f414b618cca52f13b458e7e3a0825d" + +meanie-mongoose-to-json@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/meanie-mongoose-to-json/-/meanie-mongoose-to-json-1.0.6.tgz#a1744aab5023b87ea5b8048e18b3d9117411dc21" + +meanie-multer-mime-types-filter@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/meanie-multer-mime-types-filter/-/meanie-multer-mime-types-filter-1.0.1.tgz#640042705028efacb628a5263d9c80a643f1094b" + +meanie-passport-refresh-strategy@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/meanie-passport-refresh-strategy/-/meanie-passport-refresh-strategy-1.1.2.tgz#cd3f0a0e855e32ed495c0a0ae8afe3c296f95f56" + dependencies: + passport-strategy "^1.0.0" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + +meow@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-2.0.0.tgz#8f530a8ecf5d40d3f4b4df93c3472900fba2a8f1" + dependencies: + camelcase-keys "^1.0.0" + indent-string "^1.1.0" + minimist "^1.1.0" + object-assign "^1.0.0" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + +messageformat@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/messageformat/-/messageformat-0.3.1.tgz#e58fff8245e9b3971799e5b43db58b3e9417f5a2" + dependencies: + async "~1.5.2" + glob "~6.0.4" + make-plural "~3.0.3" + nopt "~3.0.6" + watchr "~2.4.13" + +methmeth@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/methmeth/-/methmeth-1.1.0.tgz#e80a26618e52f5c4222861bb748510bd10e29089" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + +micromatch@^2.1.5: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +"mime-db@>= 1.24.0 < 2", mime-db@~1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.25.0.tgz#c18dbd7c73a5dbf6f44a024dc0d165a1e7b1c392" + +mime-types@^2.0.8, mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.13, mime-types@~2.1.7: + version "2.1.13" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.13.tgz#e07aaa9c6c6b9a7ca3012c69003ad25a39e92a88" + dependencies: + mime-db "~1.25.0" + +mime@1.3.4, mime@^1.2.11: + version "1.3.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" + +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" + +minimatch@2.x: + version "2.0.10" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" + dependencies: + brace-expansion "^1.0.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.1.0, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + +mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha-clean@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mocha-clean/-/mocha-clean-1.0.0.tgz#7e769b16cb38745df62a28917077953b05fec064" + +mocha@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.2.0.tgz#7dc4f45e5088075171a68896814e6ae9eb7a85e3" + dependencies: + browser-stdout "1.3.0" + commander "2.9.0" + debug "2.2.0" + diff "1.4.0" + escape-string-regexp "1.0.5" + glob "7.0.5" + growl "1.9.2" + json3 "3.3.2" + lodash.create "3.1.1" + mkdirp "0.5.1" + supports-color "3.1.2" + +modelo@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/modelo/-/modelo-4.2.0.tgz#3b4b420023a66ca7e32bdba16e710937e14d1b0b" + +moment@2.x.x, moment@^2.17.1: + version "2.17.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.17.1.tgz#fed9506063f36b10f066c8b59a144d7faebe1d82" + +mongodb-core@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.0.14.tgz#4e8743b87343d169a7622535edbd47dcacd790be" + dependencies: + bson "~0.5.7" + require_optional "~1.0.0" + +mongodb@2.2.12: + version "2.2.12" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.12.tgz#2a86f10228f911e9d6fefdbd7d922188d7b730f9" + dependencies: + es6-promise "3.2.1" + mongodb-core "2.0.14" + readable-stream "2.1.5" + +mongoose@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.7.2.tgz#e8ed06353c918169bec886cdc0c2077a93682faa" + dependencies: + async "2.1.4" + bson "~0.5.4" + hooks-fixed "1.2.0" + kareem "1.1.3" + mongodb "2.2.12" + mpath "0.2.1" + mpromise "0.5.5" + mquery "2.0.0" + ms "0.7.2" + muri "1.1.1" + regexp-clone "0.0.1" + sliced "1.0.1" + +morgan@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.7.0.tgz#eb10ca8e50d1abe0f8d3dad5c0201d052d981c62" + dependencies: + basic-auth "~1.0.3" + debug "~2.2.0" + depd "~1.1.0" + on-finished "~2.3.0" + on-headers "~1.0.1" + +mpath@0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.2.1.tgz#3a4e829359801de96309c27a6b2e102e89f9e96e" + +mpromise@0.5.5: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mpromise/-/mpromise-0.5.5.tgz#f5b24259d763acc2257b0a0c8c6d866fd51732e6" + +mquery@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mquery/-/mquery-2.0.0.tgz#b5abc850b90dffc3e10ae49b4b6e7a479752df22" + dependencies: + bluebird "2.10.2" + debug "2.2.0" + regexp-clone "0.0.1" + sliced "0.0.5" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + +ms@0.7.2, ms@^0.7.1: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + +multer@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/multer/-/multer-1.2.0.tgz#5be1a45259fb04d2753d33c7c2a1caf5224705a2" + dependencies: + append-field "^0.1.0" + busboy "^0.2.11" + concat-stream "^1.5.0" + mkdirp "^0.5.1" + object-assign "^3.0.0" + on-finished "^2.3.0" + type-is "^1.6.4" + xtend "^4.0.0" + +muri@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/muri/-/muri-1.1.1.tgz#64bd904eaf8ff89600c994441fad3c5195905ac2" + +mustache@*: + version "2.3.0" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.0.tgz#4028f7778b17708a489930a6e52ac3bca0da41d0" + +mute-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" + +nan@2.3.5, nan@^2.0.0, nan@^2.3.0: + version "2.3.5" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.3.5.tgz#822a0dc266290ce4cd3a12282ca3e7e364668a08" + +native-promise-only@~0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + +nested-error-stacks@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-1.0.2.tgz#19f619591519f096769a5ba9a86e6eeec823c3cf" + dependencies: + inherits "~2.0.1" + +node-forge@^0.6.33: + version "0.6.46" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.46.tgz#04a8a1c336eb72ef6f434ba7c854d608916c328d" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + +node-pre-gyp@0.6.30: + version "0.6.30" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.30.tgz#64d3073a6f573003717ccfe30c89023297babba1" + dependencies: + mkdirp "~0.5.0" + nopt "~3.0.1" + npmlog "4.x" + rc "~1.1.0" + request "2.x" + rimraf "~2.5.0" + semver "~5.3.0" + tar "~2.2.0" + tar-pack "~3.1.0" + +node-pre-gyp@^0.6.0, node-pre-gyp@^0.6.29: + version "0.6.32" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.32.tgz#fc452b376e7319b3d255f5f34853ef6fd8fe1fd5" + dependencies: + mkdirp "~0.5.1" + nopt "~3.0.6" + npmlog "^4.0.1" + rc "~1.1.6" + request "^2.79.0" + rimraf "~2.5.4" + semver "~5.3.0" + tar "~2.2.1" + tar-pack "~3.3.0" + +node-status-codes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f" + +node-uuid@~1.4.7: + version "1.4.7" + resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.7.tgz#6da5a17668c4b3dd59623bda11cf7fa4c1f60a6f" + +nodemon@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.11.0.tgz#226c562bd2a7b13d3d7518b49ad4828a3623d06c" + dependencies: + chokidar "^1.4.3" + debug "^2.2.0" + es6-promise "^3.0.2" + ignore-by-default "^1.0.0" + lodash.defaults "^3.1.2" + minimatch "^3.0.0" + ps-tree "^1.0.1" + touch "1.0.0" + undefsafe "0.0.3" + update-notifier "0.5.0" + +nopt@3.x, nopt@~3.0.1, nopt@~3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + dependencies: + abbrev "1" + +normalize-package-data@^2.3.2: + version "2.3.5" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.5.tgz#8d924f142960e1777e7ffe170543631cc7cb02df" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" + +npmlog@4.x, npmlog@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.1.tgz#d14f503b4cd79710375553004ba96e6662fbc0b8" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.1" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-1.0.0.tgz#e65dc8766d3b47b4b8307465c8311da030b070a6" + +object-assign@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" + +object-assign@^4.0.1, object-assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + +object.omit@^2.0.0, object.omit@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +on-finished@^2.3.0, on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" + +once@1.x, once@^1.3.0, once@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +once@~1.3.0, once@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" + dependencies: + wrappy "1" + +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +optjs@~3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/optjs/-/optjs-3.2.2.tgz#69a6ce89c442a44403141ad2f9b370bd5bb6f4ee" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + dependencies: + lcid "^1.0.0" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@^0.1.0: + version "0.1.3" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.3.tgz#83cf05c6d6458fc4d5ac6362ea325d92f2754217" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +output-file-sync@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76" + dependencies: + graceful-fs "^4.1.4" + mkdirp "^0.5.1" + object-assign "^4.1.0" + +package-json@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-1.2.0.tgz#c8ecac094227cdf76a316874ed05e27cc939a0e0" + dependencies: + got "^3.2.0" + registry-url "^3.0.0" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-json@^2.1.0, parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +parseurl@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56" + +passport-http-bearer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz#147469ea3669e2a84c6167ef99dbb77e1f0098a8" + dependencies: + passport-strategy "1.x.x" + +passport-local@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee" + dependencies: + passport-strategy "1.x.x" + +passport-strategy@1.x.x, passport-strategy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" + +passport@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.3.2.tgz#9dd009f915e8fe095b0124a01b8f82da07510102" + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +pause-stream@0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + dependencies: + through "~2.3" + +pause@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-1.0.0.tgz#d1da67f5482563bb7cf57f286ae2822ecfbf3670" + dependencies: + pinkie "^1.0.0" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-1.0.0.tgz#5a47f28ba1015d0201bda7bf0f358e47bec8c7e4" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pluralize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +prepend-http@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +private@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.6.tgz#55c6a976d0f9bafb9924851350fe47b9b5fbb7c1" + +process-nextick-args@^1.0.7, process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +progress@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + +prop-assign@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prop-assign/-/prop-assign-1.0.0.tgz#9767a1fbfd7093908647a6e846d31b4feaa70459" + +propprop@^0.3.0, propprop@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/propprop/-/propprop-0.3.1.tgz#a049a3568b896440067d15d8ec9f33735e570178" + +protobufjs@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-5.0.1.tgz#589ecdda1a555fd69df4699adc142d36f133aa0b" + dependencies: + ascli "~1" + bytebuffer "~5" + glob "^5.0.10" + yargs "^3.10.0" + +proxy-addr@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.2.tgz#b4cc5f22610d9535824c123aef9d3cf73c40ba37" + dependencies: + forwarded "~0.1.0" + ipaddr.js "1.1.1" + +ps-tree@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014" + dependencies: + event-stream "~3.3.0" + +pump@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.1.tgz#f1f1409fb9bd1085bbdb576b43b84ec4b5eadc1a" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3, pumpify@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.3.5.tgz#1b671c619940abcaeac0ad0e3a3c164be760993b" + dependencies: + duplexify "^3.1.2" + inherits "^2.0.1" + pump "^1.0.0" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +qs@6.2.0, qs@~6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.0.tgz#3b7848c03c2dece69a9522b0fae8c4126d745f3b" + +qs@~6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.0.tgz#f403b264f23bc01228c74131b407f18d5ea5d442" + +randomatic@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb" + dependencies: + is-number "^2.0.2" + kind-of "^3.0.2" + +range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + +raven@^0.12.1: + version "0.12.3" + resolved "https://registry.yarnpkg.com/raven/-/raven-0.12.3.tgz#1a70f04a2240d291d83603b40162c4bada71325c" + dependencies: + cookie "0.3.1" + json-stringify-safe "5.0.1" + lsmod "1.0.0" + stack-trace "0.0.9" + uuid "3.0.0" + +raw-body@~2.1.7: + version "2.1.7" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.1.7.tgz#adfeace2e4fb3098058014d08c072dcc59758774" + dependencies: + bytes "2.4.0" + iconv-lite "0.4.13" + unpipe "1.0.0" + +rc@^1.0.1, rc@~1.1.0, rc@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~1.0.4" + +read-all-stream@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/read-all-stream/-/read-all-stream-3.1.0.tgz#35c3e177f2078ef789ee4bfafa4373074eaef4fa" + dependencies: + pinkie-promise "^2.0.0" + readable-stream "^2.0.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +readable-stream@1.1.x, readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@2.1.5, readable-stream@^2.0.0, readable-stream@^2.1.5, readable-stream@~2.1.4: + version "2.1.5" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0" + dependencies: + buffer-shims "^1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.2, readable-stream@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e" + dependencies: + buffer-shims "^1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +readable-stream@~2.0.0, readable-stream@~2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + +readline2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + mute-stream "0.0.5" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + dependencies: + resolve "^1.1.6" + +regenerate@^1.2.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" + +regenerator-runtime@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.1.tgz#257f41961ce44558b18f7814af48c17559f9faeb" + +regenerator-transform@0.9.8: + version "0.9.8" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.8.tgz#0f88bb2bc03932ddb7b6b7312e68078f01026d6c" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-cache@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" + dependencies: + is-equal-shallow "^0.1.3" + is-primitive "^2.0.0" + +regexp-clone@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-0.0.1.tgz#a7c2e09891fdbf38fbb10d376fb73003e68ac589" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +registry-url@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + dependencies: + rc "^1.0.1" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^1.1.0, repeating@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-1.1.3.tgz#3d4114218877537494f97f77f9785fab810fa4ac" + dependencies: + is-finite "^1.0.0" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request@2.76.0: + version "2.76.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.76.0.tgz#be44505afef70360a0436955106be3945d95560e" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + node-uuid "~1.4.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + +request@2.x, request@^2.61.0, request@^2.70.0, request@^2.72.0, request@^2.74.0, request@^2.79.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" + +request@~2.74.0: + version "2.74.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.74.0.tgz#7693ca768bbb0ea5c8ce08c084a45efa05b892ab" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + bl "~1.1.2" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~1.0.0-rc4" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + node-uuid "~1.4.7" + oauth-sign "~0.8.1" + qs "~6.2.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + +require-uncached@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +require_optional@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.0.tgz#52a86137a849728eb60a55533617f8f914f59abf" + dependencies: + resolve-from "^2.0.0" + semver "^5.1.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" + +resolve@^1.1.6: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + +retry-request@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-1.3.2.tgz#59ad24e71f8ae3f312d5f7b4bcf467a5e5a57bd6" + dependencies: + request "2.76.0" + through2 "^2.0.0" + +rgb-hex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgb-hex/-/rgb-hex-1.0.0.tgz#bfaf8cd9cd9164b5a26d71eb4f15a0965324b3c1" + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + dependencies: + align-text "^0.1.1" + +rimraf@2, rimraf@^2.2.8, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@~2.5.0, rimraf@~2.5.1, rimraf@~2.5.4: + version "2.5.4" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04" + dependencies: + glob "^7.0.5" + +run-async@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + dependencies: + once "^1.3.0" + +rx-lite@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" + +safe-buffer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" + +safefs@^3.1.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/safefs/-/safefs-3.2.2.tgz#8170c1444d7038e08caea05a374fae2fa349e15c" + dependencies: + graceful-fs "*" + +samsam@1.1.2, samsam@~1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" + +scandirectory@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/scandirectory/-/scandirectory-2.5.0.tgz#6ce03f54a090b668e3cbedbf20edf9e310593e72" + dependencies: + ignorefs "^1.0.0" + safefs "^3.1.2" + taskgroup "^4.0.5" + +semver-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + dependencies: + semver "^5.0.3" + +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +semver@~5.0.1: + version "5.0.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" + +send@0.14.1: + version "0.14.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.14.1.tgz#a954984325392f51532a7760760e459598c89f7a" + dependencies: + debug "~2.2.0" + depd "~1.1.0" + destroy "~1.0.4" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.7.0" + fresh "0.3.0" + http-errors "~1.5.0" + mime "1.3.4" + ms "0.7.1" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.3.0" + +sendgrid-mailer@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/sendgrid-mailer/-/sendgrid-mailer-1.0.7.tgz#ea24fc7c748db75daf5db05cbb3dd4dadd6f9234" + +sendgrid-rest@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/sendgrid-rest/-/sendgrid-rest-2.3.0.tgz#662ef95a93c73c3e0a4e7a61e3880a10c78dd24a" + +sendgrid@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/sendgrid/-/sendgrid-4.7.1.tgz#38a6f1798dcdbb46361767ae4f5271104dcd232f" + dependencies: + async.ensureasync "^0.5.2" + async.queue "^0.5.2" + bottleneck "^1.12.0" + debug "^2.2.0" + lodash.chunk "^4.2.0" + sendgrid-rest "^2.3.0" + +serve-static@~1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.11.1.tgz#d6cce7693505f733c759de57befc1af76c0f0805" + dependencies: + encodeurl "~1.0.1" + escape-html "~1.0.3" + parseurl "~1.3.1" + send "0.14.1" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + +setprototypeof@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08" + +shelljs@^0.7.5: + version "0.7.5" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.5.tgz#2eef7a50a21e1ccf37da00df767ec69e30ad0675" + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +sinon-as-promised@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/sinon-as-promised/-/sinon-as-promised-4.0.2.tgz#120e9ce033daa39648dc429062fe660be1b5b412" + dependencies: + create-thenable "~1.0.0" + native-promise-only "~0.8.1" + +sinon-mongoose@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/sinon-mongoose/-/sinon-mongoose-1.3.0.tgz#2a2c75c36e9d7b665390f23fc7f91d548f580e45" + +sinon@^1.17.6: + version "1.17.6" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.6.tgz#a43116db59577c8296356afee13fafc2332e58e1" + dependencies: + formatio "1.1.1" + lolex "1.3.2" + samsam "1.1.2" + util ">=0.10.3 <1" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + +sliced@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/sliced/-/sliced-0.0.5.tgz#5edc044ca4eb6f7816d50ba2fc63e25d8fe4707f" + +sliced@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41" + +slide@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +source-map-support@^0.4.2: + version "0.4.6" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.6.tgz#32552aa64b458392a85eab3b0b5ee61527167aeb" + dependencies: + source-map "^0.5.3" + +source-map@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +source-map@^0.5.0, source-map@^0.5.3, source-map@~0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + +spdx-correct@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" + dependencies: + spdx-license-ids "^1.0.2" + +spdx-expression-parse@~1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" + +spdx-license-ids@^1.0.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" + +split-array-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/split-array-stream/-/split-array-stream-1.0.0.tgz#d5e4ffacd306161d69ed5252ff56d57e7762eaa2" + dependencies: + async "^1.4.0" + is-stream-ended "^0.1.0" + +split@0.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" + dependencies: + through "2" + +sprintf-js@>=1.0.3, sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.10.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.10.1.tgz#30e1a5d329244974a1af61511339d595af6638b0" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jodid25519 "^1.0.0" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +stack-trace@0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695" + +"statuses@>= 1.3.1 < 2", statuses@~1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" + +stream-combiner@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" + dependencies: + duplexer "~0.1.1" + +stream-consume@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.0.tgz#a41ead1a6d6081ceb79f65b061901b6d8f3d1d0f" + +stream-events@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.1.tgz#4fe7b2bbfcc53e6af31087e8c540483f412ce8c6" + dependencies: + stubs "^1.1.0" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + +streamsearch@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" + +string-format-obj@^1.0.0, string-format-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/string-format-obj/-/string-format-obj-1.1.0.tgz#7635610b1ef397013e8478be98a170e04983d068" + +string-length@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac" + dependencies: + strip-ansi "^3.0.0" + +string-template@~0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^3.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +stringstream@~0.0.4: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-json-comments@~1.0.1, strip-json-comments@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" + +stubs@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/stubs/-/stubs-1.1.2.tgz#945a08975016318762f8f7060731002ab2a0960c" + +supports-color@3.1.2, supports-color@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + dependencies: + has-flag "^1.0.0" + +supports-color@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +table@^3.7.8: + version "3.8.3" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + +tar-pack@~3.1.0: + version "3.1.4" + resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.1.4.tgz#bc8cf9a22f5832739f12f3910dac1eb97b49708c" + dependencies: + debug "~2.2.0" + fstream "~1.0.10" + fstream-ignore "~1.0.5" + once "~1.3.3" + readable-stream "~2.1.4" + rimraf "~2.5.1" + tar "~2.2.1" + uid-number "~0.0.6" + +tar-pack@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.3.0.tgz#30931816418f55afc4d21775afdd6720cee45dae" + dependencies: + debug "~2.2.0" + fstream "~1.0.10" + fstream-ignore "~1.0.5" + once "~1.3.3" + readable-stream "~2.1.4" + rimraf "~2.5.1" + tar "~2.2.1" + uid-number "~0.0.6" + +tar@~2.2.0, tar@~2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +taskgroup@^4.0.5, taskgroup@^4.2.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/taskgroup/-/taskgroup-4.3.1.tgz#7de193febd768273c457730497024d512c27915a" + dependencies: + ambi "^2.2.0" + csextends "^1.0.3" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +through2@^2.0.0, through2@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +timed-out@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a" + +to-fast-properties@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320" + +topo@1.x.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/topo/-/topo-1.1.0.tgz#e9d751615d1bb87dc865db182fa1ca0a5ef536d5" + dependencies: + hoek "2.x.x" + +touch@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/touch/-/touch-1.0.0.tgz#449cbe2dbae5a8c8038e30d71fa0ff464947c4de" + dependencies: + nopt "~1.0.10" + +tough-cookie@~2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" + dependencies: + punycode "^1.4.1" + +tryit@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" + +tunnel-agent@~0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.4" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.4.tgz#8c9dbfb52795686f166cd2023794bcf103d13c2b" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +type-detect@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" + +type-detect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" + +type-is@^1.6.4, type-is@~1.6.13: + version "1.6.14" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.14.tgz#e219639c17ded1ca0789092dd54a03826b817cb2" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.13" + +typechecker@^2.0.8: + version "2.1.0" + resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.1.0.tgz#d1c2093a54ff8a19f58cff877eeaa54f2242d383" + +typechecker@^4.3.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-4.4.0.tgz#efc56882d36e435c6eb978200e22b88278a3f7fc" + dependencies: + editions "^1.3.3" + +typechecker@~2.0.1: + version "2.0.8" + resolved "https://registry.yarnpkg.com/typechecker/-/typechecker-2.0.8.tgz#e83da84bb64c584ccb345838576c40b0337db82e" + +typedarray@~0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +uglify-js@^2.6: + version "2.7.5" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" + dependencies: + async "~0.2.6" + source-map "~0.5.1" + uglify-to-browserify "~1.0.0" + yargs "~3.10.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + +uid-number@~0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + +undefsafe@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-0.0.3.tgz#ecca3a03e56b9af17385baac812ac83b994a962f" + +unique-concat@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/unique-concat/-/unique-concat-0.2.2.tgz#9210f9bdcaacc5e1e3929490d7c019df96f18712" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +unzip-response@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe" + +update-notifier@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.5.0.tgz#07b5dc2066b3627ab3b4f530130f7eddda07a4cc" + dependencies: + chalk "^1.0.0" + configstore "^1.0.0" + is-npm "^1.0.0" + latest-version "^1.0.0" + repeating "^1.1.2" + semver-diff "^2.0.0" + string-length "^1.0.0" + +user-home@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" + +user-home@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" + dependencies: + os-homedir "^1.0.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +"util@>=0.10.3 <1": + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + dependencies: + inherits "2.0.1" + +utils-merge@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" + +uuid@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.0.tgz#6728fc0459c450d796a99c31837569bdf672d728" + +uuid@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" + +uuid@^3.0.0, uuid@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" + +v8flags@^2.0.10: + version "2.0.11" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.0.11.tgz#bca8f30f0d6d60612cc2c00641e6962d42ae6881" + dependencies: + user-home "^1.1.1" + +validate-npm-package-license@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + dependencies: + spdx-correct "~1.0.0" + spdx-expression-parse "~1.0.0" + +vary@^1, vary@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.0.tgz#e1e5affbbd16ae768dd2674394b9ad3022653140" + +verror@1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" + dependencies: + extsprintf "1.0.2" + +watchr@~2.4.13: + version "2.4.13" + resolved "https://registry.yarnpkg.com/watchr/-/watchr-2.4.13.tgz#d74847bb4d6f90f61fe2c74f9f68662aa0e07601" + dependencies: + eachr "^2.0.2" + extendr "^2.1.0" + extract-opts "^2.2.0" + ignorefs "^1.0.0" + safefs "^3.1.2" + scandirectory "^2.5.0" + taskgroup "^4.2.0" + typechecker "^2.0.8" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + +which@^1.1.1: + version "1.2.12" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192" + dependencies: + isexe "^1.1.1" + +wide-align@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad" + dependencies: + string-width "^1.0.1" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + +window-size@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + +wordwrap@^1.0.0, wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write-file-atomic@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.2.0.tgz#14c66d4e4cb3ca0565c28cf3b7a6f3e4d5938fab" + dependencies: + graceful-fs "^4.1.2" + imurmurhash "^0.1.4" + slide "^1.1.5" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + +xdg-basedir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-2.0.0.tgz#edbc903cc385fc04523d966a335504b5504d1bd2" + dependencies: + os-homedir "^1.0.0" + +xregexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" + +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +yargs-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.0.tgz#6ced869cd05a3dca6a1eaee38b68aeed4b0b4101" + dependencies: + camelcase "^3.0.0" + +yargs@^3.10.0, yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" + +yargs@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.5.0.tgz#a902e23a1f0fe912b2a03f6131b7ed740c9718ff" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + window-size "^0.2.0" + y18n "^3.2.1" + yargs-parser "^4.2.0"