diff --git a/.gitignore b/.gitignore index 4c49bd7..fec2f30 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ +index.js .env diff --git a/Capfile b/Capfile deleted file mode 100644 index 05237b9..0000000 --- a/Capfile +++ /dev/null @@ -1,23 +0,0 @@ -require 'recap/recipes/ruby' - -set :application, 'trello_backup' -set :repository, 'https://github.com/freerange/trello_backup' - -server 'badger.gofreerange.com', :app - - -set :whenever_command, 'bundle exec whenever' -set(:whenever_identifier) { application } -set(:whenever_update_flags) { "--update-crontab #{whenever_identifier} -u #{application_user}" } -set(:whenever_clear_flags) { "--clear-crontab #{whenever_identifier} -u #{application_user}" } - -after "deploy:tag", "whenever:update_crontab" -after "deploy:rollback", "whenever:update_crontab" - -namespace :whenever do - desc "Update application's crontab entries using Whenever" - task :update_crontab, :roles => :app do - as_app "#{whenever_command} #{whenever_clear_flags}" - as_app "#{whenever_command} #{whenever_update_flags}" - end -end diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 445bfdd..0000000 --- a/Gemfile +++ /dev/null @@ -1,14 +0,0 @@ -source "https://rubygems.org" - -ruby '2.2.10' - -gem "dotenv" -gem "addressable" -gem "rest-client" -gem "dropbox-sdk-v2" -gem "whenever" -gem "recap" -gem "ruby-trello" - -gem "activesupport" -gem "mime-types" diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 098ae97..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,97 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - activemodel (5.2.1) - activesupport (= 5.2.1) - activesupport (5.2.1) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - addressable (2.5.2) - public_suffix (>= 2.0.2, < 4.0) - capistrano (2.15.5) - highline - net-scp (>= 1.0.0) - net-sftp (>= 2.0.0) - net-ssh (>= 2.0.14) - net-ssh-gateway (>= 1.1.0) - chronic (0.10.2) - concurrent-ruby (1.0.5) - domain_name (0.5.20170404) - unf (>= 0.0.5, < 1.0.0) - dotenv (0.11.1) - dotenv-deployment (~> 0.0.2) - dotenv-deployment (0.0.2) - dropbox-sdk-v2 (0.0.3) - http (~> 2.0) - highline (1.6.21) - http (2.2.2) - addressable (~> 2.3) - http-cookie (~> 1.0) - http-form_data (~> 1.0.1) - http_parser.rb (~> 0.6.0) - http-cookie (1.0.3) - domain_name (~> 0.5) - http-form_data (1.0.3) - http_parser.rb (0.6.0) - i18n (1.1.1) - concurrent-ruby (~> 1.0) - json (2.1.0) - mime-types (2.99.3) - minitest (5.11.3) - net-scp (1.2.1) - net-ssh (>= 2.6.5) - net-sftp (2.1.2) - net-ssh (>= 2.6.5) - net-ssh (2.9.1) - net-ssh-gateway (1.2.0) - net-ssh (>= 2.6.5) - netrc (0.11.0) - oauth (0.5.4) - open4 (1.3.4) - public_suffix (3.0.3) - recap (1.2.2) - capistrano (~> 2.9) - open4 - thor - rest-client (1.8.0) - http-cookie (>= 1.0.2, < 2.0) - mime-types (>= 1.16, < 3.0) - netrc (~> 0.7) - ruby-trello (1.5.1) - activemodel (>= 3.2.0) - addressable (~> 2.3) - json - oauth (>= 0.4.5) - rest-client (~> 1.8.0) - thor (0.19.1) - thread_safe (0.3.6) - tzinfo (1.2.5) - thread_safe (~> 0.1) - unf (0.1.4) - unf_ext - unf_ext (0.0.7.4) - whenever (0.9.2) - activesupport (>= 2.3.4) - chronic (>= 0.6.3) - -PLATFORMS - ruby - -DEPENDENCIES - activesupport - addressable - dotenv - dropbox-sdk-v2 - mime-types - recap - rest-client - ruby-trello - whenever - -RUBY VERSION - ruby 2.2.10p489 - -BUNDLED WITH - 1.16.6 diff --git a/README.md b/README.md index 533d3c5..3d27561 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,25 @@ -We use this script to regularly backup all our GFR Trello boards to Dropbox. +## Requirements -## Generating/storing the tokens you need to use this script +* node +* npm -### Getting the Trello API key +## Setup + +### Install node packages + + npm ci + +### Configure AWS + +* You need to specify the AWS credentials and default region to use when running +the `cdk` command-line tool in the same way you would configure the `aws` +command-line tool. See [Configuring the AWS CDK Toolkit][1] for details. + +* I recommend using `aws configure` and/or `~/.aws/credentials` & `~/.aws/config` +to setup a named profile and then use the `--profile ` option +with the `cdk` command-line tool to select the relevant AWS profile. + +### Getting a Trello API key Ensure you're logged in as the GFR Admin user. @@ -13,11 +30,12 @@ Ensure you're logged in as the GFR Admin user. $ export TRELLO_KEY=`pbpaste` # Store the Trello API key in .env - $ echo "TRELLO_KEY=$TRELLO_KEY" >> .env + $ echo "TRELLO_KEY=$TRELLO_KEY" >> lambdaFunctions/enumerateTrelloBoards/.env + $ echo "TRELLO_KEY=$TRELLO_KEY" >> lambdaFunctions/backupTrelloBoard/.env -### Getting a token to allow this app to read our Trello board +### Getting a Trello API token -Ensure you're logged in as the GFR Admin user. It's safe to run do this step multiple times as you'll get the same token back even if it's already been generated. +Ensure you're logged in as the GFR Admin user on https://trello.com. It's safe to run do this step multiple times as you'll get the same token back even if it's already been generated. $ open "https://trello.com/1/connect?key=$TRELLO_KEY&name=gfr-trello-backup&expiration=never&response_type=token" # Allow the gfr-trello-backup app to read our Trello account @@ -29,54 +47,41 @@ Ensure you're logged in as the GFR Admin user. It's safe to run do this step mul # Store the Trello token in .env $ echo "TRELLO_TOKEN=$TRELLO_TOKEN" >> .env + $ echo "TRELLO_TOKEN=$TRELLO_TOKEN" >> .env -### Getting a token to allow this app to write to Dropbox - -Ensure you're logged in as the GFR Admin user. - - $ open "https://www.dropbox.com/developers/apps" - - # Navigate to "Trello Backup" - # Click the "Generate" button in OAuth 2 > Generated access token - # Copy the generated access token - - # Temporarily store the access token in an environment variable - $ export DROPBOX_ACCESS_TOKEN=`pbpaste` - - # Store the Dropbox token in .env - $ echo "DROPBOX_ACCESS_TOKEN=$DROPBOX_ACCESS_TOKEN" >> .env - -## Testing the script locally - -Assuming you've followed the instructions above and got all the tokens stored in .env, this should be as simple as running `ruby backup.rb`. If it's worked successfully then you'll see a backup for today in https://www.dropbox.com/home/Apps/Trello%20Backup. +### Environment variables -## Deployment +In the top-level `.env` file, set the following environment variables: -### Deploying with recap +* `TRELLO_BACKUP_SCHEDULE_FOR_BACKUP` - specifies how often the backup is performed, e.g. `cron(0 2 * * ? *)` runs daily at 2am (see [Schedule Expressions for Rules][3] for details) +* `TRELLO_BACKUP_SCHEDULE_FOR_CHECK` - specifies how often the post-backup check is performed, e.g. `cron(30 2 * * ? *)` runs daily at 2.30am +* `TRELLO_BACKUP_OLDEST_ALLOWED_BACKUP_IN_SECONDS` - how old a backup is allowed to be when the post-backup check is performed, e.g. `1800` only allows backups to be 30 minutes old; older backups trigger an error +* `TRELLO_BACKUP_S3_BUCKET_NAME` - the name of the S3 bucket you want to be created and used to save backups +* `TRELLO_BACKUP_MONITORING_EMAIL_ADDRESS` - the email address where monitoring emails will be sent (an email will be sent on first deployment to ask you to confirm the subscription) - $ cap bootstrap - $ cap deploy:setup - $ cap deploy +Note: this `.env` file is copied into some/all of the `lambdaFunctions` folders at build time. -### Set the application user's shell to bash +## Build - root$ chsh -s /bin/bash trello_backup + npm run build -### Set the Trello and Dropbox environment variables +## Execute CDK commands -I'm going to assume you've already got these environment variables configured in your local .env. + cdk --profile - $ cap env:set TRELLO_KEY=`grep TRELLO_KEY .env | cut -d"=" -f2` - $ cap env:set TRELLO_TOKEN=`grep TRELLO_TOKEN .env | cut -d"=" -f2` - $ cap env:set DROPBOX_ACCESS_TOKEN=`grep DROPBOX_ACCESS_TOKEN .env | cut -d"=" -f2` +* See [Command-line Toolkit][2] for a list of commands and options to use with +the `cdk` command-line tool. -## Test the script by running it manually +* The `cdk.json` file defines an appropriate value for the `--app` option, so +there is no need to specify this unless you want to override that value. - # Print the command that's being run under cron - trello_backup$ crontab -l | grep -o "/bin/bash.*backup.rb.*" +* `node_modules/.bin` must be in your `PATH` environment variable in order to +be able to run the `cdk` command-line tool. - # Copy and paste the printed command to execute the backup script manually - # If everything has worked then you should see a new backup file in - # https://www.dropbox.com/home/Apps/Trello%20Backup when you're logged - # in as GFR's dropbox user. +* When a stack uses assets (e.g. via a call to `aws-lambda.Code.asset()`), +before using the `cdk` command-line tool to deploy to an AWS environment for +the first time, the environment must be bootstrapped using: `cdk bootstrap`. +[1]: https://awslabs.github.io/aws-cdk/getting-started.html#configuring-the-cdk-toolkit +[2]: https://awslabs.github.io/aws-cdk/tools.html#command-line-toolkit-cdk +[3]: https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html diff --git a/backup.rb b/backup.rb deleted file mode 100755 index 4ee0f65..0000000 --- a/backup.rb +++ /dev/null @@ -1,56 +0,0 @@ -require 'logger' -logger = Logger.new(STDOUT) -logger.formatter = Logger::Formatter.new - -STDOUT.sync = true - -logger.info 'Loading environment...' - -require 'rubygems' -require 'bundler/setup' - -require 'dotenv' -require 'addressable/uri' -require 'restclient' -require 'dropbox' -require 'date' -require 'trello' - -Dotenv.load - -logger.info 'OK' - -Trello.configure do |config| - config.developer_public_key = ENV.fetch('TRELLO_KEY') - config.member_token = ENV.fetch('TRELLO_TOKEN') -end - -boards = Trello::Board.all.reject { |b| b.name[/Welcome Board/] } -boards.each do |board| - endpoint = "https://api.trello.com/1/boards/#{board.id}" - uri = Addressable::URI.parse(endpoint) - uri.query_values = { - :actions => :all, - :actions_limit => 1000, - :cards => :all, - :lists => :all, - :members => :all, - :member_fields => :all, - :checklists => :all, - :fields => :all, - :card_attachments => true, - :key => ENV.fetch('TRELLO_KEY'), - :token => ENV.fetch('TRELLO_TOKEN') - } - - logger.info "#{board.id} - Fetching Trello data for #{board.name} board..." - response = RestClient.get(uri.to_s) - json = response.body - logger.info "#{board.id} - OK" - - logger.info "#{board.id} - Writing data to Dropbox..." - client = Dropbox::Client.new(ENV['DROPBOX_ACCESS_TOKEN']) - filename = "/#{Date.today}-#{board.name.downcase.gsub(/[^\w]/, '-').squeeze('-')}-trello.json" - client.upload(filename, json) - logger.info "#{board.id} - OK" -end diff --git a/cdk.json b/cdk.json new file mode 100644 index 0000000..443ab0e --- /dev/null +++ b/cdk.json @@ -0,0 +1,3 @@ +{ + "app": "node index.js" +} diff --git a/config/schedule.rb b/config/schedule.rb deleted file mode 100644 index e7f0385..0000000 --- a/config/schedule.rb +++ /dev/null @@ -1,6 +0,0 @@ -env :PATH, '/usr/local/bin:/usr/bin:/bin' -env :MAILTO, 'everyone@gofreerange.com' - -every :day, :at => '2am' do - command 'cd ~/app && ruby backup.rb >> trello_backup.log 2>&1 || echo "Trello Backup: error occurred. See trello_backup.log for details."' -end diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..baab4c3 --- /dev/null +++ b/index.ts @@ -0,0 +1,113 @@ +import cdk = require('@aws-cdk/cdk'); +import lambda = require('@aws-cdk/aws-lambda'); +import events = require('@aws-cdk/aws-events'); +import s3 = require('@aws-cdk/aws-s3'); +import { Topic } from '@aws-cdk/aws-sns'; +import dotenv = require('dotenv'); + +dotenv.config(); + +const rubyLambdaRuntime = new lambda.Runtime('ruby2.5'); +const lambdaFunctionTimeout = 30; + +class TrelloBackupStack extends cdk.Stack { + constructor(parent: cdk.App, id: string, props?: cdk.StackProps) { + super(parent, id, props); + + const monitoringTopic = new Topic(this, 'monitoringTopic'); + const backupBoardTopic = new Topic(this, 'backupBoardTopic'); + + const enumerateBoardsFunction + = this.createEnumerateBoardsFunction(backupBoardTopic, monitoringTopic); + + const bucketName = process.env.TRELLO_BACKUP_S3_BUCKET_NAME; + const boardBackupsBucket + = this.createBoardBackupsBucket(bucketName); + + const backupBoardFunction + = this.createBackupBoardFunction(boardBackupsBucket, monitoringTopic); + + backupBoardTopic.subscribeLambda(backupBoardFunction); + + const checkBoardBackupsFunction + = this.createCheckBoardBackupsFunction(boardBackupsBucket, monitoringTopic); + + const monitoringEmailAddress = process.env.TRELLO_BACKUP_MONITORING_EMAIL_ADDRESS; + monitoringTopic.subscribeEmail('monitoringTopicEmail', monitoringEmailAddress); + + const scheduleForBackup = process.env.TRELLO_BACKUP_SCHEDULE_FOR_BACKUP; + const ruleForBackup = new events.EventRule(this, 'RuleForBackup', { + scheduleExpression: scheduleForBackup, + }); + ruleForBackup.addTarget(enumerateBoardsFunction); + + const scheduleForCheck = process.env.TRELLO_BACKUP_SCHEDULE_FOR_CHECK; + const ruleForCheck = new events.EventRule(this, 'RuleForCheck', { + scheduleExpression: scheduleForCheck, + }); + ruleForCheck.addTarget(checkBoardBackupsFunction); + } + + createEnumerateBoardsFunction(backupBoardTopic : Topic, monitoringTopic : Topic) : lambda.Function { + const lambdaFunction = new lambda.Function(this, 'enumerateBoards', { + runtime: rubyLambdaRuntime, + handler: 'index.handler', + code: lambda.Code.asset('./lambdaFunctions/enumerateBoards'), + environment: { + TRELLO_BACKUP_BACKUP_BOARD_TOPIC_ARN: backupBoardTopic.topicArn + }, + timeout: lambdaFunctionTimeout + }); + backupBoardTopic.grantPublish(lambdaFunction.role); + this.reportErrors(lambdaFunction, monitoringTopic); + return lambdaFunction; + } + + createBoardBackupsBucket(bucketName : string) : s3.Bucket { + return new s3.Bucket(this, 'boardBackupsBucket', { + bucketName: bucketName, + versioned: true + }); + } + + createBackupBoardFunction(boardBackupsBucket : s3.Bucket, monitoringTopic : Topic) : lambda.Function { + const lambdaFunction = new lambda.Function(this, 'backupBoard', { + runtime: rubyLambdaRuntime, + handler: 'index.handler', + code: lambda.Code.asset('./lambdaFunctions/backupBoard'), + timeout: lambdaFunctionTimeout + }); + boardBackupsBucket.grantPut(lambdaFunction.role); + this.reportErrors(lambdaFunction, monitoringTopic); + return lambdaFunction; + } + + createCheckBoardBackupsFunction(boardBackupsBucket : s3.Bucket, monitoringTopic : Topic) : lambda.Function { + const lambdaFunction = new lambda.Function(this, 'checkBoardBackups', { + runtime: rubyLambdaRuntime, + handler: 'index.handler', + code: lambda.Code.asset('./lambdaFunctions/checkBoardBackups'), + environment: { + TRELLO_BACKUP_MONITORING_TOPIC_ARN: monitoringTopic.topicArn + }, + timeout: lambdaFunctionTimeout + }); + boardBackupsBucket.grantRead(lambdaFunction.role); + monitoringTopic.grantPublish(lambdaFunction.role); + this.reportErrors(lambdaFunction, monitoringTopic); + return lambdaFunction; + } + + reportErrors(lambdaFunction : lambda.Function, monitoringTopic : Topic) : void { + const metricErrors = lambdaFunction.metricErrors(); + const alarm = metricErrors.newAlarm(this, `${lambdaFunction.id}Alarm`, { + threshold: 1, + evaluationPeriods: 1 + }); + alarm.onAlarm(monitoringTopic); + } +} + +const app = new cdk.App(); +new TrelloBackupStack(app, 'TrelloBackup'); +app.run(); diff --git a/lambdaFunctions/backupBoard/.gitignore b/lambdaFunctions/backupBoard/.gitignore new file mode 100644 index 0000000..226ca36 --- /dev/null +++ b/lambdaFunctions/backupBoard/.gitignore @@ -0,0 +1,2 @@ +.env +vendor diff --git a/lambdaFunctions/backupBoard/Gemfile b/lambdaFunctions/backupBoard/Gemfile new file mode 100644 index 0000000..8716109 --- /dev/null +++ b/lambdaFunctions/backupBoard/Gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +ruby '~> 2.5.0' + +gem 'aws-sdk-s3' +gem 'dotenv' diff --git a/lambdaFunctions/backupBoard/Gemfile.lock b/lambdaFunctions/backupBoard/Gemfile.lock new file mode 100644 index 0000000..f3df378 --- /dev/null +++ b/lambdaFunctions/backupBoard/Gemfile.lock @@ -0,0 +1,33 @@ +GEM + remote: https://rubygems.org/ + specs: + aws-eventstream (1.0.1) + aws-partitions (1.125.0) + aws-sdk-core (3.44.0) + aws-eventstream (~> 1.0) + aws-partitions (~> 1.0) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-kms (1.13.0) + aws-sdk-core (~> 3, >= 3.39.0) + aws-sigv4 (~> 1.0) + aws-sdk-s3 (1.30.0) + aws-sdk-core (~> 3, >= 3.39.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.0) + aws-sigv4 (1.0.3) + dotenv (2.5.0) + jmespath (1.4.0) + +PLATFORMS + ruby + +DEPENDENCIES + aws-sdk-s3 + dotenv + +RUBY VERSION + ruby 2.5.3p105 + +BUNDLED WITH + 1.17.1 diff --git a/lambdaFunctions/backupBoard/build.sh b/lambdaFunctions/backupBoard/build.sh new file mode 100755 index 0000000..9c37336 --- /dev/null +++ b/lambdaFunctions/backupBoard/build.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -e +cp ../../.env . +rm -rf vendor/bundle +bundle install --path vendor/bundle diff --git a/lambdaFunctions/backupBoard/index.rb b/lambdaFunctions/backupBoard/index.rb new file mode 100644 index 0000000..62a8d75 --- /dev/null +++ b/lambdaFunctions/backupBoard/index.rb @@ -0,0 +1,48 @@ +require 'aws-sdk-s3' +require 'dotenv' + +Dotenv.load + +S3_BUCKET_NAME = ENV.fetch('TRELLO_BACKUP_S3_BUCKET_NAME') + +def handler(event:, context:) + records = event.fetch('Records', []) + sns_events = records.select { |r| r['EventSource'] == 'aws:sns' } + sns_events.each do |sns_event| + attributes = sns_event.dig('Sns', 'MessageAttributes') + board_id = attributes.dig('board_id', 'Value') + board_name = attributes.dig('board_name', 'Value') + + endpoint = "https://api.trello.com/1/boards/#{board_id}" + uri = URI(endpoint) + uri.query = URI.encode_www_form({ + :key => ENV.fetch('TRELLO_KEY'), + :token => ENV.fetch('TRELLO_TOKEN'), + :actions => :all, + :actions_limit => 1000, + :cards => :all, + :card_attachments => true, + :checklists => :all, + :fields => :all, + :labels => :all, + :lists => :all, + :members => :all, + :member_fields => :all + }) + + puts "#{board_id} - Fetching Trello data for #{board_name} board..." + response = Net::HTTP.get_response(uri) + unless response.is_a?(Net::HTTPSuccess) + raise "Trello API error: #{response.message} #{response.code}" + end + json = response.body + puts "#{board_id} - OK" + + puts "#{board_id} - Writing data for #{board_name} board to S3..." + object = Aws::S3::Object.new(S3_BUCKET_NAME, "#{board_id}.json") + object.upload_stream(content_type: 'application/json') { |stream| stream << json } + puts "#{board_id} - OK" + end + + { statusCode: 200, body: 'OK' } +end diff --git a/lambdaFunctions/build.sh b/lambdaFunctions/build.sh new file mode 100755 index 0000000..58e0d21 --- /dev/null +++ b/lambdaFunctions/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +find * -type d -maxdepth 0 -exec sh -c "cd {} && ./build.sh" \; diff --git a/lambdaFunctions/checkBoardBackups/.gitignore b/lambdaFunctions/checkBoardBackups/.gitignore new file mode 100644 index 0000000..226ca36 --- /dev/null +++ b/lambdaFunctions/checkBoardBackups/.gitignore @@ -0,0 +1,2 @@ +.env +vendor diff --git a/lambdaFunctions/checkBoardBackups/Gemfile b/lambdaFunctions/checkBoardBackups/Gemfile new file mode 100644 index 0000000..24c9cce --- /dev/null +++ b/lambdaFunctions/checkBoardBackups/Gemfile @@ -0,0 +1,7 @@ +source 'https://rubygems.org' + +ruby '~> 2.5.0' + +gem 'aws-sdk-s3' +gem 'aws-sdk-sns' +gem 'dotenv' diff --git a/lambdaFunctions/checkBoardBackups/Gemfile.lock b/lambdaFunctions/checkBoardBackups/Gemfile.lock new file mode 100644 index 0000000..c789184 --- /dev/null +++ b/lambdaFunctions/checkBoardBackups/Gemfile.lock @@ -0,0 +1,37 @@ +GEM + remote: https://rubygems.org/ + specs: + aws-eventstream (1.0.1) + aws-partitions (1.127.0) + aws-sdk-core (3.44.1) + aws-eventstream (~> 1.0) + aws-partitions (~> 1.0) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-kms (1.13.0) + aws-sdk-core (~> 3, >= 3.39.0) + aws-sigv4 (~> 1.0) + aws-sdk-s3 (1.30.0) + aws-sdk-core (~> 3, >= 3.39.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.0) + aws-sdk-sns (1.9.0) + aws-sdk-core (~> 3, >= 3.39.0) + aws-sigv4 (~> 1.0) + aws-sigv4 (1.0.3) + dotenv (2.5.0) + jmespath (1.4.0) + +PLATFORMS + ruby + +DEPENDENCIES + aws-sdk-s3 + aws-sdk-sns + dotenv + +RUBY VERSION + ruby 2.5.3p105 + +BUNDLED WITH + 1.17.1 diff --git a/lambdaFunctions/checkBoardBackups/build.sh b/lambdaFunctions/checkBoardBackups/build.sh new file mode 100755 index 0000000..9c37336 --- /dev/null +++ b/lambdaFunctions/checkBoardBackups/build.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -e +cp ../../.env . +rm -rf vendor/bundle +bundle install --path vendor/bundle diff --git a/lambdaFunctions/checkBoardBackups/index.rb b/lambdaFunctions/checkBoardBackups/index.rb new file mode 100644 index 0000000..51a930f --- /dev/null +++ b/lambdaFunctions/checkBoardBackups/index.rb @@ -0,0 +1,62 @@ +require 'aws-sdk-s3' +require 'aws-sdk-sns' +require 'csv' +require 'dotenv' + +Dotenv.load + +TOPIC_ARN = ENV.fetch('TRELLO_BACKUP_MONITORING_TOPIC_ARN') +S3_BUCKET_NAME = ENV.fetch('TRELLO_BACKUP_S3_BUCKET_NAME') +OLDEST_ALLOWED_BACKUP_IN_SECONDS = Integer(ENV.fetch('TRELLO_BACKUP_OLDEST_ALLOWED_BACKUP_IN_SECONDS')) + +def handler(event:, context:) + endpoint = "https://api.trello.com/1/members/me/boards" + uri = URI(endpoint) + uri.query = URI.encode_www_form({ + :key => ENV.fetch('TRELLO_KEY'), + :token => ENV.fetch('TRELLO_TOKEN'), + :fields => 'id,name' + }) + response = Net::HTTP.get_response(uri) + unless response.is_a?(Net::HTTPSuccess) + raise "Trello API error: #{response.message} #{response.code}" + end + boards = JSON.parse(response.body) + + earliest_allowed_backup_time = Time.now - OLDEST_ALLOWED_BACKUP_IN_SECONDS + boards_with_status = boards.map do |board| + board_id = board['id'] + object_key = "#{board_id}.json" + result = { id: board_id, name: board['name'] } + begin + object = Aws::S3::Object.new(S3_BUCKET_NAME, object_key) + result[:message] = "Last backed up: #{object.data.last_modified}" + if object.data.last_modified >= earliest_allowed_backup_time + result.merge(success: true) + else + result.merge(success: false) + end + rescue Aws::S3::Errors::NotFound => e + result.merge(success: false, message: e.inspect) + end + end + + success = boards_with_status.all? { |b| b[:success] } + subject = "Trello Backup: #{success ? 'Success' : 'Failure'}" + message = '' + CSV(message, col_sep: "\t") do |csv| + csv << %w[id name success message] + boards_with_status.each do |board| + csv << [board[:id], board[:name], board[:success], board[:message]] + end + end + + sns = Aws::SNS::Client.new + sns.publish( + topic_arn: TOPIC_ARN, + subject: subject, + message: message, + ) + + { statusCode: 200, body: 'OK' } +end diff --git a/lambdaFunctions/enumerateBoards/.gitignore b/lambdaFunctions/enumerateBoards/.gitignore new file mode 100644 index 0000000..226ca36 --- /dev/null +++ b/lambdaFunctions/enumerateBoards/.gitignore @@ -0,0 +1,2 @@ +.env +vendor diff --git a/lambdaFunctions/enumerateBoards/Gemfile b/lambdaFunctions/enumerateBoards/Gemfile new file mode 100644 index 0000000..6918dec --- /dev/null +++ b/lambdaFunctions/enumerateBoards/Gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +ruby '~> 2.5.0' + +gem 'aws-sdk-sns' +gem 'dotenv' diff --git a/lambdaFunctions/enumerateBoards/Gemfile.lock b/lambdaFunctions/enumerateBoards/Gemfile.lock new file mode 100644 index 0000000..01b272f --- /dev/null +++ b/lambdaFunctions/enumerateBoards/Gemfile.lock @@ -0,0 +1,29 @@ +GEM + remote: https://rubygems.org/ + specs: + aws-eventstream (1.0.1) + aws-partitions (1.125.0) + aws-sdk-core (3.44.0) + aws-eventstream (~> 1.0) + aws-partitions (~> 1.0) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-sns (1.9.0) + aws-sdk-core (~> 3, >= 3.39.0) + aws-sigv4 (~> 1.0) + aws-sigv4 (1.0.3) + dotenv (2.5.0) + jmespath (1.4.0) + +PLATFORMS + ruby + +DEPENDENCIES + aws-sdk-sns + dotenv + +RUBY VERSION + ruby 2.5.3p105 + +BUNDLED WITH + 1.17.1 diff --git a/lambdaFunctions/enumerateBoards/build.sh b/lambdaFunctions/enumerateBoards/build.sh new file mode 100755 index 0000000..9c37336 --- /dev/null +++ b/lambdaFunctions/enumerateBoards/build.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -e +cp ../../.env . +rm -rf vendor/bundle +bundle install --path vendor/bundle diff --git a/lambdaFunctions/enumerateBoards/index.rb b/lambdaFunctions/enumerateBoards/index.rb new file mode 100644 index 0000000..8010711 --- /dev/null +++ b/lambdaFunctions/enumerateBoards/index.rb @@ -0,0 +1,44 @@ +require 'aws-sdk-sns' +require 'dotenv' + +Dotenv.load + +TOPIC_ARN = ENV.fetch('TRELLO_BACKUP_BACKUP_BOARD_TOPIC_ARN') + +def handler(event:, context:) + sns = Aws::SNS::Client.new + + endpoint = "https://api.trello.com/1/members/me/boards" + uri = URI(endpoint) + uri.query = URI.encode_www_form({ + :key => ENV.fetch('TRELLO_KEY'), + :token => ENV.fetch('TRELLO_TOKEN'), + :fields => 'id,name' + }) + response = Net::HTTP.get_response(uri) + unless response.is_a?(Net::HTTPSuccess) + raise "Trello API error: #{response.message} #{response.code}" + end + boards = JSON.parse(response.body) + + boards.each do |board| + board_id = board['id'] + board_name = board['name'] + sns.publish( + topic_arn: TOPIC_ARN, + subject: "Backup Trello board", + message: "Backup Trello board: #{board_name}", + message_attributes: { + 'board_id' => { + data_type: 'String', + string_value: board_id + }, + 'board_name' => { + data_type: 'String', + string_value: board_name + } + } + ) + end + { statusCode: 200, body: 'OK' } +end diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..0fec457 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2187 @@ +{ + "name": "trello_backup", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@aws-cdk/applet-js": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/applet-js/-/applet-js-0.20.0.tgz", + "integrity": "sha512-zOfBnyjf9uJm46VVz0CLuq+sC+UkibWFmi9Ow5qlfBJZ6fizNYvM/bwC7zhPlMYCVvNdulZBLXJ3DK85h6E3XA==", + "requires": { + "@aws-cdk/cdk": "^0.20.0", + "fs-extra": "^7.0.0", + "source-map-support": "^0.5.6", + "yaml": "^1.1.0" + } + }, + "@aws-cdk/assets": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/assets/-/assets-0.20.0.tgz", + "integrity": "sha512-6M2XjU0gddZchFP9WkwGOM21usK82M1PUC/3ev/mlTh8xM83FjYGZeHTS1asdhC3EG1dhflNZ+AmJq/M7JpGxQ==", + "requires": { + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/aws-s3": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0", + "@aws-cdk/cx-api": "^0.20.0" + } + }, + "@aws-cdk/aws-autoscaling-api": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-autoscaling-api/-/aws-autoscaling-api-0.20.0.tgz", + "integrity": "sha512-zQEP/Y8byrJ9QJdraESsD+ei25bDr1zEv6Fiz/7ess1wG3XfZPNRzNeFBfNF3ynqH0ktp6ZJSLnzmbgVeD2yNA==", + "requires": { + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/aws-cloudwatch": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-cloudwatch/-/aws-cloudwatch-0.20.0.tgz", + "integrity": "sha512-ChOEJS5J5xs2B669UpNhytSYK+TC6rW15j+4Ne/D95no7PFSmwdSCifNu+kQKtT2hmHCWSSdZxQQl828HQXPYQ==", + "requires": { + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/aws-codepipeline-api": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-codepipeline-api/-/aws-codepipeline-api-0.20.0.tgz", + "integrity": "sha512-w9AkV51/Bx1FyINCBEsAu5OEkc5HTybgxvSzzPgBH/xcuOgazCtTAY+n+2huBc4wO6jM3MshAQccCcuWOxSb8Q==", + "requires": { + "@aws-cdk/aws-events": "^0.20.0", + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/aws-ec2": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-ec2/-/aws-ec2-0.20.0.tgz", + "integrity": "sha512-V1Ez1S1eMAzHuiULXQk49P7lCyrS6UD5DzRVb6mBAkX1Kv65MyLpeiHNhmRd5aa/x9cK0LhXNZPrzDZ4ShSm4A==", + "requires": { + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0", + "@aws-cdk/cx-api": "^0.20.0" + } + }, + "@aws-cdk/aws-events": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-events/-/aws-events-0.20.0.tgz", + "integrity": "sha512-4LyROSw+mBZrrtJGjUvDP91M0Hq18VDUppxRbwjTdESGhHMogSQfB6j0xsctswxR1Hv4jF1H6ZlhxQlrQlXucg==", + "requires": { + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/aws-iam": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-iam/-/aws-iam-0.20.0.tgz", + "integrity": "sha512-fl6n5zAN5S/stry6+ij8Ziu60J/C6oUA9DWrsYRAUzNpZNIr2Cgo8tv0SrgAV/t7635ged5YtSzlHj1Gdc1bjw==", + "requires": { + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/aws-kms": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-kms/-/aws-kms-0.20.0.tgz", + "integrity": "sha512-cLRakK/CK14+1Hhhll75qra70nKJNzTCPZ9+/ZJY8Xc9zO3fDJWejF7+ZapwjN6kI8QGkAwOx+cK9dJ5KnvPzw==", + "requires": { + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/aws-lambda": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-lambda/-/aws-lambda-0.20.0.tgz", + "integrity": "sha512-tlRBkqZBzR+C6VxJDhM41S6Qf6y0SSQ7PlNyH58Cqze0IPVBYO1loKh/e2KCyQRofR1YlAPRkNqev17qkx6dXA==", + "requires": { + "@aws-cdk/assets": "^0.20.0", + "@aws-cdk/aws-cloudwatch": "^0.20.0", + "@aws-cdk/aws-codepipeline-api": "^0.20.0", + "@aws-cdk/aws-ec2": "^0.20.0", + "@aws-cdk/aws-events": "^0.20.0", + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/aws-logs": "^0.20.0", + "@aws-cdk/aws-s3": "^0.20.0", + "@aws-cdk/aws-s3-notifications": "^0.20.0", + "@aws-cdk/aws-sqs": "^0.20.0", + "@aws-cdk/aws-stepfunctions": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0", + "@aws-cdk/cx-api": "^0.20.0" + } + }, + "@aws-cdk/aws-logs": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-logs/-/aws-logs-0.20.0.tgz", + "integrity": "sha512-WONAOMZ2sBsAvSEZ0YYhAbz6GSWmAJi1Goo/0wyDArONORAELeRzXRqyXCQk+zlqMsnETpOaCopgsOG2aDYHXA==", + "requires": { + "@aws-cdk/aws-cloudwatch": "^0.20.0", + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/aws-s3": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-s3/-/aws-s3-0.20.0.tgz", + "integrity": "sha512-JFjcimPa20fpm8XPvhbSrsSFnEUNFqMDzUWhjOAWckkS6KQ08BVJJiY/06Nz/w8gG8y2IvtWsQpLZUPN+W7sZA==", + "requires": { + "@aws-cdk/aws-codepipeline-api": "^0.20.0", + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/aws-kms": "^0.20.0", + "@aws-cdk/aws-s3-notifications": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/aws-s3-notifications": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-s3-notifications/-/aws-s3-notifications-0.20.0.tgz", + "integrity": "sha512-2jiEhS4qOCfsQcPax+xAb3icXcyApRClnzEOzPfnhxnWhH6T19r4D7MWnha7c3cjc9InkkEksGvXFzTvdPSKKQ==", + "requires": { + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/aws-sns": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-sns/-/aws-sns-0.20.0.tgz", + "integrity": "sha512-28pN8oKIT6b4RwEgG+HkrOU6DxWp//6Vh+z7JQfG4jCvbTEyqKAo6pEnEExJMBAhfQDjln1CKDMbBlhXG9wBfA==", + "requires": { + "@aws-cdk/aws-autoscaling-api": "^0.20.0", + "@aws-cdk/aws-cloudwatch": "^0.20.0", + "@aws-cdk/aws-events": "^0.20.0", + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/aws-lambda": "^0.20.0", + "@aws-cdk/aws-s3-notifications": "^0.20.0", + "@aws-cdk/aws-sqs": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/aws-sqs": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-sqs/-/aws-sqs-0.20.0.tgz", + "integrity": "sha512-c8dCcVOFoWAqc8EUqav2NMRZD9AkGth9bYDjTdYnxG3H9eOmaYiv5IWRrLhTPWdPc0VCy9cGGK2lAtf+isBr4w==", + "requires": { + "@aws-cdk/aws-autoscaling-api": "^0.20.0", + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/aws-kms": "^0.20.0", + "@aws-cdk/aws-s3-notifications": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/aws-stepfunctions": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-stepfunctions/-/aws-stepfunctions-0.20.0.tgz", + "integrity": "sha512-VS5dcMQ+VAm1WMoAYt4p5K5crBw511qPOULmBwWRnHAezUPlJgtqKgev0ffNTpA+g1RTQP4ZoTaHpIFISi+wZA==", + "requires": { + "@aws-cdk/aws-cloudwatch": "^0.20.0", + "@aws-cdk/aws-events": "^0.20.0", + "@aws-cdk/aws-iam": "^0.20.0", + "@aws-cdk/cdk": "^0.20.0" + } + }, + "@aws-cdk/cdk": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cdk/-/cdk-0.20.0.tgz", + "integrity": "sha512-wzwQIrUUPtHN3Mj5v5w/Eu33Vk/81iM9ilNiBTTdcyw++52OjYQ7iTb47QXeVg8IxGz+lX+lRE/f4IJUNTzRfA==", + "requires": { + "@aws-cdk/cx-api": "^0.20.0", + "js-base64": "^2.4.5", + "json-diff": "^0.3.1" + }, + "dependencies": { + "cli-color": { + "version": "0.1.7", + "resolved": "http://registry.npmjs.org/cli-color/-/cli-color-0.1.7.tgz", + "integrity": "sha1-rcMgD6RxzCEbDaf1ZrcemLnWc0c=", + "requires": { + "es5-ext": "0.8.x" + } + }, + "difflib": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", + "integrity": "sha1-teMDYabbAjF21WKJLbhZQKcY9H4=", + "requires": { + "heap": ">= 0.2.0" + } + }, + "dreamopt": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.6.0.tgz", + "integrity": "sha1-2BPM2sjTnYrVJndVFKE92mZNa0s=", + "requires": { + "wordwrap": ">=0.0.2" + } + }, + "es5-ext": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.8.2.tgz", + "integrity": "sha1-q6jZ4ZQ6iVrJaDemKjmz9V7NlKs=" + }, + "heap": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", + "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=" + }, + "js-base64": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", + "integrity": "sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==" + }, + "json-diff": { + "version": "0.3.1", + "resolved": "http://registry.npmjs.org/json-diff/-/json-diff-0.3.1.tgz", + "integrity": "sha1-bbw64tJeB1p/1xvNmHRFhmb7aBs=", + "requires": { + "cli-color": "~0.1.6", + "difflib": "~0.2.1", + "dreamopt": "~0.6.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + } + } + }, + "@aws-cdk/cfnspec": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cfnspec/-/cfnspec-0.20.0.tgz", + "integrity": "sha512-yU9zxwwogk34BnZb22P6uudsZ6EtJb6YsqFxh4aaC/Uk3lrUh8hlUSLsx2R+F4OFDg1I1hT0m4xjsHVaObe/SQ==", + "requires": { + "md5": "^2.2.1" + } + }, + "@aws-cdk/cloudformation-diff": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cloudformation-diff/-/cloudformation-diff-0.20.0.tgz", + "integrity": "sha512-jQN1aT1jLK9MRsmHJnTTZcbqz8Kf/54VhODvHfxcYORrBsGU1dr5XIlwND1eYhILN72YpC3Cdg8n4IpM+qzSkg==", + "requires": { + "@aws-cdk/cfnspec": "^0.20.0", + "@aws-cdk/cx-api": "^0.20.0", + "cli-table": "^0.3.1", + "colors": "^1.2.1", + "fast-deep-equal": "^2.0.1", + "source-map-support": "^0.5.6" + } + }, + "@aws-cdk/cx-api": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cx-api/-/cx-api-0.20.0.tgz", + "integrity": "sha512-tbV4msow2+V9xUIDiYzD3ZGBKkdOzMYicR7zXl98i5jJT3EphbMDzulsJ7LVEMKyFIV/1q0NA0k3SJ6T22nVSw==" + }, + "@types/dotenv": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-6.1.0.tgz", + "integrity": "sha512-gmbNb7V1LbJQA4MmH0hVFgqY1cyKsa6RvKC1Xrq0WBnZ0JuuvXKciXx/s8dN0LVXCJd8xO6wIaSFSyUIoGph9g==", + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", + "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "archiver": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", + "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", + "requires": { + "archiver-utils": "^1.3.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "zip-stream": "^1.2.0" + } + }, + "archiver-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", + "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "requires": { + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash": "^4.8.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "ast-types": { + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.7.tgz", + "integrity": "sha512-2mP3TwtkY/aTv5X3ZsMpNAbOnyoC/aMJwJSoaELPkHId0nSQgFcnU4dRW3isxiz7+zBexk0ym3WNVjMiQBnJSw==" + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-cdk": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-0.20.0.tgz", + "integrity": "sha512-ddrWkiKstafJhRq8P70VXlGXtGNZaxdTs5CfZ64K/dK/2SbftmI+e1dxN801Uwej5oW0VKpoi+h+ooKL0M6abg==", + "requires": { + "@aws-cdk/applet-js": "^0.20.0", + "@aws-cdk/cloudformation-diff": "^0.20.0", + "@aws-cdk/cx-api": "^0.20.0", + "archiver": "^2.1.1", + "aws-sdk": "^2.259.1", + "camelcase": "^5.0.0", + "cli-table": "^0.3.1", + "colors": "^1.2.1", + "decamelize": "^2.0.0", + "fs-extra": "^7.0.0", + "json-diff": "^0.3.1", + "minimatch": ">=3.0", + "promptly": "^0.2.0", + "proxy-agent": "^3.0.1", + "request": "^2.83.0", + "semver": "^5.5.0", + "source-map-support": "^0.5.6", + "table": "^5.1.0", + "yaml": "^1.1.0", + "yargs": "^9.0.1" + } + }, + "aws-sdk": { + "version": "2.376.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.376.0.tgz", + "integrity": "sha512-7/xsLzgF0GJIFTy2qPmn+dFLQoBpWponm+FS9aHUmjI0UMiTieBJzHUSZ8BHIY/4JukBLc3B5hL5evW+NS4pzw==", + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "ieee754": "1.1.8", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.1.0", + "xml2js": "0.4.19" + }, + "dependencies": { + "buffer": { + "version": "4.9.1", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, + "cli-color": { + "version": "0.1.7", + "resolved": "http://registry.npmjs.org/cli-color/-/cli-color-0.1.7.tgz", + "integrity": "sha1-rcMgD6RxzCEbDaf1ZrcemLnWc0c=", + "requires": { + "es5-ext": "0.8.x" + } + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "requires": { + "colors": "1.0.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "http://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + } + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "requires": { + "buffer-crc32": "^0.2.1", + "crc32-stream": "^2.0.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "requires": { + "buffer": "^5.1.0" + } + }, + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "requires": { + "crc": "^3.4.4", + "readable-stream": "^2.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-uri-to-buffer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==" + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", + "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", + "requires": { + "xregexp": "4.0.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "requires": { + "ast-types": "0.x.x", + "escodegen": "1.x.x", + "esprima": "3.x.x" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "difflib": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", + "integrity": "sha1-teMDYabbAjF21WKJLbhZQKcY9H4=", + "requires": { + "heap": ">= 0.2.0" + } + }, + "dotenv": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", + "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==" + }, + "dreamopt": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.6.0.tgz", + "integrity": "sha1-2BPM2sjTnYrVJndVFKE92mZNa0s=", + "requires": { + "wordwrap": ">=0.0.2" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.8.2.tgz", + "integrity": "sha1-q6jZ4ZQ6iVrJaDemKjmz9V7NlKs=" + }, + "es6-promise": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escodegen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", + "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "events": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" + } + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-uri": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", + "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", + "requires": { + "data-uri-to-buffer": "1", + "debug": "2", + "extend": "3", + "file-uri-to-path": "1", + "ftp": "~0.3.10", + "readable-stream": "2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "heap": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", + "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=" + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-diff": { + "version": "0.3.1", + "resolved": "http://registry.npmjs.org/json-diff/-/json-diff-0.3.1.tgz", + "integrity": "sha1-bbw64tJeB1p/1xvNmHRFhmb7aBs=", + "requires": { + "cli-color": "~0.1.6", + "difflib": "~0.2.1", + "dreamopt": "~0.6.0" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "requires": { + "charenc": "~0.0.1", + "crypt": "~0.0.1", + "is-buffer": "~1.1.1" + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "~1.37.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=" + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "pac-proxy-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", + "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "get-uri": "^2.0.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "pac-resolver": "^3.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "^4.0.1" + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "requires": { + "co": "^4.6.0", + "degenerator": "^1.0.4", + "ip": "^1.1.5", + "netmask": "^1.0.6", + "thunkify": "^2.1.2" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "promptly": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-0.2.1.tgz", + "integrity": "sha1-ZETnyk29mJnn7rXsOSKCfr3CKzs=", + "requires": { + "read": "~1.0.4" + } + }, + "proxy-agent": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.3.tgz", + "integrity": "sha512-PXVVVuH9tiQuxQltFJVSnXWuDtNr+8aNBP6XVDDCDiUuDN8eRCm+ii4/mFWmXWEA0w8jjJSlePa4LXlM4jIzNA==", + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "pac-proxy-agent": "^3.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^4.0.1" + } + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.1", + "resolved": "http://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slice-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.0.0.tgz", + "integrity": "sha512-4j2WTWjp3GsZ+AOagyzVbzp4vWGtZ0hEZ/gDY/uTvm6MTxUfTUIsnMIFb1bn8o0RuXiqUw15H1bue8f22Vw2oQ==", + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "smart-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz", + "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==" + }, + "socks": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.2.tgz", + "integrity": "sha512-g6wjBnnMOZpE0ym6e0uHSddz9p3a+WsBaaYQaBaSCJYvrC4IXykQR9MNGjLQf38e9iIIhp3b1/Zk8YZI3KGJ0Q==", + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.0.1" + } + }, + "socks-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", + "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", + "requires": { + "agent-base": "~4.2.0", + "socks": "~2.2.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", + "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==" + }, + "sshpk": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", + "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "table": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/table/-/table-5.1.1.tgz", + "integrity": "sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw==", + "requires": { + "ajv": "^6.6.1", + "lodash": "^4.17.11", + "slice-ansi": "2.0.0", + "string-width": "^2.1.1" + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typescript": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", + "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==" + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xregexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", + "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yaml": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.1.0.tgz", + "integrity": "sha512-MD5Ptelnnjfj/w4UqdNguD9Ipzm3ws6bNiYkGkl4lkfGMU1V7QYyHkRh28EiHPdprSvV+xAhvLJ6ifyALYw7wA==" + }, + "yargs": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + } + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "requires": { + "camelcase": "^4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + } + } + }, + "zip-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", + "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", + "requires": { + "archiver-utils": "^1.3.0", + "compress-commons": "^1.2.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9dccf3f --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "trello_backup", + "version": "1.0.0", + "description": "Backup Trello boards to S3", + "main": "index.js", + "scripts": { + "buildLambdaFunctions": "cd lambdaFunctions && ./build.sh", + "build": "tsc && npm run buildLambdaFunctions" + }, + "author": "Go Free Range Ltd", + "license": "ISC", + "dependencies": { + "@aws-cdk/aws-events": "^0.20.0", + "@aws-cdk/aws-lambda": "^0.20.0", + "@aws-cdk/aws-s3": "^0.20.0", + "@aws-cdk/aws-sns": "^0.20.0", + "@types/dotenv": "^6.1.0", + "aws-cdk": "^0.20.0", + "dotenv": "^6.2.0", + "typescript": "^3.2.2" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..d68129f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "commonjs" + } +}