diff --git a/.eslintrc b/.eslintrc index 0e91e04..91b2eaa 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,5 @@ { - "extends": "airbnb-base", + "extends": ["airbnb-base", "prettier"], "env": { "node": true, "mocha": true @@ -9,11 +9,9 @@ "no-underscore-dangle": [ "error", { - "allow": [ - "_id" - ] + "allow": ["_id"] } ], - "import/no-named-as-default": 0 + "import/no-named-as-default": "off" } } diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..dc75c8a --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "trailingComma": "all", + "tabWidth": 2, + "semi": true, + "singleQuote": true +} diff --git a/package.json b/package.json index 67c7419..9e83b03 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "babel-eslint": "10.1.0", "eslint": "6.8.0", "eslint-config-airbnb-base": "14.1.0", + "eslint-config-prettier": "6.11.0", "eslint-plugin-import": "2.20.1", "husky": "4.2.3", "npm-run-all": "4.1.5", @@ -55,14 +56,20 @@ }, "dependencies": { "@babel/polyfill": "7.8.7", + "async": "3.2.0", + "aws-sdk": "2.713.0", "bson-objectid": "1.3.0", + "cli-progress": "3.8.2", "del": "4.1.1", + "dotenv": "8.2.0", "execa": "1.0.0", "fs-exists-cached": "1.0.0", "fs-extra": "7.0.1", "hosted-git-info": "2.7.1", "inquirer": "6.2.2", "lodash": "4.17.19", + "recursive-readdir": "2.2.2", + "s3-node-client": "4.4.4", "yargs": "12.0.5" } } diff --git a/src/config.js b/src/config.js index bfd1fd7..9e2d689 100644 --- a/src/config.js +++ b/src/config.js @@ -14,3 +14,7 @@ export const AWS_SECRET_ACCESS_KEY_LENGTH = 40; // file names export const GRAASP_IGNORE_FILE = '.graaspignore'; + +// deploy settings +export const DEFAULT_BUILD_DIR = './build'; +export const DEFAULT_APP_VERSION = 'latest'; diff --git a/src/createCli.js b/src/createCli.js index ffbd4b8..fcca0d4 100644 --- a/src/createCli.js +++ b/src/createCli.js @@ -1,13 +1,11 @@ import yargs from 'yargs'; import prompt from './prompt'; -import { DEFAULT_STARTER } from './config'; - -const promisify = (fn) => (...args) => { - Promise.resolve(fn(...args)).then( - () => process.exit(0), - // err => report.panic(err) - ); -}; +import deploy from './deploy'; +import { + DEFAULT_STARTER, + DEFAULT_BUILD_DIR, + DEFAULT_APP_VERSION, +} from './config'; const createCli = (argv) => { const cli = yargs(); @@ -33,25 +31,52 @@ const createCli = (argv) => { .command({ command: 'new', desc: 'Create new Graasp app.', - builder: (_) => _.option('s', { - alias: 'starter', - type: 'string', - default: DEFAULT_STARTER, - describe: `Set starter. Defaults to ${DEFAULT_STARTER}`, - }).option('f', { - alias: 'framework', - type: 'string', - describe: 'Set development framework (e.g. React, Angular)', - }).option('t', { - alias: 'type', - choices: ['app', 'lab'], - describe: 'Type of application (app or lab)', - }).option('p', { - alias: 'path', - type: 'string', - describe: 'Path where project directory will be set up.', - }), - handler: promisify(prompt), + builder: (_) => + _.option('s', { + alias: 'starter', + type: 'string', + default: DEFAULT_STARTER, + describe: `Set starter. Defaults to ${DEFAULT_STARTER}`, + }) + .option('f', { + alias: 'framework', + type: 'string', + describe: 'Set development framework (e.g. React, Angular)', + }) + .option('t', { + alias: 'type', + choices: ['app', 'lab'], + describe: 'Type of application (app or lab)', + }) + .option('p', { + alias: 'path', + type: 'string', + describe: 'Path where project directory will be set up.', + }), + handler: prompt, + }) + .command({ + command: 'deploy', + desc: 'Deploy a Graasp app to AWS', + builder: (_) => + _.option('t', { + alias: 'tag', + type: 'string', + default: DEFAULT_APP_VERSION, + describe: 'Tag the deployment with a version', + }) + .option('e', { + alias: 'env', + type: 'string', + describe: 'Environment file used to load variables from', + }) + .option('b', { + alias: 'build', + type: 'string', + default: DEFAULT_BUILD_DIR, + describe: 'Path to the build directory that will be deployed', + }), + handler: deploy, }) .wrap(cli.terminalWidth()) .demandCommand(1, 'Pass --help to see all available commands and options.') @@ -61,5 +86,4 @@ const createCli = (argv) => { .parse(argv.slice(2)); }; - export default createCli; diff --git a/src/deploy.js b/src/deploy.js new file mode 100644 index 0000000..2c9c229 --- /dev/null +++ b/src/deploy.js @@ -0,0 +1,275 @@ +import aws from 'aws-sdk'; +// import s3 from 's3-node-client'; +import dotenv from 'dotenv'; +import fs from 'fs'; +import cliProgress from 'cli-progress'; +import _ from 'lodash'; +// import { promisify } from './utils'; + +const path = require('path'); +const async = require('async'); +const readdir = require('recursive-readdir'); + +const validateTag = (tag) => { + // Both compilation hints because of backslashes used in RegExp but unecessary by conception in JS Strings + // Furthermore, the escaption is needed so RegExp will interpret the String correctly. + // prettier-ignore + // eslint-disable-next-line no-useless-escape + const pattern = new RegExp('^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\-[0-9A-Za-z]*)?$') + if (tag === 'latest' || pattern.test(tag)) { + console.info(`validated tag ${tag}`); + return true; + } + console.error(`unable to validate version '${tag}'`); + return false; +}; + +const validateEnv = (env) => { + if (fs.existsSync(env)) { + console.info(`validated environment file ${env}`); + return true; + } + console.error(`environment file '${env}' does not exist`); + return false; +}; + +const validateBuild = (build) => { + if (fs.existsSync(build)) { + console.info(`validated build directory ${build}`); + return true; + } + console.error(`build directory '${build}' does not exist`); + return false; +}; + +const validateAppVariables = ({ + REACT_APP_HOST, + REACT_APP_GRAASP_DEVELOPER_ID, + REACT_APP_GRAASP_APP_ID, +}) => { + if ( + _.isUndefined(REACT_APP_HOST) || + _.isUndefined(REACT_APP_GRAASP_DEVELOPER_ID) || + _.isUndefined(REACT_APP_GRAASP_APP_ID) + ) { + console.error( + `environment variables REACT_APP_GRAASP_APP_ID, REACT_APP_GRAASP_DEVELOPER_ID and/or REACT_APP_HOST are not defined \n + you can specify them through a .env file in the app root folder or through another file specified with the -e flag`, + ); + return false; + } + return true; +}; + +const validateAwsCredentialsVariables = ({ + BUCKET, + AWS_ACCESS_KEY_ID, + AWS_SECRET_ACCESS_KEY, +}) => { + if ( + _.isUndefined(BUCKET) || + _.isUndefined(AWS_ACCESS_KEY_ID) || + _.isUndefined(AWS_SECRET_ACCESS_KEY) + ) { + console.error( + `environment variables BUCKET, AWS_ACCESS_KEY_ID and/or AWS_SECRET_ACCESS_KEY are not defined. \n + make sure you setup your credentials file correctly using the scripts/setup.sh script and contact your favourite Graasp engineer if you keep running into trouble`, + ); + return false; + } + return true; +}; + +const loadAwsCredentials = async () => { + const awsCredentials = new aws.Credentials(); + await awsCredentials.getPromise().then( + async () => true, + (err) => { + console.error(err.stack); + return false; + }, + ); + // set the AWS credentials into the global object + aws.config.credentials = awsCredentials; +}; + +function getFiles(dirPath) { + return fs.existsSync(dirPath) ? readdir(dirPath) : []; +} + +async function uploadToS3(s3, uploadPath, bucket) { + const rootFolder = process.cwd(); + const filesToUpload = await getFiles(path.resolve(rootFolder, uploadPath)); + + console.log(filesToUpload); + + return new Promise((resolve, reject) => { + async.eachOfLimit( + filesToUpload, + 10, + async.asyncify(async (file) => { + const Key = file.replace(`${rootFolder}/`, ''); + console.log(`uploading: [${Key}]`); + return new Promise((res, rej) => { + s3.upload( + { + Key, + Bucket: bucket, + Body: fs.readFileSync(file), + }, + // eslint-disable-next-line + (err) => { + if (err) { + return rej(new Error(err)); + } + res({ result: true }); + }, + ); + }); + }), + // eslint-disable-next-line + (err) => { + if (err) { + return reject(new Error(err)); + } + resolve({ result: true }); + }, + ); + }); +} + +const deploy = async (opts) => { + const { tag, env, build } = opts; + + // validate command options + if (!validateTag(tag) || !validateEnv(env) || !validateBuild(build)) { + console.error('aborting deployment...'); + return false; + } + + // load environment variables + dotenv.config({ path: env }); + + // validate environment variables + if ( + !validateAppVariables(process.env) || + !validateAwsCredentialsVariables(process.env) + ) { + return false; + } + + const { + REACT_APP_GRAASP_DEVELOPER_ID, + REACT_APP_GRAASP_APP_ID, + REACT_APP_HOST, + REACT_APP_VERSION, + BUCKET, + DISTRIBUTION, + } = process.env; + + console.info( + `publishing app ${REACT_APP_GRAASP_APP_ID} version ${REACT_APP_VERSION}`, + ); + + loadAwsCredentials(); + + // eslint-disable-next-line + const APP_PATH = `${REACT_APP_GRAASP_DEVELOPER_ID}/${REACT_APP_GRAASP_APP_ID}/${REACT_APP_VERSION}`; + + const uploadFolder = './build'; + + // The name of the bucket that you have created + + const s3 = new aws.S3(); + + await uploadToS3(s3, uploadFolder, BUCKET) + .then(() => { + console.log('upload complete!'); + }) + .catch((err) => { + console.error(err.message); + process.exit(1); + }); + + // ensure the correct distribution variables are defined + if (_.isUndefined(DISTRIBUTION)) { + console.error('environment variable DISTRIBUTION is not defined'); + console.error( + 'contact your favourite Graasp engineer if you keep running into trouble', + ); + return false; + } + + /* + const client = s3.createClient({ s3Client: new aws.S3() }); + + const params = { + localDir: build, + deleteRemoved: true, // default false, whether to remove s3 objects + // that have no corresponding local file. + + s3Params: { + Bucket: BUCKET, + Prefix: APP_PATH, + // other options supported by putObject, except Body and ContentLength. + // See: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property + }, + }; + const progressBar = new cliProgress.SingleBar( + {}, + cliProgress.Presets.shades_classic, + ); + const uploader = client.uploadDir(params); + uploader.on('error', (err) => { + console.error('unable to sync:', err.stack); + }); + uploader.on('progress', () => { + progressBar.start(uploader.progressTotal, 0); + progressBar.update(uploader.progressAmount); + }); + uploader.on('end', () => { + progressBar.stop(); + // TODO: insert here code that should be executed once the upload is done + // e.g. invalidate cache + }); +*/ + console.info( + `published app to https://${REACT_APP_HOST}/${APP_PATH}/index.html`, + ); + + // ensure the correct distribution variables are defined + if (_.isUndefined(DISTRIBUTION)) { + console.error('environment variable DISTRIBUTION is not defined'); + console.error( + 'contact your favourite Graasp engineer if you keep running into trouble', + ); + return false; + } + + // invalidate cloudfront distribution + const pathsToInvalidate = [`/${APP_PATH}/*`]; + const invalidationParams = { + DistributionId: DISTRIBUTION, + InvalidationBatch: { + CallerReference: new Date().toString(), + Paths: { + Quantity: pathsToInvalidate.length, + Items: pathsToInvalidate, + }, + }, + }; + const cloudfront = new aws.CloudFront(); + cloudfront.createInvalidation(invalidationParams, (err, data) => { + if (err) { + // an error occurred + console.error(err, err.stack); + } else { + // successful response + console.info(data); + } + }); + + return true; +}; + +export default deploy; diff --git a/src/initStarter.js b/src/initStarter.js index 17bf81b..e8dc099 100644 --- a/src/initStarter.js +++ b/src/initStarter.js @@ -8,7 +8,7 @@ import del from 'del'; import { sync as existsSync } from 'fs-exists-cached'; import { DEFAULT_PATH, DEFAULT_STARTER, GRAASP_IGNORE_FILE } from './config'; import writeEnvFiles from './writeEnvFiles'; -import { spawn } from './utils'; +import { spawnProcess } from './utils'; const readFile = util.promisify(fs.readFile); @@ -35,7 +35,9 @@ const install = async (rootPath) => { process.chdir(rootPath); try { - const cmd = shouldUseYarn() ? spawn('yarnpkg') : spawn('npm install'); + const cmd = shouldUseYarn() + ? spawnProcess('yarnpkg') + : spawnProcess('npm install'); await cmd; } finally { process.chdir(prevDir); @@ -87,7 +89,7 @@ const commit = async (rootPath) => { process.chdir(rootPath); try { - await spawn('git add -A', { stdio: 'ignore' }); + await spawnProcess('git add -A', { stdio: 'ignore' }); // cannot spawn this because of the way we are splitting the command execSync('git commit -m "chore: initial commit from graasp cli"', { @@ -130,7 +132,7 @@ const clone = async (hostInfo, rootPath) => { console.log(`creating new site from git: ${url}`); - await spawn(`git clone ${branch} ${url} ${rootPath} --single-branch`); + await spawnProcess(`git clone ${branch} ${url} ${rootPath} --single-branch`); console.log('created starter directory layout'); diff --git a/src/utils.js b/src/utils.js index 657d8b9..0735d58 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,8 +1,14 @@ import execa from 'execa'; // use execa to spawn a better child process -/* eslint-disable-next-line import/prefer-default-export */ -export const spawn = (cmd, opts = { stdio: 'inherit' }) => { +export const spawnProcess = (cmd, opts = { stdio: 'inherit' }) => { const [file, ...args] = cmd.split(/\s+/); return execa(file, args, opts); }; + +export const promisify = (fn) => (...args) => { + Promise.resolve(fn(...args)).then( + () => process.exit(0), + // err => report.panic(err) + ); +}; diff --git a/yarn.lock b/yarn.lock index a08f6a2..e59334c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1164,11 +1164,46 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== +async@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" + integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw== + atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +aws-sdk@2.67.0: + version "2.67.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.67.0.tgz#c0fc3a4343cfc631265d9dd6bc50ba709401f857" + integrity sha1-wPw6Q0PPxjEmXZ3WvFC6cJQB+Fc= + dependencies: + buffer "5.0.6" + crypto-browserify "1.0.9" + jmespath "0.15.0" + querystring "0.2.0" + sax "1.2.1" + url "0.10.3" + uuid "3.0.1" + xml2js "0.4.17" + xmlbuilder "4.2.1" + +aws-sdk@2.713.0: + version "2.713.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.713.0.tgz#e87404ddcba093d36afafb48f119ec66f654a83f" + integrity sha512-axR1eOVn134KXJc1IT+Au2TXcK6oswY+4nvGe5GfU3pXeehhe0xNeP9Bw9yF36TRBxuvu4IJ2hRHDKma05smgA== + dependencies: + buffer "4.9.2" + events "1.1.1" + ieee754 "1.1.13" + jmespath "0.15.0" + querystring "0.2.0" + sax "1.2.1" + url "0.10.3" + uuid "3.3.2" + xml2js "0.4.19" + babel-eslint@10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" @@ -1210,6 +1245,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base64-js@^1.0.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== + base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -1279,6 +1319,23 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +buffer@4.9.2: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +buffer@5.0.6: + version "5.0.6" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.6.tgz#2ea669f7eec0b6eda05b08f8b5ff661b28573588" + integrity sha1-LqZp9+7Atu2gWwj4tf9mGyhXNYg= + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -1430,6 +1487,14 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" +cli-progress@3.8.2: + version "3.8.2" + resolved "https://registry.yarnpkg.com/cli-progress/-/cli-progress-3.8.2.tgz#abaf1fc6d6401351f16f068117a410554a0eb8c7" + integrity sha512-qRwBxLldMSfxB+YGFgNRaj5vyyHe1yMpVeDL79c+7puGujdKJHQHydgqXDcrkvQgJ5U/d3lpf6vffSoVVUftVQ== + dependencies: + colors "^1.1.2" + string-width "^4.2.0" + cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" @@ -1490,6 +1555,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colors@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + commander@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" @@ -1799,6 +1869,11 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +crypto-browserify@1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-1.0.9.tgz#cc5449685dfb85eb11c9828acc7cb87ab5bbfcc0" + integrity sha1-zFRJaF37hesRyYKKzHy4erW7/MA= + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -1929,6 +2004,11 @@ dot-prop@^3.0.0: dependencies: is-obj "^1.0.0" +dotenv@8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" + integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== + dotgitignore@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/dotgitignore/-/dotgitignore-2.1.0.tgz#a4b15a4e4ef3cf383598aaf1dfa4a04bcc089b7b" @@ -2027,6 +2107,13 @@ eslint-config-airbnb-base@14.1.0: object.assign "^4.1.0" object.entries "^1.1.1" +eslint-config-prettier@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz#f6d2238c1290d01c859a8b5c1f7d352a0b0da8b1" + integrity sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA== + dependencies: + get-stdin "^6.0.0" + eslint-import-resolver-node@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" @@ -2162,6 +2249,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= +events@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= + execa@1.0.0, execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -2241,6 +2333,13 @@ fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fd-slicer@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" + integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= + dependencies: + pend "~1.2.0" + figures@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" @@ -2321,6 +2420,11 @@ find-versions@^3.2.0: dependencies: semver-regex "^2.0.0" +findit2@~2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/findit2/-/findit2-2.2.3.tgz#58a466697df8a6205cdfdbf395536b8bd777a5f6" + integrity sha1-WKRmaX34piBc39vzlVNri9d3pfY= + flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -2432,6 +2536,11 @@ get-stdin@^4.0.1: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -2558,7 +2667,7 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@~4.1.4: version "4.1.15" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== @@ -2660,6 +2769,11 @@ iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +ieee754@1.1.13, ieee754@^1.1.4: + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -3044,6 +3158,11 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= +jmespath@0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" + integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc= + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -3251,7 +3370,7 @@ lodash@4.17.15: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -lodash@4.17.19, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: +lodash@4.17.19, lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: version "4.17.19" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== @@ -3387,6 +3506,11 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +mime@~2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369" + integrity sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg== + mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" @@ -3397,7 +3521,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -3447,6 +3571,13 @@ mkdirp@^0.5.1: dependencies: minimist "0.0.8" +mkdirp@~0.5.0: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" @@ -3887,6 +4018,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + pidtree@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b" @@ -3980,6 +4116,11 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -3990,6 +4131,11 @@ q@^1.5.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + quick-lru@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" @@ -4077,6 +4223,13 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +recursive-readdir@2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" + integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== + dependencies: + minimatch "3.0.4" + redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" @@ -4271,6 +4424,11 @@ rimraf@2.6.3, rimraf@^2.5.2, rimraf@^2.6.3: dependencies: glob "^7.1.3" +rimraf@~2.2.8: + version "2.2.8" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" + integrity sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI= + run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" @@ -4299,6 +4457,21 @@ rxjs@^6.5.3: dependencies: tslib "^1.9.0" +s3-node-client@4.4.4: + version "4.4.4" + resolved "https://registry.yarnpkg.com/s3-node-client/-/s3-node-client-4.4.4.tgz#705f1cea2a7d2330773352c649008475fb767b6c" + integrity sha1-cF8c6ip9IzB3M1LGSQCEdft2e2w= + dependencies: + aws-sdk "2.67.0" + fd-slicer "~1.0.0" + findit2 "~2.2.3" + graceful-fs "~4.1.4" + mime "~2.3.1" + mkdirp "~0.5.0" + pend "~1.2.0" + rimraf "~2.2.8" + streamsink "~1.2.0" + safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -4321,6 +4494,16 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sax@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" + integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= + +sax@>=0.6.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -4559,6 +4742,11 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" +streamsink@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/streamsink/-/streamsink-1.2.0.tgz#efafee9f1e22d3591ed7de3dcaa95c3f5e79f73c" + integrity sha1-76/unx4i01ke1949yqlcP1559zw= + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -4911,6 +5099,14 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= +url@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" + integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -4921,6 +5117,16 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +uuid@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" + integrity sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE= + +uuid@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + v8-compile-cache@^2.0.3: version "2.1.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" @@ -4990,6 +5196,34 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" +xml2js@0.4.17: + version "0.4.17" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.17.tgz#17be93eaae3f3b779359c795b419705a8817e868" + integrity sha1-F76T6q4/O3eTWceVtBlwWogX6Gg= + dependencies: + sax ">=0.6.0" + xmlbuilder "^4.1.0" + +xml2js@0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" + integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== + dependencies: + sax ">=0.6.0" + xmlbuilder "~9.0.1" + +xmlbuilder@4.2.1, xmlbuilder@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-4.2.1.tgz#aa58a3041a066f90eaa16c2f5389ff19f3f461a5" + integrity sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU= + dependencies: + lodash "^4.0.0" + +xmlbuilder@~9.0.1: + version "9.0.7" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" + integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= + xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"