├── .vscode └── settings.json ├── services_conf ├── haproxy.js ├── hhvm.js ├── redis.js ├── main.js ├── services.js ├── nginx.js ├── node.js ├── php.js └── mysql.js ├── bash ├── down ├── up_prod ├── up_dev ├── save.images ├── stack.deploy ├── init ├── reset ├── compose.deploy └── setup ├── .gitignore ├── LICENSE ├── package.json ├── README.md ├── index.js └── yarn.lock /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.enable": false 3 | } -------------------------------------------------------------------------------- /services_conf/haproxy.js: -------------------------------------------------------------------------------- 1 | module.exports.prompt = null 2 | 3 | module.exports.map = null 4 | 5 | module.exports.path = null 6 | 7 | module.exports.defaults = null 8 | 9 | module.exports.dependencies = null -------------------------------------------------------------------------------- /services_conf/hhvm.js: -------------------------------------------------------------------------------- 1 | module.exports.prompt = null 2 | 3 | module.exports.map = null 4 | 5 | module.exports.path = null 6 | 7 | module.exports.defaults = null 8 | 9 | module.exports.dependencies = null -------------------------------------------------------------------------------- /services_conf/redis.js: -------------------------------------------------------------------------------- 1 | module.exports.prompt = null 2 | 3 | module.exports.map = null 4 | 5 | module.exports.path = null 6 | 7 | module.exports.defaults = null 8 | 9 | module.exports.dependencies = null -------------------------------------------------------------------------------- /bash/down: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exu 4 | 5 | ## loading .environment variables if exist 6 | if [ -f .env ]; then . .env; fi 7 | if [ -f ../.env ]; then . ../.env; fi 8 | 9 | docker-compose down --remove-orphans -------------------------------------------------------------------------------- /bash/up_prod: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exu 4 | 5 | ## loading .environment variables if exist 6 | if [ -f .env ]; then . .env; fi 7 | if [ -f ../.env ]; then . ../.env; fi 8 | 9 | . ./init && docker-compose -f ../docker-compose.yml up -d --build 10 | 11 | -------------------------------------------------------------------------------- /bash/up_dev: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exu 4 | 5 | ## loading .environment variables if exist 6 | if [ -f .env ]; then . .env; fi 7 | if [ -f ../.env ]; then . ../.env; fi 8 | 9 | docker-compose -f ../docker-compose.yml -f ../docker-compose.dev.yml up -d --build --remove-orphans -------------------------------------------------------------------------------- /bash/save.images: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exu 4 | 5 | ## loading .environment variables if exist 6 | if [ -f .env ]; then . .env; fi 7 | if [ -f ../.env ]; then . ../.env; fi 8 | 9 | ## get all running containers 10 | ## filter by projectname 11 | 12 | echo "$PROJECT_NAME" -------------------------------------------------------------------------------- /bash/stack.deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exu 4 | 5 | ## loading .environment variables if exist 6 | if [ -f .env ]; then . .env; fi 7 | if [ -f ../.env ]; then . ../.env; fi 8 | 9 | echo "Make sure you're running this command in a Docker Swarm environment"; 10 | docker stack deploy -------------------------------------------------------------------------------- /bash/init: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exu 4 | 5 | ## loading .environment variables if exist 6 | if [ -f .env ]; then . .env; fi 7 | if [ -f ../.env ]; then . ../.env; fi 8 | 9 | echo "Setting up global network for multiple projects (if not exists)" 10 | 11 | if [ `docker network ls | grep -c network_main` != 1 ]; then 12 | docker-compose -f ../network/docker-compose.yml up -d; 13 | else 14 | echo "Network had already been set"; 15 | fi 16 | -------------------------------------------------------------------------------- /bash/reset: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exu 4 | 5 | ## loading .environment variables if exist 6 | if [ -f .env ]; then . .env; fi 7 | if [ -f ../.env ]; then . ../.env; fi 8 | 9 | echo "-----------------------------------------------" 10 | echo "Careful! This command is to be used only on" 11 | echo "development environments" 12 | echo "-----------------------------------------------" 13 | echo "It will delete all docker networks and volumes" 14 | echo "along with all orphan containers" 15 | echo "\n\n" 16 | 17 | docker-compose down --remove-orphans 18 | 19 | docker network prune -f 20 | docker volume prune -f 21 | -------------------------------------------------------------------------------- /bash/compose.deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exu 4 | 5 | ## loading .environment variables if exist 6 | if [ -f .env ]; then . .env; fi 7 | if [ -f ../.env ]; then . ../.env; fi 8 | 9 | ## info 10 | echo "\n For better understanding check https://docs.docker.com/machine/overview/" 11 | echo "\n" 12 | 13 | if [ -z $DOCKER_HOST -o -z $DOCKER_TLS_VERIFY -o -z $DOCKER_CERT_PATH ]; then 14 | echo "Please set DOCKER_HOST, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH" 15 | echo "if you want to deploy to a remote server" 16 | fi 17 | 18 | if [ ! -z $1 ]; then 19 | docker-compose build $1 20 | docker-compose up --no-deps -d $1 21 | else 22 | echo "Please enter the name of the service you want to deploy" 23 | fi -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ani Sinanaj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /services_conf/main.js: -------------------------------------------------------------------------------- 1 | module.exports.prompt = [{ 2 | name: "DB_PORT", 3 | default: 8806, 4 | message: "DBMS Port".magenta 5 | }, { 6 | default: process.cwd().split("/").pop(), 7 | name: "PROJECT_NAME", 8 | required: true, 9 | validate: input => !/(?=.*[A-Z])/g.test(input) || "Project name must be lowercase", 10 | message: "Project name".magenta 11 | }, { 12 | default: '1.0.0', 13 | name: "VERSION", 14 | message: "Version of the project".magenta 15 | }, { 16 | default: 'registry.progress44.com', 17 | name: "REGISTRY", 18 | message: "Docker registry address".magenta 19 | }, { 20 | default: 'master', 21 | name: "GIT_BRANCH", 22 | message: "Project branch".magenta 23 | }, { 24 | default: process.cwd().split("/").pop(), 25 | name: "COMPOSE_PROJECT_NAME", 26 | required: false, 27 | message: "Project name + branch".magenta, 28 | when: q => { 29 | q.COMPOSE_PROJECT_NAME = q.GIT_BRANCH.toLowerCase() + q.PROJECT_NAME.toLowerCase() 30 | return false 31 | } 32 | }] 33 | 34 | module.exports.map = { 35 | DB_PORT: "DB_PORT", 36 | PROJECT_NAME: "PROJECT_NAME", 37 | COMPOSE_PROJECT_NAME: "COMPOSE_PROJECT_NAME", 38 | GIT_BRANCH: "GIT_BRANCH", 39 | VERSION: "VERSION", 40 | REGISTRY: "REGISTRY" 41 | } 42 | 43 | module.exports.path = "" 44 | 45 | module.exports.defaults = null 46 | 47 | module.exports.dependencies = [ 48 | { PHP_MODS: {php: "PHP_MODS"} } 49 | ] -------------------------------------------------------------------------------- /services_conf/services.js: -------------------------------------------------------------------------------- 1 | module.exports.prompt = [{ 2 | type: 'checkbox', 3 | name: 'services', 4 | message: "Which services will you use?".magenta, 5 | pageSize: 5, 6 | choices: [{ 7 | name: "Php 7", 8 | value: "php7" 9 | }, { 10 | name: "Php 5", 11 | value: "legacy" 12 | }, { 13 | name: "HHVM", 14 | value: "hhvm" 15 | }, { 16 | name: "Redis", 17 | value: "redis" 18 | }, { 19 | name: "NodeJS", 20 | value: "node" 21 | }, { 22 | name: "influxDB", 23 | value: "influxdb" 24 | }, { 25 | name: "MongoDB", 26 | value: "mongodb" 27 | }, { 28 | name: "MySQL", 29 | value: "mysql" 30 | }, { 31 | name: "Nginx", 32 | value: "nginx" 33 | }, { 34 | name: "Tensorflow", 35 | value: "tensorflow" 36 | }, { 37 | name: "ElasticSearch", 38 | value: "elasticsearch" 39 | }, { 40 | name: "Kibana", 41 | value: "kibana" 42 | }, { 43 | name: "Logstash", 44 | value: "logstash" 45 | }, { 46 | name: "Email Server", 47 | value: "mailer" 48 | }, { 49 | name: "Registry", 50 | value: "registry" 51 | }, { 52 | name: "LDAP Server", 53 | value: "ldapserver" 54 | }] 55 | }] 56 | 57 | module.exports.map = {} 58 | 59 | module.exports.path = null 60 | 61 | module.exports.dependencies = null -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blimpair", 3 | "version": "1.0.12-beta", 4 | "description": "Docker web framework initializer", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/blimpair/blimp.git" 9 | }, 10 | "keywords": [ 11 | "docker", 12 | "web" 13 | ], 14 | "bin": { 15 | "blimp": "./index.js" 16 | }, 17 | "author": "Ani Sinanaj", 18 | "license": "MIT", 19 | "bugs": { 20 | "type": "git", 21 | "url": "https://github.com/blimpair/blimp/issues" 22 | }, 23 | "homepage": "https://github.com/blimpair/blimp#readme", 24 | "preferGlobal": true, 25 | "debug": false, 26 | "dependencies": { 27 | "async": "^2.3.0", 28 | "colors": "^1.1.2", 29 | "commander": "^2.9.0", 30 | "fs-extended": "^0.2.1", 31 | "generate-password": "^1.3.0", 32 | "gm": "^1.23.1", 33 | "image-size": "^0.5.1", 34 | "inquirer": "^3.0.6", 35 | "js-yaml": "^3.8.3", 36 | "node-env-file": "^0.1.8", 37 | "pem": "^1.9.4", 38 | "prompt": "^1.0.0", 39 | "q": "^1.5.0", 40 | "request": "^2.87.0", 41 | "shell-escape": "^0.2.0", 42 | "simple-git": "^1.72.0", 43 | "uglifyjs": "^2.4.10", 44 | "underscore": "^1.8.3", 45 | "underscore.string": "^3.3.4", 46 | "universal-analytics": "^0.4.13", 47 | "unzip": "^0.1.11", 48 | "update-notifier": "^2.1.0", 49 | "yamljs": "^0.2.10" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /bash/setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exu 4 | 5 | ## loading .environment variables if exist 6 | if [ -f .env ]; then . .env; fi 7 | if [ -f ../.env ]; then . ../.env; fi 8 | 9 | if [ ! -z "$1" -a "$1" == "ubuntu" ]; then 10 | 11 | echo $2 | sudo -S 12 | 13 | apt-get update 14 | apt-get upgrade -y 15 | 16 | apt-get install apt-transport-https ca-certificates 17 | sudo apt-key adv \ 18 | --keyserver hkp://ha.pool.sks-keyservers.net:80 \ 19 | --recv-keys 58118E89F3A912897C070ADBF76221572C52609D 20 | 21 | apt-get install linux-image-extra-$(uname -r) linux-image-extra-virtual 22 | echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list 23 | apt-get update 24 | 25 | apt-get install docker-engine 26 | service docker start 27 | 28 | curl -L https://github.com/docker/compose/releases/download/1.11.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose 29 | chmod +x /usr/local/bin/docker-compose 30 | fi 31 | 32 | if [ ! -z "$1" -a "$1" == "debian" ]; then 33 | 34 | apt-get update 35 | apt-get upgrade -y 36 | 37 | echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/docker.list 38 | 39 | apt-get install -y --no-install-recommends \ 40 | apt-transport-https \ 41 | ca-certificates \ 42 | curl \ 43 | software-properties-common 44 | 45 | curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - 46 | 47 | apt-key fingerprint 0EBFCD88 48 | 49 | add-apt-repository \ 50 | "deb [arch=amd64] https://download.docker.com/linux/debian \ 51 | $(lsb_release -cs) \ 52 | stable" 53 | 54 | apt-get update 55 | 56 | if [ ! -z $PRODUCTION ]; then 57 | apt-cache madison docker-ce 58 | docker-ce | 17.03.0~ce-0~debian-$(lsb_release -cs) | https://download.docker.com/linux/debian jessie/stable amd64 Packages 59 | 60 | #apt-get install docker-ce= -y --no-install-recommends 61 | else 62 | apt-get install docker-ce -y --no-install-recommends 63 | fi 64 | fi -------------------------------------------------------------------------------- /services_conf/nginx.js: -------------------------------------------------------------------------------- 1 | module.exports.prompt = { // use nested prompt 2 | "development": [{ 3 | name: "VIRTUAL_HOST", 4 | message: "[VIRTUAL_HOST] Domain(s) managed by this project's nginx".magenta, 5 | default: "localhost", 6 | required: true 7 | }], 8 | "production": [{ 9 | name: "VIRTUAL_HOST", 10 | message: "[VIRTUAL_HOST] Domain(s) managed by this project's nginx".magenta, 11 | default: "domain.com", 12 | required: true 13 | }, { 14 | name: "LETSENCRYPT_ENABLED", 15 | message: "Do you want to enable SSL with Let's encrypt?".magenta, 16 | type: 'list', 17 | pageSize: 2, 18 | required: true, 19 | choices: [{ 20 | name: "yes", 21 | value: 1 22 | }, { 23 | name: "no", 24 | value: 0 25 | }] 26 | }, { 27 | name: "LETSENCRYPT_EMAIL", 28 | message: "Email to use for Let's Encrypt certificates".magenta, 29 | default: "dev@caffeina.com", 30 | when: q => q.LETSENCRYPT_ENABLED === 1, 31 | required: true 32 | }, { 33 | name: "LETSENCRYPT_HOST", 34 | message: "Domain or domains for Let's Encrypt".magenta, 35 | default: "domain.com", 36 | when: q => q.LETSENCRYPT_ENABLED === 1, 37 | required: true 38 | }, { 39 | name: "REUSE_KEY", 40 | message: "Reuse always the first private key when generating certificates?".magenta, 41 | default: false, 42 | pageSize: 2, 43 | type: 'list', 44 | choices: [{ 45 | name: "yes", 46 | value: 1 47 | }, { 48 | name: "no", 49 | value: 0 50 | }], 51 | when: q => q.LETSENCRYPT_ENABLED === 1, 52 | required: true 53 | }] 54 | } 55 | 56 | module.exports.map = { 57 | DOMAIN: "DOMAIN", 58 | VIRTUAL_HOST: "VIRTUAL_HOST" 59 | } 60 | 61 | module.exports.defaults = { 62 | dev: { 63 | TZ: "Europe/Rome", 64 | ENVIRONMENT: "DEVELOPMENT", 65 | WORKDIR: "/www", 66 | VIRTUAL_PROTO: "https", 67 | VIRTUAL_PORT: "443" 68 | }, 69 | prod: { 70 | TZ: "Europe/Rome", 71 | ENVIRONMENT: "PRODUCTION", 72 | WORKDIR: "/www", 73 | VIRTUAL_PROTO: "https", 74 | VIRTUAL_PORT: "443" 75 | } 76 | } 77 | 78 | module.exports.path = "images/nginx/proxy" 79 | 80 | module.exports.dependencies = null -------------------------------------------------------------------------------- /services_conf/node.js: -------------------------------------------------------------------------------- 1 | module.exports.prompt = { 2 | development: [{ 3 | name: "VIRTUAL_HOST", 4 | message: "[VIRTUAL_HOST] Domain(s) managed by this project's nginx".magenta, 5 | default: "localhost", 6 | required: true 7 | }], 8 | production: [{ 9 | name: "VIRTUAL_HOST", 10 | message: "[VIRTUAL_HOST] Domain(s) managed by this project's nginx".magenta, 11 | default: "domain.com", 12 | required: true 13 | }, { 14 | name: "LETSENCRYPT_ENABLED", 15 | message: "Do you want to enable SSL with Let's encrypt?".magenta, 16 | type: 'list', 17 | pageSize: 2, 18 | required: true, 19 | choices: [{ 20 | name: "yes", 21 | value: 1 22 | }, { 23 | name: "no", 24 | value: 0 25 | }] 26 | }, { 27 | name: "LETSENCRYPT_EMAIL", 28 | message: "Email to use for Let's Encrypt certificates".magenta, 29 | default: "dev@caffeina.com", 30 | when: q => q.LETSENCRYPT_ENABLED === 1, 31 | required: true 32 | }, { 33 | name: "LETSENCRYPT_HOST", 34 | message: "Domain or domains for Let's Encrypt".magenta, 35 | default: "domain.com", 36 | when: q => q.LETSENCRYPT_ENABLED === 1, 37 | required: true 38 | }, { 39 | name: "REUSE_KEY", 40 | message: "Reuse always the first private key when generating certificates?".magenta, 41 | default: false, 42 | pageSize: 2, 43 | type: 'list', 44 | choices: [{ 45 | name: "yes", 46 | value: 1 47 | }, { 48 | name: "no", 49 | value: 0 50 | }], 51 | when: q => q.LETSENCRYPT_ENABLED === 1, 52 | required: true 53 | }] 54 | } 55 | 56 | module.exports.map = { 57 | PORT: "PORT" 58 | } 59 | 60 | module.exports.path = "images/node/node" 61 | 62 | module.exports.defaults = { 63 | dev: { 64 | VERSION: "7-alpine", 65 | PORT: "3000", 66 | WORKDIR: "/app", 67 | NODE_ENV: "development", 68 | DB_HOST: "mysql" 69 | }, 70 | prod: { 71 | VERSION: "7-alpine", 72 | PORT: "3000", 73 | WORKDIR: "/app", 74 | NODE_ENV: "production", 75 | DB_HOST: "mysql" 76 | } 77 | } 78 | 79 | module.exports.dependencies = [ 80 | { DB_NAME: {main: "PROJECT_NAME"} }, 81 | { DB_USER: {mysql: "MYSQL_USER"} }, 82 | { DB_PASS: {mysql: "MYSQL_PASSWORD"} } 83 | ] -------------------------------------------------------------------------------- /services_conf/php.js: -------------------------------------------------------------------------------- 1 | module.exports.prompt = { // use nested prompt 2 | "development": [{ 3 | name: "AERIAWORK_ENABLED", 4 | message: "Do you want to preload AeriaWork?".magenta, 5 | type: 'list', 6 | pageSize: 2, 7 | required: true, 8 | choices: [{ 9 | name: "yes", 10 | value: 1 11 | }, { 12 | name: "no", 13 | value: '' 14 | }] 15 | }, { 16 | name: "DOMAIN", 17 | message: "[DOMAIN] Endpoint to access this container (equals VIRTUAL_HOST by default)".magenta, 18 | required: false 19 | }, { 20 | name: "PHP_MODS", 21 | message: "Php modules needed for the project separated by space (ignored in alpine)".magenta, 22 | default: "curl", 23 | required: false 24 | }], 25 | "production": [{ 26 | name: "AERIAWORK_ENABLED", 27 | message: "Do you want to preload AeriaWork?".magenta, 28 | type: 'list', 29 | pageSize: 2, 30 | required: true, 31 | choices: [{ 32 | name: "yes", 33 | value: 1 34 | }, { 35 | name: "no", 36 | value: '' 37 | }] 38 | }, { 39 | name: "DOMAIN", 40 | message: "[DOMAIN] Endpoint to access this container (equals VIRTUAL_HOST by default)".magenta, 41 | required: false 42 | }] 43 | } 44 | 45 | module.exports.map = { 46 | //DOMAIN: ["DOMAIN", "HTTP_HOST"], 47 | //PUBLIC_URL: "PUBLIC_URL", 48 | AERIAWORK_ENABLED: "AERIAWORK_ENABLED", 49 | CORE_ENABLED: "CORE_ENABLED" 50 | } 51 | 52 | module.exports.path = "images/php/php" 53 | 54 | module.exports.defaults = { 55 | dev: { 56 | TZ: "Europe/Rome", // Defaults 57 | DOCKER: "1", // Defaults 58 | ENV: "local", // Defaults 59 | WP_POST_REVISIONS: "false", // Defaults 60 | WP_USE_THEMES: "false", // Defaults 61 | WP_LANG: "it_IT", // Defaults 62 | WORKDIR: "/www", 63 | DEVELOPMENT: "1", // Defaults 64 | 65 | DB_HOST: "mysql", 66 | DB_NAME: "", // Match with MySQL 67 | DB_USER: "", // Match with MySQL 68 | DB_PASS: "", // Match with MySQL 69 | 70 | PROJECT_NAME: "", // Match with main 71 | APP_ID: "", // Match with main 72 | PORT: "80", // Match with main 73 | 74 | PHP_MODS: "curl" 75 | }, 76 | prod: { 77 | TZ: "Europe/Rome", // Defaults 78 | DOCKER: "1", // Defaults 79 | ENV: "local", // Defaults 80 | WP_POST_REVISIONS: "false", // Defaults 81 | WP_USE_THEMES: "false", // Defaults 82 | WP_LANG: "it_IT", // Defaults 83 | WORKDIR: "/www", 84 | DEVELOPMENT: "0", // Defaults 85 | 86 | DB_HOST: "mysql", 87 | DB_NAME: "", // Match with MySQL 88 | DB_USER: "", // Match with MySQL 89 | DB_PASS: "", // Match with MySQL 90 | 91 | PROJECT_NAME: "", // Match with main 92 | APP_ID: "", // Match with main 93 | PORT: "80", // Match with main 94 | 95 | PHP_MODS: "curl" 96 | } 97 | } 98 | 99 | module.exports.dependencies = [ 100 | { PROJECT_NAME: {main: "PROJECT_NAME"} }, 101 | { APP_ID: {main: "PROJECT_NAME"} }, 102 | 103 | { DB_NAME: {main: "PROJECT_NAME"} }, 104 | { DB_USER: {mysql: "MYSQL_USER"} }, 105 | { DB_PASS: {mysql: "MYSQL_PASSWORD"} }, 106 | 107 | { DOMAIN: {nginx: "DOMAIN"} }, 108 | { PUBLIC_URL: {nginx: "DOMAIN"} } 109 | ] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker deploy 2 | 3 | This tool lets you create a docker based environment with a micro-services architecture, enabling you to select only the services needed. It focuses on web development with some preconfigured images like Php, Redis, Nginx, Nodejs, Mysql, Mariadb, HHVM. 4 | 5 | The idea behind this tool is to make it easy to start developing web applications. The steps are as follows 6 | 7 | - Create a new project based on a template 8 | - Set it up with an easy prompt 9 | - Select services 10 | - Configure each service 11 | - Dev/Test cycle locally 12 | - Build/Deploy to the production server 13 | - Enabling A/B testing 14 | - Rollback 15 | 16 | ## Requirements 17 | * node `^7.0.0` 18 | * yarn `^0.23.0` or npm `^3.0.0` 19 | 20 | ## Getting Started 21 | 22 | After confirming that your development environment meets the specified [requirements](#requirements), you can create a new project by doing the following: 23 | 24 | ### Install from source 25 | 26 | First, clone the project: 27 | 28 | ```bash 29 | $ git clone https://github.com/blimpair/blimp.git 30 | $ cd 31 | ``` 32 | 33 | Then install dependencies and check to see it works. It is recommended that you use [Yarn](https://yarnpkg.com/) for deterministic installs, but `npm install` will work just as well. 34 | 35 | ```bash 36 | $ yarn install # Install project dependencies 37 | $ npm link # Will link the current directory to your binaries so you can use it as a global executable 38 | ``` 39 | ## Usage 40 | 41 | Once you've completed the installation procedure, you can start using the tool. 42 | 43 | ### CLI API 44 | 45 | When running `npm link` the command `blimp` is made available globally 46 | 47 | #### Create 48 | 49 | ```bash 50 | $ blimp create # This project is created in the current working directory 51 | ``` 52 | What this command does is clone the main template for web development and strip it of unnecessary files. It also removes `.git` folder so you can init your own repo. 53 | 54 | Once this command completes, you ought to `cd` to the project folder 55 | 56 | #### Setup 57 | 58 | ```bash 59 | $ blimp setup 60 | ``` 61 | 62 | Running setup will start a prompt asking you some questions to configure the project. First it will ask what services you want to enable. Once that is completed, it will start subsequent prompts to complete the configuration of each micro-service, diferentiating between `development` and `production` environments. 63 | 64 | > Note that these differences should be minimal. An example is the database password and username which may be more complicated in production while it can be empty in development 65 | 66 | > Running this command again after having worked on the project may result in failure when testing your project. Clean it and biuld from scratch. 67 | 68 | #### Build 69 | 70 | ```bash 71 | $ blimp build # requires parameter env which is either dev or prod 72 | ``` 73 | 74 | Building the project for development creates a symbolic link to the services' data volumes into the project folder so you can work seamlessly. In particular your application in development will reside in `/data/` 75 | It is required to maintain that directory structure as it determines other services in some cases. Like if you use php and nginx, a folder containing the nginx configuration for the project will be made available which will be automatically loaded by nginx. 76 | The production build command will copy your application code inside the images and will build it tagging with the project version defined in config.json. 77 | 78 | #### Clean 79 | 80 | ```bash 81 | $ blimp clean 82 | ``` 83 | Be careful when running this command as it will delete all services and their data. 84 | 85 | #### Deploy 86 | 87 | WIP 88 | 89 | ## Dependencies 90 | 91 | - [Docker template](https://github.com/blimpair/architecture) 92 | - Architecture for micro-services based web development with the option to create many projects or different instances of the same one. 93 | - [AeriaWork](https://git.caffeina.co/open-source/aeriawork) 94 | - In the case of php web development, if you create an empty project and build it, the php image will automatically initialize an **AeriaWork** project. 95 | 96 | ## License 97 | 98 | MIT. 99 | -------------------------------------------------------------------------------- /services_conf/mysql.js: -------------------------------------------------------------------------------- 1 | const pass = require("generate-password") 2 | 3 | function askUserAndPassword(q) { 4 | if (q.GEN_UP && !q.MYSQL_USER && !q.MYSQL_PASSWORD) { 5 | q.MYSQL_USER = pass.generate({ 6 | length: 10, 7 | numbers: false, 8 | uppercase: false 9 | }) 10 | q.MYSQL_PASSWORD = pass.generate({ 11 | length: 25, 12 | numbers: true, 13 | uppercase: true, 14 | symbols: true, 15 | strict: true 16 | }) 17 | return false 18 | } else if (q.MYSQL_USER && q.MYSQL_PASSWORD) { 19 | return false 20 | } 21 | return true 22 | } 23 | 24 | module.exports.prompt = { // use nested prompt 25 | "development": [/*{ 26 | validate: (input) => { 27 | return /^[a-zA-Z\s\-]+$/.test(input) || 28 | 'Name must be only letters or dashes'.red 29 | }, 30 | name: "MYSQL_DATABASE", 31 | message: "Database name".magenta, 32 | required: true 33 | },*/{ 34 | type: 'list', 35 | name: 'GEN_UP', 36 | message: "Generate a random username and password?".magenta, 37 | pageSize: 2, 38 | choices: [{ 39 | name: "yes", 40 | value: true 41 | }, { 42 | name: "no", 43 | value: false 44 | }] 45 | },{ 46 | validate: (input) => { 47 | return /^[a-zA-Z\s\-]+$/.test(input) || 48 | 'Enter a username for your database user'.red 49 | }, 50 | name: "MYSQL_USER", 51 | message: "Database username".magenta, 52 | required: true, 53 | when: askUserAndPassword 54 | },{ 55 | name: "MYSQL_PASSWORD", 56 | message: "Database password".magenta, 57 | type: "password", 58 | validate: (input) => { 59 | return input.length > 0 || 60 | 'Enter a password'.red 61 | }, 62 | when: askUserAndPassword 63 | },{ 64 | hidden: true, 65 | default: 'root', 66 | name: "MYSQL_ROOT_PASSWORD", 67 | type: "password", 68 | validate: (input) => { 69 | return input.length > 0 || 70 | "Password for root user" 71 | }, 72 | when: () => false , 73 | message: "Set a password for `root` or leave it to it's default (root)".magenta 74 | },{ 75 | type: 'list', 76 | name: 'MYSQL_ALLOW_EMPTY_PASSWORD', 77 | message: "Allow a database user with an empty password?".magenta, 78 | pageSize: 2, 79 | choices: [{ 80 | name: "yes", 81 | value: "yes" 82 | }, { 83 | name: "no", 84 | value: "" 85 | }], 86 | when: false 87 | }], 88 | "production": [/*{ 89 | validate: (input) => { 90 | return /^[a-zA-Z\s\-]+$/.test(input) || 91 | 'Name must be only letters, spaces, or dashes'.red 92 | }, 93 | name: "MYSQL_DATABASE", 94 | message: "Database name".magenta, 95 | required: true 96 | },*/{ 97 | type: 'list', 98 | name: 'GEN_UP', 99 | message: "Generate a random username and password?".magenta, 100 | pageSize: 2, 101 | choices: [{ 102 | name: "yes", 103 | value: true 104 | }, { 105 | name: "no", 106 | value: false 107 | }] 108 | },{ 109 | validate: (input) => { 110 | return /^[a-zA-Z\s\-]+$/.test(input) || 111 | 'Enter a username for your database user'.red 112 | }, 113 | name: "MYSQL_USER", 114 | message: "Database username".magenta, 115 | required: true, 116 | when: askUserAndPassword 117 | },{ 118 | name: "MYSQL_PASSWORD", 119 | message: "Database password".magenta, 120 | type: "password", 121 | validate: (input) => { 122 | return input.length > 0 || 123 | 'Enter a password'.red 124 | }, 125 | when: askUserAndPassword 126 | }] 127 | } 128 | 129 | module.exports.map = { 130 | MYSQL_DATABASE: "MYSQL_DATABASE", 131 | MYSQL_USER: "MYSQL_USER", 132 | MYSQL_PASSWORD: "MYSQL_PASSWORD", 133 | MYSQL_ROOT_PASSWORD: "MYSQL_ROOT_PASSWORD", 134 | MYSQL_RANDOM_ROOT_PASSWORD: "MYSQL_RANDOM_ROOT_PASSWORD", 135 | MYSQL_ALLOW_EMPTY_PASSWORD: "MYSQL_ALLOW_EMPTY_PASSWORD" 136 | } 137 | 138 | module.exports.path = "images/mysql/db" 139 | 140 | module.exports.dependencies = [ 141 | { MYSQL_DATABASE: {main: "PROJECT_NAME"} } 142 | ] 143 | 144 | module.exports.defaults = { 145 | dev: { 146 | 147 | }, 148 | prod: { 149 | MYSQL_ALLOW_EMPTY_PASSWORD: "no", 150 | MYSQL_RANDOM_ROOT_PASSWORD: "yes" 151 | } 152 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict' 3 | 4 | const manifest = require('./package.json') 5 | const CWD = process.cwd() 6 | const async = require('async') 7 | const gm = require('gm') 8 | const path = require('path') 9 | const program = require('commander') 10 | const _ = require('underscore') 11 | const inquirer = require('inquirer') 12 | const prompt = require('prompt') 13 | const child_process = require('child_process') 14 | const escape = require("shell-escape") 15 | const env = require('node-env-file') 16 | const fs = require('fs-extended') 17 | const Q = require('q') 18 | const colors = require('colors') 19 | const yaml = require('js-yaml') 20 | const git = require('simple-git') 21 | const containers = "https://github.com/blimpair/architecture" 22 | 23 | const execOpts = { cwd: CWD, stdio:[0,1,2], sync: true } // stdio is only needed for execSync|spawn 24 | reqEnvOrExit() 25 | const schemaMap = { 26 | php7: "php", 27 | legacy: "php", 28 | phpa: "php", 29 | php: "php", 30 | hhvm: "hhvm", 31 | mysql: "mysql", 32 | node: "node", 33 | mongodb: "mongo", 34 | influxdb: "influx", 35 | redis: "redis", 36 | nginx: "nginx" 37 | } 38 | var envs = [] 39 | var order = [] 40 | 41 | ///////////// 42 | // Helpers // 43 | ///////////// 44 | 45 | const exec = (cmd, opts, callback) => { 46 | if (opts.sync || !_.isArray(cmd)) { 47 | if (manifest.debug) console.log("--", "Sync command: ", JSON.stringify(cmd), JSON.stringify(opts)) 48 | 49 | if (_.isArray(cmd)) cmd = cmd.join(" ") //escape(cmd) 50 | child_process.exec(cmd, opts, callback) 51 | } else { 52 | //return Q.promise((resolve, reject) => { 53 | if (manifest.debug) console.log("--", "Spawn command", JSON.stringify(cmd), cmd.join(" "), JSON.stringify(opts)) 54 | 55 | let spawned = child_process.spawn(cmd.shift(), cmd, opts) 56 | spawned.on("close", (err) => { 57 | if (err != 0) log(`Process exited with code ${err}`, false, false) 58 | 59 | if (callback) callback(err, false, false) 60 | else log(err, false, false) 61 | //else resolve(output) 62 | }) 63 | //}) 64 | } 65 | } 66 | 67 | const log = (err, stdout, stderr) => { 68 | if (err) error(err, 1, true) 69 | 70 | if (stderr != null && stderr != "") process.stdout.write(`${stderr}\n`.yellow) 71 | if (stdout != null && stdout != "") process.stdout.write(`${stdout}\n`.blue) 72 | } 73 | 74 | function getUserHome() { 75 | return process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'] 76 | } 77 | 78 | // Log an event to the CLI + GA, and miserably exit 79 | function error(msg, code, dont_exit) { 80 | process.stdout.write(msg.toString().red) 81 | 82 | if (dont_exit == false) { 83 | process.exit( code || 1 ) 84 | } 85 | } 86 | 87 | function reqEnvOrExit(){ 88 | if (fs.existsSync(`${CWD}/.env`)) env(`${CWD}/.env`) 89 | if (fs.existsSync(`${CWD}/yml/.env`)) return env(`${CWD}/yml/.env`, {overwrite: true}) 90 | 91 | if (!fs.existsSync(`${CWD}/.env`)) process.stdout.write('.env file is missing.\n\n'.red) 92 | if (fs.existsSync(`${CWD}/.env.sample`)) return env(`${CWD}/.env.sample`) 93 | } 94 | 95 | function projectName() { 96 | if (!fs.existsSync(`${CWD}/config.json`)) return CWD.split("/").pop() 97 | 98 | let config = require(`${CWD}/config.json`) 99 | 100 | if (config && config.globals && config.globals.main) return config.globals.main.PROJECT_NAME 101 | else return CWD.split("/").pop() 102 | } 103 | 104 | function projectVersion() { 105 | if (!fs.existsSync(`${CWD}/config.json`)) return '1.0.0' 106 | 107 | let config = require(`${CWD}/config.json`) 108 | 109 | if (config && config.globals && config.globals.main) return config.globals.main.VERSION 110 | else return '1.0.0' 111 | } 112 | 113 | function projectBranch() { 114 | if (!fs.existsSync(`${CWD}/config.json`)) return 'master' 115 | 116 | let config = require(`${CWD}/config.json`) 117 | 118 | if (config && config.globals && config.globals.main) return config.globals.main.GIT_BRANCH 119 | else return 'master' 120 | } 121 | 122 | function projectRepo() { 123 | if (!fs.existsSync(`${CWD}/config.json`)) return null 124 | 125 | let config = require(`${CWD}/config.json`) 126 | 127 | if (config && config.globals && config.globals.main) return config.globals.main.GIT_REMOTE 128 | else return null 129 | } 130 | 131 | function containerIdFromName(name) { 132 | return new Promise((resolve, reject) => { 133 | let cmd = ["docker", "ps", "-q", "-f", `name=${projectBranch()}${projectName()}_${name}`] 134 | exec(cmd, _.extend(execOpts, {sync: true}), (err, stdout, stderr) => { 135 | if (err) return reject(err, stderr) 136 | process.stdout.write(`\nLooking for ${projectBranch()}${projectName()}_${name}\n`.blue) 137 | log(false, stdout, stderr) 138 | 139 | resolve(stdout.toString().split("\n")[0]) 140 | }) 141 | }) 142 | } 143 | 144 | function filesMap(itemPath, stat) { 145 | return { 146 | path: itemPath, 147 | name: path.basename(itemPath), 148 | ext: path.extname(itemPath), 149 | size: stat.size, 150 | } 151 | } 152 | 153 | ///////// 154 | // Git // 155 | ///////// 156 | 157 | function gitCleanOrExit() { 158 | return exec(['git', 'status', '--porcelain'], execOpts) 159 | .then((stdout) => { 160 | var lines = (stdout.match(/\n/g) || []).length 161 | if (lines > 0) { 162 | process.stdout.write('Current working directory is not clean. Please commit current changes before doing anything') 163 | } 164 | }) 165 | .catch(log) 166 | } 167 | 168 | function gitTag(version) { 169 | process.stdout.write("Tagging current changes...") 170 | return exec(['git', 'tag', '-d', version], execOpts, () => { 171 | return exec(['git', 'tag', version], execOpts, () => { 172 | return exec(['git', 'push', '--tags'], execOpts) 173 | }) 174 | }) 175 | } 176 | 177 | function gitCommit(message) { 178 | process.stdout.write("Commiting current changes...") 179 | return exec(['git', 'add', '-A'], execOpts, () => { 180 | exec(['git', 'commit', '-am' + message], execOpts, () => { 181 | exec(['git', 'push'], execOpts) 182 | }) 183 | }) 184 | } 185 | 186 | function gitInit() { 187 | // To be implemented 188 | /*git() 189 | .init() 190 | .add('./*') 191 | .commit("First commit!") 192 | .addRemote('origin', 'https://github.com/user/repo.git') 193 | .push('origin', 'master')*/ 194 | 195 | return Q.resolve() 196 | } 197 | 198 | function gitClone(dir, callback) { 199 | if (_.isFunction(dir) && !callback) { 200 | callback = dir 201 | dir = "." 202 | } 203 | 204 | process.stdout.write("Cloning docker infrastructure...\n".green) 205 | 206 | /*git() 207 | .clone(containers, dir, null, () => { 208 | if(_.isFunction(callback)) callback() 209 | })*/ 210 | 211 | let cmd = ['git','clone', containers, dir] 212 | return exec(cmd, _.extend(execOpts, {sync: false}), callback) 213 | } 214 | 215 | function gitRemoveRemote(dir, callback) { 216 | if (_.isFunction(dir) && !callback) { 217 | callback = dir 218 | dir = "." 219 | } 220 | 221 | process.stdout.write("Resetting git...\n".green) 222 | 223 | /*let cmd = ['rm','-rf', `${dir}/.git`] 224 | return exec(cmd, execOpts, callback)*/ 225 | 226 | fs.deleteDir(`${dir}/.git`, () => { 227 | fs.deleteDir(`${dir}/network/.git`, () => { 228 | if (_.isFunction(callback)) callback() 229 | }) 230 | }) 231 | } 232 | 233 | function initSubmodules(dir) { 234 | return Q.promise((resolve, reject) => { 235 | if (_.isFunction(dir) && !callback) { 236 | callback = dir 237 | dir = "." 238 | } 239 | 240 | return exec(['git','submodule', 'init'], _.extend(execOpts, {sync: false, cwd: `${CWD}/${dir}`}), (err, stdout, stderr) => { 241 | if (err) return reject(err, stderr) 242 | log(false, stdout, stderr) 243 | resolve(dir) 244 | }) 245 | }) 246 | } 247 | 248 | function cloneSubmodules(dir) { 249 | return Q.promise((resolve, reject) => { 250 | if (_.isFunction(dir) && !callback) { 251 | callback = dir 252 | dir = "." 253 | } 254 | 255 | return exec(['git','submodule', 'update'], _.extend(execOpts, {sync: false, cwd: `${CWD}/${dir}`}), (err, stdout, stderr) => { 256 | if (err) return reject(err, stderr) 257 | log(false, stdout, stderr) 258 | resolve(dir) 259 | }) 260 | }) 261 | } 262 | 263 | /////////////// 264 | // Dockerize // 265 | /////////////// 266 | 267 | //////////// 268 | // Create // 269 | //////////// 270 | 271 | function create(name) { 272 | var self = this 273 | if (!_.isString(name)) { 274 | process.stdout.write("Please provide a name for your project\n".red) 275 | return false 276 | } 277 | 278 | createProject(name) 279 | .then(removeOrigin) 280 | .then(cleanFiles) 281 | .then(function() { 282 | process.stdout.write("Project cloned.\n".green) 283 | }) 284 | .catch(function(e, stderr) { 285 | if (_.isString(e)) process.stdout.write(e.red) 286 | else process.stdout.write(e) 287 | }) 288 | } 289 | 290 | function createProject(name) { 291 | return Q.promise(function(resolve, reject) { 292 | if (fs.existsSync(name)) { 293 | return reject("A folder named <" + name + "> already exists") 294 | } 295 | 296 | process.stdout.write("Creating new project ".green + name + "\n".green) 297 | 298 | gitClone(name, (err, stdout, stderr) => { 299 | if (err) return reject(err, stderr) 300 | log(false, stdout, stderr) 301 | 302 | initSubmodules(name) 303 | .then(() => cloneSubmodules(name)) 304 | .then(() => initSubmodules(`${name}/network`)) 305 | .then(() => cloneSubmodules(`${name}/network`)) 306 | .then(() => resolve(name)) 307 | }) 308 | }) 309 | } 310 | 311 | function removeOrigin(name) { 312 | return Q.promise(function(resolve, reject) { 313 | gitRemoveRemote(name, (err, stdout, stderr) => { 314 | if (err) return reject(err, stderr) 315 | log(false, stdout, stderr) 316 | resolve(name) 317 | }) 318 | }) 319 | } 320 | 321 | function cleanFiles(name) { 322 | return Q.promise(function(resolve, reject) { 323 | 324 | fs.listAll(`${CWD}/${name}`, { map: filesMap }, function (err, files) { 325 | files.forEach(f => { 326 | if (".md" == f.ext || ".png" == f.ext || ".gitignore" == f.ext) fs.deleteFile(f.path) 327 | }) 328 | }) 329 | 330 | resolve() 331 | }) 332 | } 333 | 334 | /////////// 335 | // Build // 336 | /////////// 337 | 338 | function build(type) { 339 | process.stdout.write("Building docker for the specified environment\n".green) 340 | type = _.isString(type) ? type : _.isObject(type.environment) ? type.environment : false 341 | 342 | if (!type) { 343 | error("\nPlease provide build environment [dev|prod]") 344 | return 345 | } 346 | 347 | // Override .env.sample COMPOSE_PROJECT_NAME 348 | try { 349 | env(`${CWD}/.env`, {overwrite: true}) 350 | } catch(e) { 351 | process.env.COMPOSE_PROJECT_NAME = `${projectBranch()}${projectName()}` 352 | } 353 | 354 | var cmd = ["docker-compose", "-f", "yml/docker-compose.yml"] 355 | if (type == "dev") { 356 | cmd = cmd.concat(["-f", "yml/docker-compose.dev.yml"]) //, "--remove-orphans" 357 | } 358 | 359 | cmd = cmd.concat(["up", "-d", "--build"]) 360 | 361 | exec(cmd, _.extend(execOpts, {sync: false}), log) 362 | } 363 | 364 | /////////// 365 | // Clean // 366 | /////////// 367 | 368 | function clean(rm) { 369 | var self = this 370 | 371 | if (self.rm) { 372 | process.stdout.write("Careful! This command is to be used only on development environments \n".yellow) 373 | process.stdout.write("It will delete all docker networks and volumes along with all orphan containers\n".red) 374 | exec(["docker", "network", "prune", "-f"], _.extend(execOpts, {sync: false}), (err, stdout, stderr) => { 375 | log(err, stdout, stderr) 376 | exec(["docker", "volume", "prune", "-f"], _.extend(execOpts, {sync: false}), (err, stdout, stderr) => { 377 | log(err, stdout, stderr) 378 | exec(["docker-compose", "down"], 379 | _.extend(execOpts, {cwd: `${CWD}/yml`, sync: false}), log) 380 | }) 381 | }) 382 | } else { 383 | exec(["docker-compose", "down"], 384 | _.extend(execOpts, {cwd: `${CWD}/yml`, sync: false}), log) 385 | } 386 | } 387 | 388 | /////////////////// 389 | // Load balancer // 390 | /////////////////// 391 | 392 | function loadBalancer() { 393 | var self = this 394 | 395 | if (self.rm) { 396 | removeLoadBalancer() 397 | return 398 | } 399 | 400 | // Override .env.sample COMPOSE_PROJECT_NAME 401 | try { 402 | env(`${CWD}/network/.env`, {overwrite: true}) 403 | } catch(e) { 404 | process.env.COMPOSE_PROJECT_NAME = "network" 405 | } 406 | 407 | process.stdout.write("Creating main network and load balancer\n".green) 408 | exec("docker network ls", execOpts, (error, stdout, stderr) => { 409 | process.stdout.write("Showing all networks: \n".yellow) 410 | process.stdout.write(stdout.blue) 411 | 412 | if (stdout.indexOf("tier_1") != -1) { 413 | process.stdout.write("Network already exists".green) 414 | } else { 415 | exec(["docker-compose", "up", "-d", "--build"], _.extend(execOpts, {sync: false, cwd: `${CWD}/network`}), log) 416 | } 417 | }) 418 | } 419 | 420 | function removeLoadBalancer() { 421 | process.stdout.write("Removing main network and load balancer\n".green) 422 | exec(["docker-compose", "down"], _.extend(execOpts, {cwd: CWD + "/network", sync: false}) , log) 423 | } 424 | 425 | //////////// 426 | // Deploy // 427 | //////////// 428 | 429 | function deploy() { 430 | 431 | } 432 | 433 | //////////// 434 | // Get in // 435 | //////////// 436 | 437 | function getin(service) { 438 | if (!_.isString(service)) return log(null, null, `Command not used correctly. You must provide -s`) 439 | 440 | process.stdout.write(`Getting into container ${service}\n`.green) 441 | 442 | service = service.toLowerCase() 443 | 444 | let found = false 445 | _(schemaMap).mapObject((v, k) => { 446 | if (k == service) found = true 447 | }) 448 | 449 | if (service == "mysql") service = "db" 450 | containerIdFromName(service) 451 | .then((container_id) => { 452 | exec([`docker`, `exec`, `-it`, `${container_id}`, `sh`], _.extend(execOpts, {sync: false}), log) 453 | }) 454 | .catch(log) 455 | } 456 | 457 | //////////// 458 | // Export // 459 | //////////// 460 | 461 | function exportService(service, tag) { 462 | if (!_.isString(service)) return log(null, null, `Command not used correctly. You must provide -s`) 463 | if (!_.isString(tag)) tag = projectVersion() 464 | 465 | process.stdout.write(`Exporting ${service} in ${CWD}/dist \n`.green) 466 | fs.createDirSync(`${CWD}/dist`) 467 | 468 | if (service == "mysql") service = "db" 469 | 470 | containerIdFromName(service) 471 | .then( (id) => { 472 | let cmd = [ 473 | "docker", 474 | "save", 475 | "-o", 476 | `${CWD}/dist/${id}.tar`, 477 | `${id}:${tag}` 478 | ] 479 | 480 | exec(cmd, _.extend(execOpts, {sync: false}), log) 481 | }) 482 | .catch(log) 483 | } 484 | 485 | ////////// 486 | // Load // 487 | ////////// 488 | 489 | function loadService(service) { 490 | if (!_.isString(service)) return log(null, null, `Command not used correctly. You must provide -s`) 491 | 492 | process.stdout.write(`Loading ${service} in ${CWD}/dist \n`.green) 493 | 494 | if (service == "mysql") service = "db" 495 | containerIdFromName(service) 496 | .then( () => { 497 | if (!fs.existsSync(`${CWD}/dist/${id}.tar`)) { 498 | log(null, null, `Image doesn't seem to exist in ./dist/ \n`.red) 499 | return false 500 | } 501 | 502 | let cmd = ["docker", "load", "-i", `${CWD}/dist/${id}.tar`] 503 | 504 | exec(cmd, _.extend(execOpts, {sync: false}), log) 505 | }) 506 | .catch(log) 507 | } 508 | 509 | /////////// 510 | // Setup // 511 | /////////// 512 | 513 | function writeEnv(opts) { 514 | return Q.promise((resolve, reject) => { 515 | envs.push(opts) 516 | resolve() 517 | }) 518 | } 519 | 520 | function ask(block) { 521 | return Q.promise((resolve, reject) => { 522 | let schema = null 523 | try { 524 | schema = require(`${__dirname}/services_conf/${block}`) 525 | } catch(e) { 526 | return resolve({service: block}) 527 | } 528 | process.stdout.write(`\n${block.toUpperCase()}\n`.green) 529 | 530 | if (!schema.prompt) return resolve({service: block, source: schema}) 531 | 532 | if (_.isArray(schema.prompt)) { 533 | inquirer.prompt(schema.prompt) 534 | .then((d) => { 535 | resolve({service: block, main: d, source: schema}) 536 | }) 537 | } else { 538 | if (_.isArray(schema.prompt.development)) { 539 | process.stdout.write("\n > Development variables\n".blue) 540 | 541 | inquirer.prompt(schema.prompt.development) 542 | .then((dev) => { 543 | if (!_.isArray(schema.prompt.production)) return resolve({service: block, dev: dev, source: schema}) 544 | process.stdout.write("\n > Production variables\n".blue) 545 | 546 | inquirer.prompt(schema.prompt.production) 547 | .then((prod) => { 548 | return resolve({service: block, dev: dev, prod: prod, source: schema}) 549 | }) 550 | }) 551 | } 552 | } 553 | }) 554 | } 555 | 556 | function recursiveAsk(schemas) { 557 | let schema = null 558 | if (schemas && (schema = schemas.shift())) { 559 | return ask(schema) 560 | .then(writeEnv) 561 | .then(() => { 562 | return recursiveAsk(schemas) 563 | }) 564 | } else { 565 | return Q.resolve() 566 | } 567 | } 568 | 569 | function processSingle(node, env) { 570 | let updated = { 571 | service: env.service, 572 | source: env.source 573 | } 574 | updated[node] = {} 575 | 576 | _.mapObject(env[node], (value, key) => { 577 | let mapKey = env.source.map && env.source.map[key] ? env.source.map[key] : null 578 | 579 | if (_.isArray(mapKey)) _(mapKey).each( k => updated[node][k] = value ) 580 | else if (_.isString(mapKey)) updated[node][mapKey] = value 581 | else updated[node][key] = value 582 | }) 583 | 584 | if (!env.source) return updated 585 | 586 | updated[node] = _.extend(env.source.defaults ? env.source.defaults[node] : {}, updated[node]) 587 | 588 | return updated 589 | } 590 | 591 | function processConfig() { 592 | return Q.promise((resolve, reject) => { 593 | let all = [] 594 | envs.forEach((env, index) => { 595 | if (env.main) all.push(processSingle("main", env)) 596 | else all.push( _.extend( 597 | processSingle("dev", env), 598 | processSingle("prod", env) )) 599 | }) 600 | resolve(all) 601 | }) 602 | } 603 | 604 | function linker(envs) { 605 | return Q.promise((resolve, reject) => { 606 | let linked = [] 607 | envs.forEach((env, index) => { 608 | let current = env 609 | // continue if there aren't any dependencies for the current service 610 | if (!current.source || !current.source.dependencies) return linked.push(current) 611 | 612 | // for each dependency of the current object 613 | current.source.dependencies.forEach((dep) => { 614 | _(dep).mapObject((pointer, key) => { 615 | _(pointer).mapObject((pointerKey, service) => { 616 | let serviceIndex = order.indexOf(service) 617 | let serviceObject = -1 != serviceIndex ? envs[++serviceIndex] : envs[0] 618 | 619 | if (current.dev && current.dev[key]) return 620 | if (current.prod && current.prod[key]) return 621 | 622 | if (serviceObject.main) { 623 | if (current.dev) current.dev[key] = serviceObject.main[pointerKey] 624 | if (current.prod && !current.prod[key]) current.prod[key] = serviceObject.main[pointerKey] 625 | } 626 | 627 | if (serviceObject.dev && current.dev) current.dev[key] = serviceObject.dev[pointerKey] 628 | if (serviceObject.prod && current.prod && !current.prod[key]) current.prod[key] = serviceObject.prod[pointerKey] 629 | 630 | if (current.main && serviceObject.dev) current.main[key] = serviceObject.dev[pointerKey] 631 | }) 632 | }) 633 | }) 634 | linked.push(current) 635 | }) 636 | 637 | return resolve(linked) 638 | }) 639 | } 640 | 641 | function makeConfjson(all) { 642 | return Q.promise((resolve, reject) => { 643 | let omitted = [] 644 | all.forEach(conf => { 645 | if (conf.source) { 646 | conf.source = { path: conf.source.path } 647 | if (conf.source.path != null) omitted.push(conf) 648 | } 649 | }) 650 | 651 | omitted = {globals: omitted.shift(), services: omitted} 652 | fs.createFileSync(`${CWD}/config.json`, JSON.stringify(omitted, null, " ")) 653 | 654 | return resolve(omitted) 655 | }) 656 | } 657 | 658 | function toEnv(ob) { 659 | let str = [] 660 | 661 | _(ob).mapObject((v, k) => { 662 | if (undefined == v || 'undefined' == v) return 663 | str.push(`${k.replace(" ", "_")}=` + (!/\w/g.test(v) || !v.length ? `'${v}'` : v)) 664 | }) 665 | return str.join("\n") 666 | } 667 | 668 | function updateYml(keys, file) { 669 | return Q.promise((resolve, reject) => { 670 | try { 671 | if (!fs.existsSync(`${file}.orig`)) fs.writeFileSync(`${file}.orig`, fs.readFileSync(file)) 672 | 673 | let yml = yaml.safeLoad(fs.readFileSync(`${file}.orig`)) 674 | let srv = {} 675 | 676 | for (let k in yml.services) if (keys.indexOf(k) !== -1) srv[k] = yml.services[k] 677 | yml.services = srv 678 | 679 | fs.writeFileSync(file, yaml.safeDump(yml)) 680 | resolve() 681 | } catch(e) { 682 | reject(e) 683 | } 684 | }) 685 | } 686 | 687 | function updateYmls(keys) { 688 | return Q.promise((resolve, reject) => { 689 | updateYml(keys, `${CWD}/yml/docker-compose.yml`) 690 | .then(t => updateYml(keys, `${CWD}/yml/docker-compose.dev.yml`)) 691 | .then(resolve) 692 | .catch(reject) 693 | }) 694 | } 695 | 696 | function writeEnvFiles(config) { 697 | return Q.promise((resolve, reject) => { 698 | if (!_(config).isObject()) { 699 | if (!fs.existsSync(`${CWD}/config.json`)) { 700 | process.stdout.write("Missing config.json".red) 701 | return reject() 702 | } else { 703 | config = fs.readJSONSync(`${CWD}/config.json`) 704 | } 705 | } 706 | 707 | if (config.globals) { 708 | if (config.globals.source.path != null) { 709 | fs.createFileSync(`${CWD}/${config.globals.source.path}.env`, toEnv(config.globals.main)) 710 | } 711 | } 712 | 713 | _(config.services).each((service) => { 714 | if (service.source && service.source.path) { 715 | if (_.isObject(service.dev)) { 716 | fs.createFileSync(`${CWD}/${service.source.path}.dev.env`, toEnv(service.dev)) 717 | } 718 | if (_.isObject(service.prod)) { 719 | fs.createFileSync(`${CWD}/${service.source.path}.env`, toEnv(service.prod)) 720 | } 721 | } 722 | }) 723 | 724 | resolve() 725 | }) 726 | } 727 | 728 | function setup() { 729 | ask('main') 730 | .then(writeEnv) 731 | .then(m => ask("services")) 732 | .then((a) => { 733 | let services = [] 734 | let keys = [] 735 | 736 | a.main.services.forEach((service) => { 737 | let srv = schemaMap[service] || service 738 | if (services.indexOf(srv) == -1) { 739 | services.push(srv) 740 | keys.push(service) 741 | } 742 | }) 743 | order = _(services).clone() 744 | return recursiveAsk(services).then(t => updateYmls(keys)) 745 | }) 746 | .then(processConfig) 747 | .then(linker) 748 | .then(makeConfjson) 749 | .then(writeEnvFiles) 750 | //.then(gitInit) 751 | .catch(e => process.stdout.write(e.toString().red)) 752 | } 753 | 754 | function generateEnvs() { 755 | writeEnvFiles() 756 | } 757 | 758 | ///////////////////////// 759 | // Configure commander // 760 | ///////////////////////// 761 | 762 | program 763 | .version(manifest.version, '-v, --version') 764 | .description(manifest.description) 765 | .usage('command [options]') 766 | 767 | //////////// 768 | // Init P // 769 | //////////// 770 | 771 | program 772 | .command('deploy') 773 | .description('Deploy the project') 774 | .action(deploy) 775 | 776 | program 777 | .command('setup') 778 | .description('Configure project variables') 779 | .action(setup) 780 | 781 | program 782 | .command('create') 783 | .description('Initialize a new project') 784 | .action(create) 785 | 786 | program 787 | .command('build') 788 | .option("-e, --environment", "Type of build. [dev|prod]", /^(dev|prod)$/, "dev") 789 | .description('Build the project') 790 | .action(build) 791 | 792 | program 793 | .command('clean') 794 | .description('Clean the whole docker environment') 795 | .option("-r, --rm", "Remove networks and volumes") 796 | .action(clean) 797 | 798 | program 799 | .command('loadbalancer') 800 | .alias("lb") 801 | .option("-r, --rm", "Remove loadbalancer and network") 802 | .description('Create a load balancer and the main network where to attach all the projects') 803 | .action(loadBalancer) 804 | 805 | program 806 | .command('generate-env') 807 | .alias("gen") 808 | .description("Generates all env files from the config.json file.") 809 | .action(generateEnvs) 810 | 811 | program 812 | .command('get-in') 813 | .alias('run') 814 | .option('-s, --service', "Service name to get in to i.e. php") 815 | .description("Get inside the shell of container and run your commands to update it") 816 | .action(getin) 817 | 818 | program 819 | .command('export') 820 | .option('-s, --service', "Service name to export i.e. php") 821 | .option('-t, --tag', "Service tag i.e. 1.0.0. If not provided, `latest` will be used") 822 | .description("Export a container and save it under ./dist folder as a tar image") 823 | .action(exportService) 824 | 825 | program 826 | .command('load') 827 | .option('-s, --service', "Service name to load i.e. php") 828 | .description("Load a previously exported image. The command will look in ./dist folder for the image") 829 | .action(loadService) 830 | 831 | // Parse the input arguments 832 | program.parse(process.argv) 833 | 834 | // Start commander 835 | if (program.args.length === 0 || typeof program.args[program.args.length - 1] === 'string') { 836 | program.help() 837 | } else { 838 | 839 | } -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | ajv@^4.9.1: 6 | version "4.11.5" 7 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.5.tgz#b6ee74657b993a01dce44b7944d56f485828d5bd" 8 | dependencies: 9 | co "^4.6.0" 10 | json-stable-stringify "^1.0.1" 11 | 12 | amdefine@>=0.0.4: 13 | version "1.0.1" 14 | resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" 15 | 16 | ansi-align@^1.1.0: 17 | version "1.1.0" 18 | resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-1.1.0.tgz#2f0c1658829739add5ebb15e6b0c6e3423f016ba" 19 | dependencies: 20 | string-width "^1.0.1" 21 | 22 | ansi-escapes@^1.1.0: 23 | version "1.4.0" 24 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" 25 | 26 | ansi-regex@^2.0.0: 27 | version "2.1.1" 28 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 29 | 30 | ansi-styles@^2.2.1: 31 | version "2.2.1" 32 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 33 | 34 | argparse@^1.0.7: 35 | version "1.0.9" 36 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" 37 | dependencies: 38 | sprintf-js "~1.0.2" 39 | 40 | array-parallel@~0.1.3: 41 | version "0.1.3" 42 | resolved "https://registry.yarnpkg.com/array-parallel/-/array-parallel-0.1.3.tgz#8f785308926ed5aa478c47e64d1b334b6c0c947d" 43 | 44 | array-series@~0.1.5: 45 | version "0.1.5" 46 | resolved "https://registry.yarnpkg.com/array-series/-/array-series-0.1.5.tgz#df5d37bfc5c2ef0755e2aa4f92feae7d4b5a972f" 47 | 48 | asn1@~0.2.3: 49 | version "0.2.3" 50 | resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" 51 | 52 | assert-plus@1.0.0, assert-plus@^1.0.0: 53 | version "1.0.0" 54 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" 55 | 56 | assert-plus@^0.2.0: 57 | version "0.2.0" 58 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" 59 | 60 | async@1.2.x: 61 | version "1.2.1" 62 | resolved "https://registry.yarnpkg.com/async/-/async-1.2.1.tgz#a4816a17cd5ff516dfa2c7698a453369b9790de0" 63 | 64 | async@^2.3.0: 65 | version "2.3.0" 66 | resolved "https://registry.yarnpkg.com/async/-/async-2.3.0.tgz#1013d1051047dd320fe24e494d5c66ecaf6147d9" 67 | dependencies: 68 | lodash "^4.14.0" 69 | 70 | async@~0.2.6: 71 | version "0.2.10" 72 | resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" 73 | 74 | async@~0.9.0: 75 | version "0.9.2" 76 | resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" 77 | 78 | async@~1.0.0: 79 | version "1.0.0" 80 | resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" 81 | 82 | asynckit@^0.4.0: 83 | version "0.4.0" 84 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 85 | 86 | aws-sign2@~0.6.0: 87 | version "0.6.0" 88 | resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" 89 | 90 | aws4@^1.2.1: 91 | version "1.6.0" 92 | resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" 93 | 94 | balanced-match@^0.4.1: 95 | version "0.4.2" 96 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" 97 | 98 | bcrypt-pbkdf@^1.0.0: 99 | version "1.0.1" 100 | resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" 101 | dependencies: 102 | tweetnacl "^0.14.3" 103 | 104 | "binary@>= 0.3.0 < 1": 105 | version "0.3.0" 106 | resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79" 107 | dependencies: 108 | buffers "~0.1.1" 109 | chainsaw "~0.1.0" 110 | 111 | boom@2.x.x: 112 | version "2.10.1" 113 | resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" 114 | dependencies: 115 | hoek "2.x.x" 116 | 117 | boxen@^1.0.0: 118 | version "1.0.0" 119 | resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.0.0.tgz#b2694baf1f605f708ff0177c12193b22f29aaaab" 120 | dependencies: 121 | ansi-align "^1.1.0" 122 | camelcase "^4.0.0" 123 | chalk "^1.1.1" 124 | cli-boxes "^1.0.0" 125 | string-width "^2.0.0" 126 | term-size "^0.1.0" 127 | widest-line "^1.0.0" 128 | 129 | brace-expansion@^1.0.0: 130 | version "1.1.6" 131 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" 132 | dependencies: 133 | balanced-match "^0.4.1" 134 | concat-map "0.0.1" 135 | 136 | buffers@~0.1.1: 137 | version "0.1.1" 138 | resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" 139 | 140 | camelcase@^4.0.0: 141 | version "4.1.0" 142 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" 143 | 144 | capture-stack-trace@^1.0.0: 145 | version "1.0.0" 146 | resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" 147 | 148 | caseless@~0.12.0: 149 | version "0.12.0" 150 | resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 151 | 152 | chainsaw@~0.1.0: 153 | version "0.1.0" 154 | resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" 155 | dependencies: 156 | traverse ">=0.3.0 <0.4" 157 | 158 | chalk@^1.0.0, chalk@^1.1.1: 159 | version "1.1.3" 160 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 161 | dependencies: 162 | ansi-styles "^2.2.1" 163 | escape-string-regexp "^1.0.2" 164 | has-ansi "^2.0.0" 165 | strip-ansi "^3.0.0" 166 | supports-color "^2.0.0" 167 | 168 | cli-boxes@^1.0.0: 169 | version "1.0.0" 170 | resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" 171 | 172 | cli-cursor@^2.1.0: 173 | version "2.1.0" 174 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" 175 | dependencies: 176 | restore-cursor "^2.0.0" 177 | 178 | cli-width@^2.0.0: 179 | version "2.1.0" 180 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" 181 | 182 | co@^4.6.0: 183 | version "4.6.0" 184 | resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" 185 | 186 | code-point-at@^1.0.0: 187 | version "1.1.0" 188 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 189 | 190 | colors@1.0.x: 191 | version "1.0.3" 192 | resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" 193 | 194 | colors@^1.1.2: 195 | version "1.1.2" 196 | resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" 197 | 198 | combined-stream@^1.0.5, combined-stream@~1.0.5: 199 | version "1.0.5" 200 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" 201 | dependencies: 202 | delayed-stream "~1.0.0" 203 | 204 | commander@^2.9.0: 205 | version "2.9.0" 206 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" 207 | dependencies: 208 | graceful-readlink ">= 1.0.0" 209 | 210 | concat-map@0.0.1: 211 | version "0.0.1" 212 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 213 | 214 | configstore@^3.0.0: 215 | version "3.0.0" 216 | resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.0.0.tgz#e1b8669c1803ccc50b545e92f8e6e79aa80e0196" 217 | dependencies: 218 | dot-prop "^4.1.0" 219 | graceful-fs "^4.1.2" 220 | mkdirp "^0.5.0" 221 | unique-string "^1.0.0" 222 | write-file-atomic "^1.1.2" 223 | xdg-basedir "^3.0.0" 224 | 225 | core-util-is@~1.0.0: 226 | version "1.0.2" 227 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 228 | 229 | create-error-class@^3.0.0: 230 | version "3.0.2" 231 | resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" 232 | dependencies: 233 | capture-stack-trace "^1.0.0" 234 | 235 | cross-spawn-async@^2.1.1: 236 | version "2.2.5" 237 | resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc" 238 | dependencies: 239 | lru-cache "^4.0.0" 240 | which "^1.2.8" 241 | 242 | cross-spawn@^4.0.0: 243 | version "4.0.2" 244 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" 245 | dependencies: 246 | lru-cache "^4.0.1" 247 | which "^1.2.9" 248 | 249 | cryptiles@2.x.x: 250 | version "2.0.5" 251 | resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" 252 | dependencies: 253 | boom "2.x.x" 254 | 255 | crypto-random-string@^1.0.0: 256 | version "1.0.0" 257 | resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" 258 | 259 | cycle@1.0.x: 260 | version "1.0.3" 261 | resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" 262 | 263 | dashdash@^1.12.0: 264 | version "1.14.1" 265 | resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 266 | dependencies: 267 | assert-plus "^1.0.0" 268 | 269 | debug@^2.6.7: 270 | version "2.6.8" 271 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" 272 | dependencies: 273 | ms "2.0.0" 274 | 275 | debug@~2.2.0: 276 | version "2.2.0" 277 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" 278 | dependencies: 279 | ms "0.7.1" 280 | 281 | deep-equal@~0.2.1: 282 | version "0.2.2" 283 | resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d" 284 | 285 | deep-extend@~0.4.0: 286 | version "0.4.1" 287 | resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253" 288 | 289 | delayed-stream@~1.0.0: 290 | version "1.0.0" 291 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 292 | 293 | dot-prop@^4.1.0: 294 | version "4.1.1" 295 | resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.1.1.tgz#a8493f0b7b5eeec82525b5c7587fa7de7ca859c1" 296 | dependencies: 297 | is-obj "^1.0.0" 298 | 299 | duplexer3@^0.1.4: 300 | version "0.1.4" 301 | resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" 302 | 303 | ecc-jsbn@~0.1.1: 304 | version "0.1.1" 305 | resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" 306 | dependencies: 307 | jsbn "~0.1.0" 308 | 309 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 310 | version "1.0.5" 311 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 312 | 313 | esprima@^3.1.1: 314 | version "3.1.3" 315 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" 316 | 317 | execa@^0.4.0: 318 | version "0.4.0" 319 | resolved "https://registry.yarnpkg.com/execa/-/execa-0.4.0.tgz#4eb6467a36a095fabb2970ff9d5e3fb7bce6ebc3" 320 | dependencies: 321 | cross-spawn-async "^2.1.1" 322 | is-stream "^1.1.0" 323 | npm-run-path "^1.0.0" 324 | object-assign "^4.0.1" 325 | path-key "^1.0.0" 326 | strip-eof "^1.0.0" 327 | 328 | extend@~3.0.0: 329 | version "3.0.0" 330 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" 331 | 332 | external-editor@^2.0.1: 333 | version "2.0.1" 334 | resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.1.tgz#4c597c6c88fa6410e41dbbaa7b1be2336aa31095" 335 | dependencies: 336 | tmp "^0.0.31" 337 | 338 | extsprintf@1.0.2: 339 | version "1.0.2" 340 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" 341 | 342 | eyes@0.1.x: 343 | version "0.1.8" 344 | resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" 345 | 346 | figures@^2.0.0: 347 | version "2.0.0" 348 | resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" 349 | dependencies: 350 | escape-string-regexp "^1.0.5" 351 | 352 | forever-agent@~0.6.1: 353 | version "0.6.1" 354 | resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" 355 | 356 | form-data@~2.1.1: 357 | version "2.1.2" 358 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4" 359 | dependencies: 360 | asynckit "^0.4.0" 361 | combined-stream "^1.0.5" 362 | mime-types "^2.1.12" 363 | 364 | fs-extended@^0.2.1: 365 | version "0.2.1" 366 | resolved "https://registry.yarnpkg.com/fs-extended/-/fs-extended-0.2.1.tgz#3910358127e9c72c8296c30142c7763b5f5e2d3a" 367 | 368 | fs.realpath@^1.0.0: 369 | version "1.0.0" 370 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 371 | 372 | "fstream@>= 0.1.30 < 1": 373 | version "0.1.31" 374 | resolved "https://registry.yarnpkg.com/fstream/-/fstream-0.1.31.tgz#7337f058fbbbbefa8c9f561a28cab0849202c988" 375 | dependencies: 376 | graceful-fs "~3.0.2" 377 | inherits "~2.0.0" 378 | mkdirp "0.5" 379 | rimraf "2" 380 | 381 | generate-password@^1.3.0: 382 | version "1.3.0" 383 | resolved "https://registry.yarnpkg.com/generate-password/-/generate-password-1.3.0.tgz#4da4c154530d21c1995a77aac5a3ea04882fc8ad" 384 | 385 | get-stream@^3.0.0: 386 | version "3.0.0" 387 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" 388 | 389 | getpass@^0.1.1: 390 | version "0.1.6" 391 | resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" 392 | dependencies: 393 | assert-plus "^1.0.0" 394 | 395 | glob@^7.0.5: 396 | version "7.1.1" 397 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" 398 | dependencies: 399 | fs.realpath "^1.0.0" 400 | inflight "^1.0.4" 401 | inherits "2" 402 | minimatch "^3.0.2" 403 | once "^1.3.0" 404 | path-is-absolute "^1.0.0" 405 | 406 | gm@^1.23.0: 407 | version "1.23.0" 408 | resolved "https://registry.yarnpkg.com/gm/-/gm-1.23.0.tgz#80a2fe9cbf131515024846444658461269f52661" 409 | dependencies: 410 | array-parallel "~0.1.3" 411 | array-series "~0.1.5" 412 | cross-spawn "^4.0.0" 413 | debug "~2.2.0" 414 | 415 | got@^6.7.1: 416 | version "6.7.1" 417 | resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" 418 | dependencies: 419 | create-error-class "^3.0.0" 420 | duplexer3 "^0.1.4" 421 | get-stream "^3.0.0" 422 | is-redirect "^1.0.0" 423 | is-retry-allowed "^1.0.0" 424 | is-stream "^1.0.0" 425 | lowercase-keys "^1.0.0" 426 | safe-buffer "^5.0.1" 427 | timed-out "^4.0.0" 428 | unzip-response "^2.0.1" 429 | url-parse-lax "^1.0.0" 430 | 431 | graceful-fs@^4.1.11, graceful-fs@^4.1.2: 432 | version "4.1.11" 433 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 434 | 435 | graceful-fs@~3.0.2: 436 | version "3.0.11" 437 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818" 438 | dependencies: 439 | natives "^1.1.0" 440 | 441 | "graceful-readlink@>= 1.0.0": 442 | version "1.0.1" 443 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 444 | 445 | har-schema@^1.0.5: 446 | version "1.0.5" 447 | resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" 448 | 449 | har-validator@~4.2.1: 450 | version "4.2.1" 451 | resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" 452 | dependencies: 453 | ajv "^4.9.1" 454 | har-schema "^1.0.5" 455 | 456 | has-ansi@^2.0.0: 457 | version "2.0.0" 458 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 459 | dependencies: 460 | ansi-regex "^2.0.0" 461 | 462 | hawk@~3.1.3: 463 | version "3.1.3" 464 | resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" 465 | dependencies: 466 | boom "2.x.x" 467 | cryptiles "2.x.x" 468 | hoek "2.x.x" 469 | sntp "1.x.x" 470 | 471 | hoek@2.x.x: 472 | version "2.16.3" 473 | resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" 474 | 475 | http-signature@~1.1.0: 476 | version "1.1.1" 477 | resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" 478 | dependencies: 479 | assert-plus "^0.2.0" 480 | jsprim "^1.2.2" 481 | sshpk "^1.7.0" 482 | 483 | i@0.3.x: 484 | version "0.3.5" 485 | resolved "https://registry.yarnpkg.com/i/-/i-0.3.5.tgz#1d2b854158ec8169113c6cb7f6b6801e99e211d5" 486 | 487 | image-size@^0.5.1: 488 | version "0.5.1" 489 | resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.1.tgz#28eea8548a4b1443480ddddc1e083ae54652439f" 490 | 491 | imurmurhash@^0.1.4: 492 | version "0.1.4" 493 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 494 | 495 | inflight@^1.0.4: 496 | version "1.0.6" 497 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 498 | dependencies: 499 | once "^1.3.0" 500 | wrappy "1" 501 | 502 | inherits@2, inherits@~2.0.0, inherits@~2.0.1: 503 | version "2.0.3" 504 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 505 | 506 | ini@~1.3.0: 507 | version "1.3.4" 508 | resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" 509 | 510 | inquirer@^3.0.6: 511 | version "3.0.6" 512 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" 513 | dependencies: 514 | ansi-escapes "^1.1.0" 515 | chalk "^1.0.0" 516 | cli-cursor "^2.1.0" 517 | cli-width "^2.0.0" 518 | external-editor "^2.0.1" 519 | figures "^2.0.0" 520 | lodash "^4.3.0" 521 | mute-stream "0.0.7" 522 | run-async "^2.2.0" 523 | rx "^4.1.0" 524 | string-width "^2.0.0" 525 | strip-ansi "^3.0.0" 526 | through "^2.3.6" 527 | 528 | is-fullwidth-code-point@^1.0.0: 529 | version "1.0.0" 530 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 531 | dependencies: 532 | number-is-nan "^1.0.0" 533 | 534 | is-fullwidth-code-point@^2.0.0: 535 | version "2.0.0" 536 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 537 | 538 | is-npm@^1.0.0: 539 | version "1.0.0" 540 | resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" 541 | 542 | is-obj@^1.0.0: 543 | version "1.0.1" 544 | resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" 545 | 546 | is-promise@^2.1.0: 547 | version "2.1.0" 548 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 549 | 550 | is-redirect@^1.0.0: 551 | version "1.0.0" 552 | resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" 553 | 554 | is-retry-allowed@^1.0.0: 555 | version "1.1.0" 556 | resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" 557 | 558 | is-stream@^1.0.0, is-stream@^1.1.0: 559 | version "1.1.0" 560 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 561 | 562 | is-typedarray@~1.0.0: 563 | version "1.0.0" 564 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 565 | 566 | isarray@0.0.1: 567 | version "0.0.1" 568 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" 569 | 570 | isexe@^2.0.0: 571 | version "2.0.0" 572 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 573 | 574 | isstream@0.1.x, isstream@~0.1.2: 575 | version "0.1.2" 576 | resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 577 | 578 | jodid25519@^1.0.0: 579 | version "1.0.2" 580 | resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" 581 | dependencies: 582 | jsbn "~0.1.0" 583 | 584 | js-yaml@^3.8.3: 585 | version "3.8.3" 586 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.3.tgz#33a05ec481c850c8875929166fe1beb61c728766" 587 | dependencies: 588 | argparse "^1.0.7" 589 | esprima "^3.1.1" 590 | 591 | jsbn@~0.1.0: 592 | version "0.1.1" 593 | resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" 594 | 595 | json-schema@0.2.3: 596 | version "0.2.3" 597 | resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" 598 | 599 | json-stable-stringify@^1.0.1: 600 | version "1.0.1" 601 | resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" 602 | dependencies: 603 | jsonify "~0.0.0" 604 | 605 | json-stringify-safe@~5.0.1: 606 | version "5.0.1" 607 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 608 | 609 | jsonify@~0.0.0: 610 | version "0.0.0" 611 | resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" 612 | 613 | jsprim@^1.2.2: 614 | version "1.4.0" 615 | resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918" 616 | dependencies: 617 | assert-plus "1.0.0" 618 | extsprintf "1.0.2" 619 | json-schema "0.2.3" 620 | verror "1.3.6" 621 | 622 | latest-version@^3.0.0: 623 | version "3.1.0" 624 | resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" 625 | dependencies: 626 | package-json "^4.0.0" 627 | 628 | lazy-req@^2.0.0: 629 | version "2.0.0" 630 | resolved "https://registry.yarnpkg.com/lazy-req/-/lazy-req-2.0.0.tgz#c9450a363ecdda2e6f0c70132ad4f37f8f06f2b4" 631 | 632 | lodash@^4.14.0, lodash@^4.3.0: 633 | version "4.17.4" 634 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 635 | 636 | lowercase-keys@^1.0.0: 637 | version "1.0.0" 638 | resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" 639 | 640 | lru-cache@^4.0.0, lru-cache@^4.0.1: 641 | version "4.0.2" 642 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" 643 | dependencies: 644 | pseudomap "^1.0.1" 645 | yallist "^2.0.0" 646 | 647 | "match-stream@>= 0.0.2 < 1": 648 | version "0.0.2" 649 | resolved "https://registry.yarnpkg.com/match-stream/-/match-stream-0.0.2.tgz#99eb050093b34dffade421b9ac0b410a9cfa17cf" 650 | dependencies: 651 | buffers "~0.1.1" 652 | readable-stream "~1.0.0" 653 | 654 | mime-db@~1.27.0: 655 | version "1.27.0" 656 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1" 657 | 658 | mime-types@^2.1.12, mime-types@~2.1.7: 659 | version "2.1.15" 660 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed" 661 | dependencies: 662 | mime-db "~1.27.0" 663 | 664 | mimic-fn@^1.0.0: 665 | version "1.1.0" 666 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" 667 | 668 | minimatch@^3.0.2: 669 | version "3.0.3" 670 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" 671 | dependencies: 672 | brace-expansion "^1.0.0" 673 | 674 | minimist@0.0.8: 675 | version "0.0.8" 676 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 677 | 678 | minimist@^1.2.0: 679 | version "1.2.0" 680 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" 681 | 682 | mkdirp@0.5, mkdirp@0.x.x, mkdirp@^0.5.0: 683 | version "0.5.1" 684 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 685 | dependencies: 686 | minimist "0.0.8" 687 | 688 | ms@0.7.1: 689 | version "0.7.1" 690 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" 691 | 692 | ms@2.0.0: 693 | version "2.0.0" 694 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 695 | 696 | mute-stream@0.0.7, mute-stream@~0.0.4: 697 | version "0.0.7" 698 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" 699 | 700 | natives@^1.1.0: 701 | version "1.1.0" 702 | resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.0.tgz#e9ff841418a6b2ec7a495e939984f78f163e6e31" 703 | 704 | ncp@1.0.x: 705 | version "1.0.1" 706 | resolved "https://registry.yarnpkg.com/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" 707 | 708 | node-env-file@^0.1.8: 709 | version "0.1.8" 710 | resolved "https://registry.yarnpkg.com/node-env-file/-/node-env-file-0.1.8.tgz#fccb7b050f735b5a33da9eb937cf6f1ab457fb69" 711 | 712 | npm-run-path@^1.0.0: 713 | version "1.0.0" 714 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-1.0.0.tgz#f5c32bf595fe81ae927daec52e82f8b000ac3c8f" 715 | dependencies: 716 | path-key "^1.0.0" 717 | 718 | number-is-nan@^1.0.0: 719 | version "1.0.1" 720 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 721 | 722 | oauth-sign@~0.8.1: 723 | version "0.8.2" 724 | resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" 725 | 726 | object-assign@^4.0.1: 727 | version "4.1.1" 728 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 729 | 730 | once@^1.3.0: 731 | version "1.4.0" 732 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 733 | dependencies: 734 | wrappy "1" 735 | 736 | onetime@^2.0.0: 737 | version "2.0.1" 738 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" 739 | dependencies: 740 | mimic-fn "^1.0.0" 741 | 742 | os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: 743 | version "1.0.2" 744 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 745 | 746 | "over@>= 0.0.5 < 1": 747 | version "0.0.5" 748 | resolved "https://registry.yarnpkg.com/over/-/over-0.0.5.tgz#f29852e70fd7e25f360e013a8ec44c82aedb5708" 749 | 750 | package-json@^4.0.0: 751 | version "4.0.1" 752 | resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" 753 | dependencies: 754 | got "^6.7.1" 755 | registry-auth-token "^3.0.1" 756 | registry-url "^3.0.3" 757 | semver "^5.1.0" 758 | 759 | path-is-absolute@^1.0.0: 760 | version "1.0.1" 761 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 762 | 763 | path-key@^1.0.0: 764 | version "1.0.0" 765 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-1.0.0.tgz#5d53d578019646c0d68800db4e146e6bdc2ac7af" 766 | 767 | pem@^1.9.4: 768 | version "1.9.4" 769 | resolved "https://registry.yarnpkg.com/pem/-/pem-1.9.4.tgz#63e89c49c17629610e978e87514e5cdbf498374f" 770 | dependencies: 771 | os-tmpdir "^1.0.1" 772 | which "^1.2.4" 773 | 774 | performance-now@^0.2.0: 775 | version "0.2.0" 776 | resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" 777 | 778 | pkginfo@0.3.x: 779 | version "0.3.1" 780 | resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" 781 | 782 | pkginfo@0.x.x: 783 | version "0.4.0" 784 | resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.0.tgz#349dbb7ffd38081fcadc0853df687f0c7744cd65" 785 | 786 | prepend-http@^1.0.1: 787 | version "1.0.4" 788 | resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" 789 | 790 | prompt@^1.0.0: 791 | version "1.0.0" 792 | resolved "https://registry.yarnpkg.com/prompt/-/prompt-1.0.0.tgz#8e57123c396ab988897fb327fd3aedc3e735e4fe" 793 | dependencies: 794 | colors "^1.1.2" 795 | pkginfo "0.x.x" 796 | read "1.0.x" 797 | revalidator "0.1.x" 798 | utile "0.3.x" 799 | winston "2.1.x" 800 | 801 | pseudomap@^1.0.1: 802 | version "1.0.2" 803 | resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" 804 | 805 | "pullstream@>= 0.4.1 < 1": 806 | version "0.4.1" 807 | resolved "https://registry.yarnpkg.com/pullstream/-/pullstream-0.4.1.tgz#d6fb3bf5aed697e831150eb1002c25a3f8ae1314" 808 | dependencies: 809 | over ">= 0.0.5 < 1" 810 | readable-stream "~1.0.31" 811 | setimmediate ">= 1.0.2 < 2" 812 | slice-stream ">= 1.0.0 < 2" 813 | 814 | punycode@^1.4.1: 815 | version "1.4.1" 816 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" 817 | 818 | q@^1.5.0: 819 | version "1.5.0" 820 | resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" 821 | 822 | qs@~6.4.0: 823 | version "6.4.0" 824 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" 825 | 826 | rc@^1.0.1, rc@^1.1.6: 827 | version "1.1.7" 828 | resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.7.tgz#c5ea564bb07aff9fd3a5b32e906c1d3a65940fea" 829 | dependencies: 830 | deep-extend "~0.4.0" 831 | ini "~1.3.0" 832 | minimist "^1.2.0" 833 | strip-json-comments "~2.0.1" 834 | 835 | read@1.0.x: 836 | version "1.0.7" 837 | resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" 838 | dependencies: 839 | mute-stream "~0.0.4" 840 | 841 | readable-stream@~1.0.0, readable-stream@~1.0.31: 842 | version "1.0.34" 843 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" 844 | dependencies: 845 | core-util-is "~1.0.0" 846 | inherits "~2.0.1" 847 | isarray "0.0.1" 848 | string_decoder "~0.10.x" 849 | 850 | registry-auth-token@^3.0.1: 851 | version "3.3.0" 852 | resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.0.tgz#57ae67347e73d96345ed1bc01294c7237c02aa63" 853 | dependencies: 854 | rc "^1.1.6" 855 | safe-buffer "^5.0.1" 856 | 857 | registry-url@^3.0.3: 858 | version "3.1.0" 859 | resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" 860 | dependencies: 861 | rc "^1.0.1" 862 | 863 | request@2.x, request@^2.81.0: 864 | version "2.81.0" 865 | resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" 866 | dependencies: 867 | aws-sign2 "~0.6.0" 868 | aws4 "^1.2.1" 869 | caseless "~0.12.0" 870 | combined-stream "~1.0.5" 871 | extend "~3.0.0" 872 | forever-agent "~0.6.1" 873 | form-data "~2.1.1" 874 | har-validator "~4.2.1" 875 | hawk "~3.1.3" 876 | http-signature "~1.1.0" 877 | is-typedarray "~1.0.0" 878 | isstream "~0.1.2" 879 | json-stringify-safe "~5.0.1" 880 | mime-types "~2.1.7" 881 | oauth-sign "~0.8.1" 882 | performance-now "^0.2.0" 883 | qs "~6.4.0" 884 | safe-buffer "^5.0.1" 885 | stringstream "~0.0.4" 886 | tough-cookie "~2.3.0" 887 | tunnel-agent "^0.6.0" 888 | uuid "^3.0.0" 889 | 890 | restore-cursor@^2.0.0: 891 | version "2.0.0" 892 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" 893 | dependencies: 894 | onetime "^2.0.0" 895 | signal-exit "^3.0.2" 896 | 897 | revalidator@0.1.x: 898 | version "0.1.8" 899 | resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" 900 | 901 | rimraf@2, rimraf@2.x.x: 902 | version "2.6.1" 903 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" 904 | dependencies: 905 | glob "^7.0.5" 906 | 907 | run-async@^2.2.0: 908 | version "2.3.0" 909 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" 910 | dependencies: 911 | is-promise "^2.1.0" 912 | 913 | rx@^4.1.0: 914 | version "4.1.0" 915 | resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" 916 | 917 | safe-buffer@^5.0.1: 918 | version "5.0.1" 919 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" 920 | 921 | semver-diff@^2.0.0: 922 | version "2.1.0" 923 | resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" 924 | dependencies: 925 | semver "^5.0.3" 926 | 927 | semver@^5.0.3, semver@^5.1.0: 928 | version "5.3.0" 929 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" 930 | 931 | "setimmediate@>= 1.0.1 < 2", "setimmediate@>= 1.0.2 < 2": 932 | version "1.0.5" 933 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" 934 | 935 | shell-escape@^0.2.0: 936 | version "0.2.0" 937 | resolved "https://registry.yarnpkg.com/shell-escape/-/shell-escape-0.2.0.tgz#68fd025eb0490b4f567a027f0bf22480b5f84133" 938 | 939 | signal-exit@^3.0.2: 940 | version "3.0.2" 941 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 942 | 943 | simple-git@^1.72.0: 944 | version "1.73.0" 945 | resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.73.0.tgz#87683a729b1bee016a3182f95a2ab72317bb0230" 946 | dependencies: 947 | debug "^2.6.7" 948 | 949 | "slice-stream@>= 1.0.0 < 2": 950 | version "1.0.0" 951 | resolved "https://registry.yarnpkg.com/slice-stream/-/slice-stream-1.0.0.tgz#5b33bd66f013b1a7f86460b03d463dec39ad3ea0" 952 | dependencies: 953 | readable-stream "~1.0.31" 954 | 955 | slide@^1.1.5: 956 | version "1.1.6" 957 | resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" 958 | 959 | sntp@1.x.x: 960 | version "1.0.9" 961 | resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" 962 | dependencies: 963 | hoek "2.x.x" 964 | 965 | source-map@0.1.34: 966 | version "0.1.34" 967 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.34.tgz#a7cfe89aec7b1682c3b198d0acfb47d7d090566b" 968 | dependencies: 969 | amdefine ">=0.0.4" 970 | 971 | sprintf-js@^1.0.3, sprintf-js@~1.0.2: 972 | version "1.0.3" 973 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 974 | 975 | sshpk@^1.7.0: 976 | version "1.11.0" 977 | resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.11.0.tgz#2d8d5ebb4a6fab28ffba37fa62a90f4a3ea59d77" 978 | dependencies: 979 | asn1 "~0.2.3" 980 | assert-plus "^1.0.0" 981 | dashdash "^1.12.0" 982 | getpass "^0.1.1" 983 | optionalDependencies: 984 | bcrypt-pbkdf "^1.0.0" 985 | ecc-jsbn "~0.1.1" 986 | jodid25519 "^1.0.0" 987 | jsbn "~0.1.0" 988 | tweetnacl "~0.14.0" 989 | 990 | stack-trace@0.0.x: 991 | version "0.0.9" 992 | resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695" 993 | 994 | string-width@^1.0.1: 995 | version "1.0.2" 996 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 997 | dependencies: 998 | code-point-at "^1.0.0" 999 | is-fullwidth-code-point "^1.0.0" 1000 | strip-ansi "^3.0.0" 1001 | 1002 | string-width@^2.0.0: 1003 | version "2.0.0" 1004 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" 1005 | dependencies: 1006 | is-fullwidth-code-point "^2.0.0" 1007 | strip-ansi "^3.0.0" 1008 | 1009 | string_decoder@~0.10.x: 1010 | version "0.10.31" 1011 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" 1012 | 1013 | stringstream@~0.0.4: 1014 | version "0.0.5" 1015 | resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" 1016 | 1017 | strip-ansi@^3.0.0: 1018 | version "3.0.1" 1019 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 1020 | dependencies: 1021 | ansi-regex "^2.0.0" 1022 | 1023 | strip-eof@^1.0.0: 1024 | version "1.0.0" 1025 | resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" 1026 | 1027 | strip-json-comments@~2.0.1: 1028 | version "2.0.1" 1029 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 1030 | 1031 | supports-color@^2.0.0: 1032 | version "2.0.0" 1033 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 1034 | 1035 | term-size@^0.1.0: 1036 | version "0.1.1" 1037 | resolved "https://registry.yarnpkg.com/term-size/-/term-size-0.1.1.tgz#87360b96396cab5760963714cda0d0cbeecad9ca" 1038 | dependencies: 1039 | execa "^0.4.0" 1040 | 1041 | through@^2.3.6: 1042 | version "2.3.8" 1043 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1044 | 1045 | timed-out@^4.0.0: 1046 | version "4.0.1" 1047 | resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" 1048 | 1049 | tmp@^0.0.31: 1050 | version "0.0.31" 1051 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" 1052 | dependencies: 1053 | os-tmpdir "~1.0.1" 1054 | 1055 | tough-cookie@~2.3.0: 1056 | version "2.3.2" 1057 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" 1058 | dependencies: 1059 | punycode "^1.4.1" 1060 | 1061 | "traverse@>=0.3.0 <0.4": 1062 | version "0.3.9" 1063 | resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" 1064 | 1065 | tunnel-agent@^0.6.0: 1066 | version "0.6.0" 1067 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 1068 | dependencies: 1069 | safe-buffer "^5.0.1" 1070 | 1071 | tweetnacl@^0.14.3, tweetnacl@~0.14.0: 1072 | version "0.14.5" 1073 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 1074 | 1075 | uglify-to-browserify@~1.0.0: 1076 | version "1.0.2" 1077 | resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" 1078 | 1079 | uglifyjs@^2.4.10: 1080 | version "2.4.10" 1081 | resolved "https://registry.yarnpkg.com/uglifyjs/-/uglifyjs-2.4.10.tgz#632927319fa6a3da3fc91f9773ac27bfe6c3ee92" 1082 | dependencies: 1083 | async "~0.2.6" 1084 | source-map "0.1.34" 1085 | uglify-to-browserify "~1.0.0" 1086 | yargs "~1.3.3" 1087 | 1088 | underscore.string@^3.3.4: 1089 | version "3.3.4" 1090 | resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.4.tgz#2c2a3f9f83e64762fdc45e6ceac65142864213db" 1091 | dependencies: 1092 | sprintf-js "^1.0.3" 1093 | util-deprecate "^1.0.2" 1094 | 1095 | underscore@1.x, underscore@^1.8.3: 1096 | version "1.8.3" 1097 | resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" 1098 | 1099 | unique-string@^1.0.0: 1100 | version "1.0.0" 1101 | resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" 1102 | dependencies: 1103 | crypto-random-string "^1.0.0" 1104 | 1105 | universal-analytics@^0.4.13: 1106 | version "0.4.13" 1107 | resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.13.tgz#dc6829ff7297ae1b4f8d1427d5a945521f1bba26" 1108 | dependencies: 1109 | async "1.2.x" 1110 | request "2.x" 1111 | underscore "1.x" 1112 | uuid "^3.0.0" 1113 | 1114 | unzip-response@^2.0.1: 1115 | version "2.0.1" 1116 | resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" 1117 | 1118 | unzip@^0.1.11: 1119 | version "0.1.11" 1120 | resolved "https://registry.yarnpkg.com/unzip/-/unzip-0.1.11.tgz#89749c63b058d7d90d619f86b98aa1535d3b97f0" 1121 | dependencies: 1122 | binary ">= 0.3.0 < 1" 1123 | fstream ">= 0.1.30 < 1" 1124 | match-stream ">= 0.0.2 < 1" 1125 | pullstream ">= 0.4.1 < 1" 1126 | readable-stream "~1.0.31" 1127 | setimmediate ">= 1.0.1 < 2" 1128 | 1129 | update-notifier@^2.1.0: 1130 | version "2.1.0" 1131 | resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.1.0.tgz#ec0c1e53536b76647a24b77cb83966d9315123d9" 1132 | dependencies: 1133 | boxen "^1.0.0" 1134 | chalk "^1.0.0" 1135 | configstore "^3.0.0" 1136 | is-npm "^1.0.0" 1137 | latest-version "^3.0.0" 1138 | lazy-req "^2.0.0" 1139 | semver-diff "^2.0.0" 1140 | xdg-basedir "^3.0.0" 1141 | 1142 | url-parse-lax@^1.0.0: 1143 | version "1.0.0" 1144 | resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" 1145 | dependencies: 1146 | prepend-http "^1.0.1" 1147 | 1148 | util-deprecate@^1.0.2: 1149 | version "1.0.2" 1150 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1151 | 1152 | utile@0.3.x: 1153 | version "0.3.0" 1154 | resolved "https://registry.yarnpkg.com/utile/-/utile-0.3.0.tgz#1352c340eb820e4d8ddba039a4fbfaa32ed4ef3a" 1155 | dependencies: 1156 | async "~0.9.0" 1157 | deep-equal "~0.2.1" 1158 | i "0.3.x" 1159 | mkdirp "0.x.x" 1160 | ncp "1.0.x" 1161 | rimraf "2.x.x" 1162 | 1163 | uuid@^3.0.0: 1164 | version "3.0.1" 1165 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" 1166 | 1167 | verror@1.3.6: 1168 | version "1.3.6" 1169 | resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" 1170 | dependencies: 1171 | extsprintf "1.0.2" 1172 | 1173 | which@^1.2.4, which@^1.2.8, which@^1.2.9: 1174 | version "1.2.14" 1175 | resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" 1176 | dependencies: 1177 | isexe "^2.0.0" 1178 | 1179 | widest-line@^1.0.0: 1180 | version "1.0.0" 1181 | resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-1.0.0.tgz#0c09c85c2a94683d0d7eaf8ee097d564bf0e105c" 1182 | dependencies: 1183 | string-width "^1.0.1" 1184 | 1185 | winston@2.1.x: 1186 | version "2.1.1" 1187 | resolved "https://registry.yarnpkg.com/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e" 1188 | dependencies: 1189 | async "~1.0.0" 1190 | colors "1.0.x" 1191 | cycle "1.0.x" 1192 | eyes "0.1.x" 1193 | isstream "0.1.x" 1194 | pkginfo "0.3.x" 1195 | stack-trace "0.0.x" 1196 | 1197 | wrappy@1: 1198 | version "1.0.2" 1199 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1200 | 1201 | write-file-atomic@^1.1.2: 1202 | version "1.3.4" 1203 | resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" 1204 | dependencies: 1205 | graceful-fs "^4.1.11" 1206 | imurmurhash "^0.1.4" 1207 | slide "^1.1.5" 1208 | 1209 | xdg-basedir@^3.0.0: 1210 | version "3.0.0" 1211 | resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" 1212 | 1213 | yallist@^2.0.0: 1214 | version "2.1.2" 1215 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" 1216 | 1217 | yamljs@^0.2.10: 1218 | version "0.2.10" 1219 | resolved "https://registry.yarnpkg.com/yamljs/-/yamljs-0.2.10.tgz#481cc7c25ca73af59f591f0c96e3ce56c757a40f" 1220 | dependencies: 1221 | argparse "^1.0.7" 1222 | glob "^7.0.5" 1223 | 1224 | yargs@~1.3.3: 1225 | version "1.3.3" 1226 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.3.3.tgz#054de8b61f22eefdb7207059eaef9d6b83fb931a" 1227 | --------------------------------------------------------------------------------