diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 000000000..1c45422e2
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,20 @@
+environment:
+ global:
+ SLS_IGNORE_WARNING: "*"
+ matrix:
+ - NODEJS_VERSION: "4"
+ - NODEJS_VERSION: "6"
+
+install:
+ # Get the version of Node.js
+ - ps: Install-Product node $Env:NODEJS_VERSION
+ # install modules
+ - npm install
+ - node --version
+ - npm --version
+
+test_script:
+ - npm test
+
+# Don't actually build.
+build: off
diff --git a/.eslintignore b/.eslintignore
index 412a51062..c29438b87 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -2,3 +2,4 @@ coverage
node_modules
tmp
tmpdirs-serverless
+lib/plugins/create/templates/**
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0644f59f4..5f306e18d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,28 @@
+# 1.20.2 (17.08.2017)
+- [Bump event-gateway version to 0.5.15](https://github.com/serverless/serverless/pull/4116)
+
+## Meta
+- [Comparison since last release](https://github.com/serverless/serverless/compare/v1.20.1...v1.20.2)
+
+
+# 1.20.1 (17.08.2017)
+- [Rethrow original plugin error in debug mode](https://github.com/serverless/serverless/pull/4091)
+- [Add platform gate to serverless run / emit](https://github.com/serverless/serverless/pull/4103)
+
+## Meta
+- [Comparison since last release](https://github.com/serverless/serverless/compare/v1.20.0...v1.20.1)
+
+
+# 1.20.0 (16.08.2017)
+- [Add Serverless Run plugin](https://github.com/serverless/serverless/pull/4034)
+- [Add Serverless Emit plugin](https://github.com/serverless/serverless/pull/4038)
+- [Kubeless template for python and nodejs](https://github.com/serverless/serverless/pull/3970)
+- [Improve deprecation hook message](https://github.com/serverless/serverless/pull/4011)
+
+## Meta
+- [Comparison since last release](https://github.com/serverless/serverless/compare/v1.19.0...v1.20.0)
+
+
# 1.19.0 (02.08.2017)
- [Removed provider name validation](https://github.com/serverless/serverless/pull/3941)
- [Fixed a bug with dev dependencies exclusion](https://github.com/serverless/serverless/pull/3975)
@@ -8,7 +33,6 @@
- [Comparison since last release](https://github.com/serverless/serverless/compare/v1.18.1...v1.19.0)
-
# 1.18.1 (28.07.2017)
- [Fixed a bug with Serverless Variables](https://github.com/serverless/serverless/pull/3996)
- [Fixed a bug with dev dependencies exclusion](https://github.com/serverless/serverless/pull/3975)
diff --git a/Dockerfile b/Dockerfile
index a0066f1f4..eacb4f70c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,5 +6,8 @@ RUN curl -o- -L https://yarnpkg.com/install.sh | bash
# install python tooling
RUN apt-get update -y && apt-get install -y python-dev python-pip && pip install --upgrade pip
+# install other utils
+RUN apt-get update -y && apt-get install -y screen
+
# install aws-cli
RUN pip install awscli
diff --git a/README.md b/README.md
index f721d4c9f..14f75373f 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](http://serverless.com)
+[](http://serverless.com)
[](http://www.serverless.com)
[](https://travis-ci.org/serverless/serverless)
@@ -152,74 +152,74 @@ This table is generated from https://github.com/serverless/plugins/blob/master/p
-->
| Plugin | Author |
|:-------|:------:|
-| **[API GW binary support](https://github.com/maciejtreder/serverless-apigw-binary)**
Serverless plugin to enable binary support in AWS API Gateway. | [Maciej Treder](https://github.com/maciejtreder) |
-| **[Raml Serverless](https://github.com/andrewcurioso/raml-serverless)**
Serverless plugin to work with RAML API spec documents | [andrewcurioso](http://github.com/andrewcurioso) |
-| **[Serverless Alexa Plugin](https://github.com/rajington/serverless-alexa-plugin)**
Serverless plugin to support Alexa Lambda events | [rajington](http://github.com/rajington) |
-| **[Serverless Api Stage](https://github.com/leftclickben/serverless-api-stage)**
Serverless API Stage plugin, enables stage variables and logging for AWS API Gateway. | [leftclickben](http://github.com/leftclickben) |
-| **[Serverless Apig S3](https://github.com/sdd/serverless-apig-s3)**
Serve static front-end content from S3 via the API Gatewy and deploy client bundle to S3. | [sdd](http://github.com/sdd) |
-| **[Serverless Aws Alias](https://github.com/HyperBrain/serverless-aws-alias)**
This plugin enables use of AWS aliases on Lambda functions. | [HyperBrain](http://github.com/HyperBrain) |
-| **[Serverless Aws Documentation](https://github.com/9cookies/serverless-aws-documentation)**
Serverless plugin to add documentation and models to the serverless generated API Gateway | [9cookies](http://github.com/9cookies) |
-| **[Serverless Build Plugin](https://github.com/nfour/serverless-build-plugin)**
A Node.js focused build plugin for serverless. | [nfour](http://github.com/nfour) |
-| **[Serverless Cljs Plugin](https://github.com/nervous-systems/serverless-cljs-plugin)**
Enables Clojurescript as an implementation language for Lambda handlers | [nervous-systems](http://github.com/nervous-systems) |
-| **[Serverless Coffeescript](https://github.com/duanefields/serverless-coffeescript)**
A Serverless plugin to compile your CoffeeScript into JavaScript at deployment | [duanefields](http://github.com/duanefields) |
-| **[Serverless Command Line Event Args](https://github.com/horike37/serverless-command-line-event-args)**
This module is Serverless Framework plugin. Event JSON passes to your Lambda function in commandline. | [horike37](http://github.com/horike37) |
-| **[Serverless Crypt](https://github.com/marcy-terui/serverless-crypt)**
Securing the secrets on Serverless Framework by AWS KMS encryption. | [marcy-terui](http://github.com/marcy-terui) |
-| **[Serverless Dir Config Plugin](https://github.com/economysizegeek/serverless-dir-config-plugin)**
EXPERIMENTAL - Serverless plugin to load function and resource definitions from a directory. | [economysizegeek](http://github.com/economysizegeek) |
-| **[Serverless Dotenv](https://github.com/Jimdo/serverless-dotenv)**
Fetch environment variables and write it to a .env file | [Jimdo](http://github.com/Jimdo) |
-| **[Serverless Dotnet](https://github.com/fruffin/serverless-dotnet)**
A serverless plugin to run 'dotnet' commands as part of the deploy process | [fruffin](http://github.com/fruffin) |
-| **[Serverless Dynalite](https://github.com/sdd/serverless-dynalite)**
Run dynalite locally (no JVM, all JS) to simulate DynamoDB. Watch serverless.yml for table config updates. | [sdd](http://github.com/sdd) |
-| **[Serverless Dynamodb Local](https://github.com/99xt/serverless-dynamodb-local)**
Serverless Dynamodb Local Plugin - Allows to run dynamodb locally for serverless | [99xt](http://github.com/99xt) |
-| **[Serverless Dynamodb Ttl](https://github.com/Jimdo/serverless-dynamodb-ttl)**
Configure DynamoDB TTL in serverless.yml (until CloudFormation supports this). | [Jimdo](http://github.com/Jimdo) |
-| **[Serverless Enable Api Logs](https://github.com/paulSambolin/serverless-enable-api-logs)**
Enables Coudwatch logging for API Gateway events | [paulSambolin](http://github.com/paulSambolin) |
-| **[Serverless Event Constant Inputs](https://github.com/dittto/serverless-event-constant-inputs)**
Allows you to add constant inputs to events in Serverless 1.0. For more info see [constant values in Cloudwatch](https://aws.amazon.com/blogs/compute/simply-serverless-use-constant-values-in-cloudwatch-event-triggered-lambda-functions/) | [dittto](http://github.com/dittto) |
-| **[Serverless Export Env](https://github.com/arabold/serverless-export-env)**
Export environment variables into a .env file with automatic AWS CloudFormation reference resolution. | [arabold](http://github.com/arabold) |
-| **[Serverless Hooks Plugin](https://github.com/uswitch/serverless-hooks-plugin)**
Run arbitrary commands on any lifecycle event in serverless | [uswitch](http://github.com/uswitch) |
-| **[Serverless Jest Plugin](https://github.com/SC5/serverless-jest-plugin)**
A Serverless Plugin for the Serverless Framework which adds support for test-driven development using Jest | [SC5](http://github.com/SC5) |
-| **[Serverless Mocha Plugin](https://github.com/SC5/serverless-mocha-plugin)**
A Serverless Plugin for the Serverless Framework which adds support for test-driven development using Mocha | [SC5](http://github.com/SC5) |
-| **[Serverless Offline](https://github.com/dherault/serverless-offline)**
Emulate AWS λ and API Gateway locally when developing your Serverless project | [dherault](http://github.com/dherault) |
-| **[Serverless Offline Scheduler](https://github.com/ajmath/serverless-offline-scheduler)**
Runs scheduled functions offline while integrating with serverless-offline | [ajmath](http://github.com/ajmath) |
-| **[Serverless Package Python Functions](https://github.com/ubaniabalogun/serverless-package-python-functions)**
Packaging Python Lambda functions with only the dependencies/requirements they need. | [ubaniabalogun](http://github.com/ubaniabalogun) |
-| **[Serverless Parameters](https://github.com/svdgraaf/serverless-parameters)**
Add parameters to the generated cloudformation templates | [svdgraaf](http://github.com/svdgraaf) |
-| **[Serverless Plugin Aws Alerts](https://github.com/ACloudGuru/serverless-plugin-aws-alerts)**
A Serverless plugin to easily add CloudWatch alarms to functions | [ACloudGuru](http://github.com/ACloudGuru) |
-| **[Serverless Plugin Bind Deployment Id](https://github.com/jacob-meacham/serverless-plugin-bind-deployment-id)**
A Serverless plugin to bind the randomly generated deployment resource to your custom resources | [jacob-meacham](http://github.com/jacob-meacham) |
-| **[Serverless Plugin Browserify](https://github.com/doapp-ryanp/serverless-plugin-browserify)**
Speed up your node based lambda's | [doapp-ryanp](http://github.com/doapp-ryanp) |
-| **[Serverless Plugin Cfauthorizer](https://github.com/SC5/serverless-plugin-cfauthorizer)**
This plugin allows you to define your own API Gateway Authorizers as the Serverless CloudFormation resources and apply them to HTTP endpoints. | [SC5](http://github.com/SC5) |
-| **[Serverless Plugin Cloudwatch Sumologic](https://github.com/ACloudGuru/serverless-plugin-cloudwatch-sumologic)**
Plugin which auto-subscribes a log delivery lambda function to lambda log groups created by serverless | [ACloudGuru](http://github.com/ACloudGuru) |
-| **[Serverless Plugin Diff](https://github.com/nicka/serverless-plugin-diff)**
Compares your local AWS CloudFormation templates against deployed ones. | [nicka](http://github.com/nicka) |
-| **[Serverless Plugin Encode Env Var Objects](https://github.com/yonomi/serverless-plugin-encode-env-var-objects)**
Serverless plugin to encode any environment variable objects. | [yonomi](http://github.com/yonomi) |
-| **[Serverless Plugin External Sns Events](https://github.com/silvermine/serverless-plugin-external-sns-events)**
Add ability for functions to use existing or external SNS topics as an event source | [silvermine](http://github.com/silvermine) |
-| **[Serverless Plugin Git Variables](https://github.com/jacob-meacham/serverless-plugin-git-variables)**
A Serverless plugin to expose git variables (branch name, HEAD description, full commit hash) to your serverless services | [jacob-meacham](http://github.com/jacob-meacham) |
-| **[Serverless Plugin Graphiql](https://github.com/bencooling/serverless-plugin-graphiql)**
A Serverless plugin to run a local http server for graphiql and your graphql handler | [bencooling](http://github.com/bencooling) |
-| **[Serverless Plugin Include Dependencies](https://github.com/dougmoscrop/serverless-plugin-include-dependencies)**
This is a Serverless plugin that should make your deployed functions smaller. | [dougmoscrop](http://github.com/dougmoscrop) |
-| **[Serverless Plugin Iopipe](https://github.com/iopipe/serverless-plugin-iopipe)**
See inside your Lambda functions with high fidelity metrics and monitoring. | [iopipe](http://github.com/iopipe) |
-| **[Serverless Plugin Lambda Dead Letter](https://github.com/gmetzker/serverless-plugin-lambda-dead-letter)**
A Serverless plugin that can configure a lambda with a dead letter queue or topic | [gmetzker](http://github.com/gmetzker) |
-| **[Serverless Plugin Multiple Responses](https://github.com/silvermine/serverless-plugin-multiple-responses)**
Enable multiple content-types for Response template | [silvermine](http://github.com/silvermine) |
-| **[Serverless Plugin Optimize](https://github.com/FidelLimited/serverless-plugin-optimize)**
Bundle with Browserify, transpile with Babel to ES5 and minify with Uglify your Serverless functions. | [FidelLimited](http://github.com/FidelLimited) |
-| **[Serverless Plugin Package Dotenv File](https://github.com/ACloudGuru/serverless-plugin-package-dotenv-file)**
A Serverless plugin to copy a .env file into the serverless package | [ACloudGuru](http://github.com/ACloudGuru) |
-| **[Serverless Plugin Scripts](https://github.com/mvila/serverless-plugin-scripts)**
Add scripting capabilities to the Serverless Framework | [mvila](http://github.com/mvila) |
-| **[Serverless Plugin Select](https://github.com/FidelLimited/serverless-plugin-select)**
Select which functions are to be deployed based on region and stage. | [FidelLimited](http://github.com/FidelLimited) |
-| **[Serverless Plugin Simulate](https://github.com/gertjvr/serverless-plugin-simulate)**
Simulate AWS Lambda and API Gateway locally using Docker | [gertjvr](http://github.com/gertjvr) |
-| **[Serverless Plugin Stack Outputs](https://github.com/svdgraaf/serverless-plugin-stack-outputs)**
Displays stack outputs for your serverless stacks when `sls info` is ran | [svdgraaf](http://github.com/svdgraaf) |
-| **[Serverless Plugin Stage Variables](https://github.com/svdgraaf/serverless-plugin-stage-variables)**
Add stage variables for Serverless 1.x to ApiGateway, so you can use variables in your Lambda's | [svdgraaf](http://github.com/svdgraaf) |
-| **[Serverless Plugin Subscription Filter](https://github.com/tsub/serverless-plugin-subscription-filter)**
A serverless plugin to register AWS CloudWatchLogs subscription filter | [tsub](http://github.com/tsub) |
-| **[Serverless Plugin Typescript](https://github.com/graphcool/serverless-plugin-typescript)**
Serverless plugin for zero-config Typescript support. | [graphcool](http://github.com/graphcool) |
-| **[Serverless Plugin Warmup](https://github.com/FidelLimited/serverless-plugin-warmup)**
Keep your lambdas warm during Winter. | [FidelLimited](http://github.com/FidelLimited) |
-| **[Serverless Plugin Webpack](https://github.com/goldwasserexchange/serverless-plugin-webpack)**
A serverless plugin to automatically bundle your functions individually with webpack | [goldwasserexchange](http://github.com/goldwasserexchange) |
-| **[Serverless Plugin Write Env Vars](https://github.com/silvermine/serverless-plugin-write-env-vars)**
Write environment variables out to a file that is compatible with dotenv | [silvermine](http://github.com/silvermine) |
-| **[Serverless Prune Plugin](https://github.com/claygregory/serverless-prune-plugin)**
Deletes old versions of functions from AWS, preserving recent and aliased versions | [claygregory](http://github.com/claygregory) |
-| **[Serverless Pseudo Parameters](https://github.com/svdgraaf/serverless-pseudo-parameters)**
Use ${AWS::AccountId} and other cloudformation pseudo parameters in your serverless.yml values | [svdgraaf](http://github.com/svdgraaf) |
-| **[Serverless Python Individually](https://github.com/cfchou/serverless-python-individually)**
A serverless framework plugin to install multiple lambda functions written in python | [cfchou](http://github.com/cfchou) |
-| **[Serverless Python Requirements](https://github.com/UnitedIncome/serverless-python-requirements)**
Serverless plugin to bundle Python packages | [UnitedIncome](http://github.com/UnitedIncome) |
-| **[Serverless Resources Env](https://github.com/rurri/serverless-resources-env)**
After Deploy, this plugin fetches cloudformation resource identifiers and sets them on AWS lambdas, and creates local .-env file | [rurri](http://github.com/rurri) |
-| **[Serverless Run Function Plugin](https://github.com/lithin/serverless-run-function-plugin)**
Run serverless function locally | [lithin](http://github.com/lithin) |
-| **[Serverless Sam](https://github.com/SAPessi/serverless-sam)**
Exports an AWS SAM template for a service created with the Serverless Framework. | [SAPessi](http://github.com/SAPessi) |
-| **[Serverless Scriptable Plugin](https://github.com/weixu365/serverless-scriptable-plugin)**
Customize Serverless behavior without writing a plugin. | [weixu365](http://github.com/weixu365) |
-| **[Serverless Sqs Alarms Plugin](https://github.com/sbstjn/serverless-sqs-alarms-plugin)**
Wrapper to setup CloudWatch Alarms on SQS queue length | [sbstjn](http://github.com/sbstjn) |
-| **[Serverless Sqs Fifo](https://github.com/vortarian/serverless-sqs-fifo)**
A serverless plugin to handle creation of sqs fifo queue's in aws (stop-gap) | [vortarian](http://github.com/vortarian) |
-| **[Serverless Step Functions](https://github.com/horike37/serverless-step-functions)**
AWS Step Functions with Serverless Framework. | [horike37](http://github.com/horike37) |
-| **[Serverless Subscription Filter](https://github.com/blackevil245/serverless-subscription-filter)**
Serverless plugin to register subscription filter for Lambda logs. Register and pipe the logs of one lambda to another to process. | [blackevil245](http://github.com/blackevil245) |
-| **[Serverless Vpc Discovery](https://github.com/amplify-education/serverless-vpc-discovery)**
Serverless plugin for discovering VPC / Subnet / Security Group configuration by name. | [amplify-education](http://github.com/amplify-education) |
-| **[Serverless Webpack](https://github.com/elastic-coders/serverless-webpack)**
Serverless plugin to bundle your lambdas with Webpack | [elastic-coders](http://github.com/elastic-coders) |
+| **[API GW binary support](https://github.com/maciejtreder/serverless-apigw-binary)**
Serverless plugin to enable binary support in AWS API Gateway. | [Maciej Treder](https://github.com/maciejtreder) |
+| **[Raml Serverless](https://github.com/andrewcurioso/raml-serverless)**
Serverless plugin to work with RAML API spec documents | [andrewcurioso](http://github.com/andrewcurioso) |
+| **[Serverless Alexa Plugin](https://github.com/rajington/serverless-alexa-plugin)**
Serverless plugin to support Alexa Lambda events | [rajington](http://github.com/rajington) |
+| **[Serverless Api Stage](https://github.com/leftclickben/serverless-api-stage)**
Serverless API Stage plugin, enables stage variables and logging for AWS API Gateway. | [leftclickben](http://github.com/leftclickben) |
+| **[Serverless Apig S3](https://github.com/sdd/serverless-apig-s3)**
Serve static front-end content from S3 via the API Gatewy and deploy client bundle to S3. | [sdd](http://github.com/sdd) |
+| **[Serverless Aws Alias](https://github.com/HyperBrain/serverless-aws-alias)**
This plugin enables use of AWS aliases on Lambda functions. | [HyperBrain](http://github.com/HyperBrain) |
+| **[Serverless Aws Documentation](https://github.com/9cookies/serverless-aws-documentation)**
Serverless plugin to add documentation and models to the serverless generated API Gateway | [9cookies](http://github.com/9cookies) |
+| **[Serverless Build Plugin](https://github.com/nfour/serverless-build-plugin)**
A Node.js focused build plugin for serverless. | [nfour](http://github.com/nfour) |
+| **[Serverless Cljs Plugin](https://github.com/nervous-systems/serverless-cljs-plugin)**
Enables Clojurescript as an implementation language for Lambda handlers | [nervous-systems](http://github.com/nervous-systems) |
+| **[Serverless Coffeescript](https://github.com/duanefields/serverless-coffeescript)**
A Serverless plugin to compile your CoffeeScript into JavaScript at deployment | [duanefields](http://github.com/duanefields) |
+| **[Serverless Command Line Event Args](https://github.com/horike37/serverless-command-line-event-args)**
This module is Serverless Framework plugin. Event JSON passes to your Lambda function in commandline. | [horike37](http://github.com/horike37) |
+| **[Serverless Crypt](https://github.com/marcy-terui/serverless-crypt)**
Securing the secrets on Serverless Framework by AWS KMS encryption. | [marcy-terui](http://github.com/marcy-terui) |
+| **[Serverless Dir Config Plugin](https://github.com/economysizegeek/serverless-dir-config-plugin)**
EXPERIMENTAL - Serverless plugin to load function and resource definitions from a directory. | [economysizegeek](http://github.com/economysizegeek) |
+| **[Serverless Dotenv](https://github.com/Jimdo/serverless-dotenv)**
Fetch environment variables and write it to a .env file | [Jimdo](http://github.com/Jimdo) |
+| **[Serverless Dotnet](https://github.com/fruffin/serverless-dotnet)**
A serverless plugin to run 'dotnet' commands as part of the deploy process | [fruffin](http://github.com/fruffin) |
+| **[Serverless Dynalite](https://github.com/sdd/serverless-dynalite)**
Run dynalite locally (no JVM, all JS) to simulate DynamoDB. Watch serverless.yml for table config updates. | [sdd](http://github.com/sdd) |
+| **[Serverless Dynamodb Local](https://github.com/99xt/serverless-dynamodb-local)**
Serverless Dynamodb Local Plugin - Allows to run dynamodb locally for serverless | [99xt](http://github.com/99xt) |
+| **[Serverless Dynamodb Ttl](https://github.com/Jimdo/serverless-dynamodb-ttl)**
Configure DynamoDB TTL in serverless.yml (until CloudFormation supports this). | [Jimdo](http://github.com/Jimdo) |
+| **[Serverless Enable Api Logs](https://github.com/paulSambolin/serverless-enable-api-logs)**
Enables Coudwatch logging for API Gateway events | [paulSambolin](http://github.com/paulSambolin) |
+| **[Serverless Event Constant Inputs](https://github.com/dittto/serverless-event-constant-inputs)**
Allows you to add constant inputs to events in Serverless 1.0. For more info see [constant values in Cloudwatch](https://aws.amazon.com/blogs/compute/simply-serverless-use-constant-values-in-cloudwatch-event-triggered-lambda-functions/) | [dittto](http://github.com/dittto) |
+| **[Serverless Export Env](https://github.com/arabold/serverless-export-env)**
Export environment variables into a .env file with automatic AWS CloudFormation reference resolution. | [arabold](http://github.com/arabold) |
+| **[Serverless Hooks Plugin](https://github.com/uswitch/serverless-hooks-plugin)**
Run arbitrary commands on any lifecycle event in serverless | [uswitch](http://github.com/uswitch) |
+| **[Serverless Jest Plugin](https://github.com/SC5/serverless-jest-plugin)**
A Serverless Plugin for the Serverless Framework which adds support for test-driven development using Jest | [SC5](http://github.com/SC5) |
+| **[Serverless Mocha Plugin](https://github.com/SC5/serverless-mocha-plugin)**
A Serverless Plugin for the Serverless Framework which adds support for test-driven development using Mocha | [SC5](http://github.com/SC5) |
+| **[Serverless Offline](https://github.com/dherault/serverless-offline)**
Emulate AWS λ and API Gateway locally when developing your Serverless project | [dherault](http://github.com/dherault) |
+| **[Serverless Offline Scheduler](https://github.com/ajmath/serverless-offline-scheduler)**
Runs scheduled functions offline while integrating with serverless-offline | [ajmath](http://github.com/ajmath) |
+| **[Serverless Package Python Functions](https://github.com/ubaniabalogun/serverless-package-python-functions)**
Packaging Python Lambda functions with only the dependencies/requirements they need. | [ubaniabalogun](http://github.com/ubaniabalogun) |
+| **[Serverless Parameters](https://github.com/svdgraaf/serverless-parameters)**
Add parameters to the generated cloudformation templates | [svdgraaf](http://github.com/svdgraaf) |
+| **[Serverless Plugin Aws Alerts](https://github.com/ACloudGuru/serverless-plugin-aws-alerts)**
A Serverless plugin to easily add CloudWatch alarms to functions | [ACloudGuru](http://github.com/ACloudGuru) |
+| **[Serverless Plugin Bind Deployment Id](https://github.com/jacob-meacham/serverless-plugin-bind-deployment-id)**
A Serverless plugin to bind the randomly generated deployment resource to your custom resources | [jacob-meacham](http://github.com/jacob-meacham) |
+| **[Serverless Plugin Browserify](https://github.com/doapp-ryanp/serverless-plugin-browserify)**
Speed up your node based lambda's | [doapp-ryanp](http://github.com/doapp-ryanp) |
+| **[Serverless Plugin Cfauthorizer](https://github.com/SC5/serverless-plugin-cfauthorizer)**
This plugin allows you to define your own API Gateway Authorizers as the Serverless CloudFormation resources and apply them to HTTP endpoints. | [SC5](http://github.com/SC5) |
+| **[Serverless Plugin Cloudwatch Sumologic](https://github.com/ACloudGuru/serverless-plugin-cloudwatch-sumologic)**
Plugin which auto-subscribes a log delivery lambda function to lambda log groups created by serverless | [ACloudGuru](http://github.com/ACloudGuru) |
+| **[Serverless Plugin Diff](https://github.com/nicka/serverless-plugin-diff)**
Compares your local AWS CloudFormation templates against deployed ones. | [nicka](http://github.com/nicka) |
+| **[Serverless Plugin Encode Env Var Objects](https://github.com/yonomi/serverless-plugin-encode-env-var-objects)**
Serverless plugin to encode any environment variable objects. | [yonomi](http://github.com/yonomi) |
+| **[Serverless Plugin External Sns Events](https://github.com/silvermine/serverless-plugin-external-sns-events)**
Add ability for functions to use existing or external SNS topics as an event source | [silvermine](http://github.com/silvermine) |
+| **[Serverless Plugin Git Variables](https://github.com/jacob-meacham/serverless-plugin-git-variables)**
A Serverless plugin to expose git variables (branch name, HEAD description, full commit hash) to your serverless services | [jacob-meacham](http://github.com/jacob-meacham) |
+| **[Serverless Plugin Graphiql](https://github.com/bencooling/serverless-plugin-graphiql)**
A Serverless plugin to run a local http server for graphiql and your graphql handler | [bencooling](http://github.com/bencooling) |
+| **[Serverless Plugin Include Dependencies](https://github.com/dougmoscrop/serverless-plugin-include-dependencies)**
This is a Serverless plugin that should make your deployed functions smaller. | [dougmoscrop](http://github.com/dougmoscrop) |
+| **[Serverless Plugin Iopipe](https://github.com/iopipe/serverless-plugin-iopipe)**
See inside your Lambda functions with high fidelity metrics and monitoring. | [iopipe](http://github.com/iopipe) |
+| **[Serverless Plugin Lambda Dead Letter](https://github.com/gmetzker/serverless-plugin-lambda-dead-letter)**
A Serverless plugin that can configure a lambda with a dead letter queue or topic | [gmetzker](http://github.com/gmetzker) |
+| **[Serverless Plugin Multiple Responses](https://github.com/silvermine/serverless-plugin-multiple-responses)**
Enable multiple content-types for Response template | [silvermine](http://github.com/silvermine) |
+| **[Serverless Plugin Optimize](https://github.com/FidelLimited/serverless-plugin-optimize)**
Bundle with Browserify, transpile with Babel to ES5 and minify with Uglify your Serverless functions. | [FidelLimited](http://github.com/FidelLimited) |
+| **[Serverless Plugin Package Dotenv File](https://github.com/ACloudGuru/serverless-plugin-package-dotenv-file)**
A Serverless plugin to copy a .env file into the serverless package | [ACloudGuru](http://github.com/ACloudGuru) |
+| **[Serverless Plugin Scripts](https://github.com/mvila/serverless-plugin-scripts)**
Add scripting capabilities to the Serverless Framework | [mvila](http://github.com/mvila) |
+| **[Serverless Plugin Select](https://github.com/FidelLimited/serverless-plugin-select)**
Select which functions are to be deployed based on region and stage. | [FidelLimited](http://github.com/FidelLimited) |
+| **[Serverless Plugin Simulate](https://github.com/gertjvr/serverless-plugin-simulate)**
Simulate AWS Lambda and API Gateway locally using Docker | [gertjvr](http://github.com/gertjvr) |
+| **[Serverless Plugin Stack Outputs](https://github.com/svdgraaf/serverless-plugin-stack-outputs)**
Displays stack outputs for your serverless stacks when `sls info` is ran | [svdgraaf](http://github.com/svdgraaf) |
+| **[Serverless Plugin Stage Variables](https://github.com/svdgraaf/serverless-plugin-stage-variables)**
Add stage variables for Serverless 1.x to ApiGateway, so you can use variables in your Lambda's | [svdgraaf](http://github.com/svdgraaf) |
+| **[Serverless Plugin Subscription Filter](https://github.com/tsub/serverless-plugin-subscription-filter)**
A serverless plugin to register AWS CloudWatchLogs subscription filter | [tsub](http://github.com/tsub) |
+| **[Serverless Plugin Typescript](https://github.com/graphcool/serverless-plugin-typescript)**
Serverless plugin for zero-config Typescript support. | [graphcool](http://github.com/graphcool) |
+| **[Serverless Plugin Warmup](https://github.com/FidelLimited/serverless-plugin-warmup)**
Keep your lambdas warm during Winter. | [FidelLimited](http://github.com/FidelLimited) |
+| **[Serverless Plugin Webpack](https://github.com/goldwasserexchange/serverless-plugin-webpack)**
A serverless plugin to automatically bundle your functions individually with webpack | [goldwasserexchange](http://github.com/goldwasserexchange) |
+| **[Serverless Plugin Write Env Vars](https://github.com/silvermine/serverless-plugin-write-env-vars)**
Write environment variables out to a file that is compatible with dotenv | [silvermine](http://github.com/silvermine) |
+| **[Serverless Prune Plugin](https://github.com/claygregory/serverless-prune-plugin)**
Deletes old versions of functions from AWS, preserving recent and aliased versions | [claygregory](http://github.com/claygregory) |
+| **[Serverless Pseudo Parameters](https://github.com/svdgraaf/serverless-pseudo-parameters)**
Use ${AWS::AccountId} and other cloudformation pseudo parameters in your serverless.yml values | [svdgraaf](http://github.com/svdgraaf) |
+| **[Serverless Python Individually](https://github.com/cfchou/serverless-python-individually)**
A serverless framework plugin to install multiple lambda functions written in python | [cfchou](http://github.com/cfchou) |
+| **[Serverless Python Requirements](https://github.com/UnitedIncome/serverless-python-requirements)**
Serverless plugin to bundle Python packages | [UnitedIncome](http://github.com/UnitedIncome) |
+| **[Serverless Resources Env](https://github.com/rurri/serverless-resources-env)**
After Deploy, this plugin fetches cloudformation resource identifiers and sets them on AWS lambdas, and creates local .-env file | [rurri](http://github.com/rurri) |
+| **[Serverless Run Function Plugin](https://github.com/lithin/serverless-run-function-plugin)**
Run serverless function locally | [lithin](http://github.com/lithin) |
+| **[Serverless Sam](https://github.com/SAPessi/serverless-sam)**
Exports an AWS SAM template for a service created with the Serverless Framework. | [SAPessi](http://github.com/SAPessi) |
+| **[Serverless Scriptable Plugin](https://github.com/weixu365/serverless-scriptable-plugin)**
Customize Serverless behavior without writing a plugin. | [weixu365](http://github.com/weixu365) |
+| **[Serverless Sqs Alarms Plugin](https://github.com/sbstjn/serverless-sqs-alarms-plugin)**
Wrapper to setup CloudWatch Alarms on SQS queue length | [sbstjn](http://github.com/sbstjn) |
+| **[Serverless Sqs Fifo](https://github.com/vortarian/serverless-sqs-fifo)**
A serverless plugin to handle creation of sqs fifo queue's in aws (stop-gap) | [vortarian](http://github.com/vortarian) |
+| **[Serverless Step Functions](https://github.com/horike37/serverless-step-functions)**
AWS Step Functions with Serverless Framework. | [horike37](http://github.com/horike37) |
+| **[Serverless Subscription Filter](https://github.com/blackevil245/serverless-subscription-filter)**
Serverless plugin to register subscription filter for Lambda logs. Register and pipe the logs of one lambda to another to process. | [blackevil245](http://github.com/blackevil245) |
+| **[Serverless Vpc Discovery](https://github.com/amplify-education/serverless-vpc-discovery)**
Serverless plugin for discovering VPC / Subnet / Security Group configuration by name. | [amplify-education](http://github.com/amplify-education) |
+| **[Serverless Webpack](https://github.com/elastic-coders/serverless-webpack)**
Serverless plugin to bundle your lambdas with Webpack | [elastic-coders](http://github.com/elastic-coders) |
| **[Serverless Wsgi](https://github.com/logandk/serverless-wsgi)**
Serverless plugin to deploy WSGI applications (Flask/Django/Pyramid etc.) and bundle Python packages | [logandk](http://github.com/logandk) |
@@ -230,50 +230,50 @@ This table is generated from https://github.com/serverless/examples/blob/master/
-->
| Project Name | Author |
|:-------------|:------:|
-| **[Serverless Graphql Api](https://github.com/boazdejong/serverless-graphql-api)**
Serverless GraphQL API using Lambda and DynamoDB | [boazdejong](http://github.com/boazdejong) |
-| **[Serverless Screenshot](https://github.com/svdgraaf/serverless-screenshot)**
Serverless Screenshot Service using PhantomJS | [svdgraaf](http://github.com/svdgraaf) |
-| **[Serverless Postgraphql](https://github.com/rentrop/serverless-postgraphql)**
GraphQL endpoint for PostgreSQL using postgraphql | [rentrop](http://github.com/rentrop) |
-| **[Serverless Messenger Boilerplate](https://github.com/SC5/serverless-messenger-boilerplate)**
Serverless messenger bot boilerplate | [SC5](http://github.com/SC5) |
-| **[Serverless Npm Registry](https://github.com/craftship/yith)**
Serverless private npm registry, proxy and cache. | [craftship](http://github.com/craftship) |
-| **[Serverless Pokego](https://github.com/jch254/pokego-serverless)**
Serverless-powered API to fetch nearby Pokemon Go data | [jch254](http://github.com/jch254) |
-| **[Serverless Weekly2pocket App](https://github.com/s0enke/weekly2pocket)**
Serverless-powered API for sending posts to pocket app | [s0enke](http://github.com/s0enke) |
-| **[Serverless Facebook Quotebot](https://github.com/pmuens/quotebot)**
100% Serverless Facebook messenger chatbot which will respond with inspiring quotes | [pmuens](http://github.com/pmuens) |
-| **[Serverless Slack Trevorbot](https://github.com/conveyal/trevorbot)**
Slack bot for info on where in the world is Trevor Gerhardt? | [conveyal](http://github.com/conveyal) |
-| **[Serverless Garden Aid](https://github.com/garden-aid/web-bff)**
IoT Garden Aid Backend | [garden-aid](http://github.com/garden-aid) |
-| **[Serverless React Boilerplate](https://github.com/99xt/serverless-react-boilerplate)**
A serverless react boilerplate for offline development | [99xt](http://github.com/99xt) |
-| **[Serverless Delivery Framework](https://github.com/99xt/serverless-delivery-framework)**
This is a boilerplate for version release pipeline with serverless framework | [99xt](http://github.com/99xt) |
-| **[Serverless Mailgun Slack](https://github.com/Marcus-L/serverless-mailgun-slack)**
A Serverless function for posting to a Slack Webhook in response to a Mailgun route | [Marcus-L](http://github.com/Marcus-L) |
-| **[Pfs Email Serverless](https://github.com/SCPR/pfs-email-serverless)**
This is a lambda function created by the serverless framework. It searches through members in our mongodb who have not been sent emails and sends them an email with their custom token to unlock the pledge free stream. It then marks those members off as already receiving the email. | [SCPR](http://github.com/SCPR) |
-| **[Plaid Cashburndown Service](https://github.com/cplee/cashburndown-service)**
Service for calculating cash burndown with plaid. Frontend code can be found here: https://github.com/cplee/cashburndown-site | [cplee](http://github.com/cplee) |
-| **[Cordis Serverless](https://github.com/marzeelabs/cordis-serverless)**
A serverless API for EU Cordis data | [marzeelabs](http://github.com/marzeelabs) |
-| **[Serverless Newsletter Signup](https://github.com/ivanderbu2/serverless-newsletter-signup)**
Saves user details into DynamoDB table. Required values are email, first_name and last_name. | [ivanderbu2](http://github.com/ivanderbu2) |
-| **[Serverless Slack Cron](https://github.com/ivanderbu2/serverless-slack-cron)**
Lambda function which sends messages to Slack channel in regular intervals via cron trigger. | [ivanderbu2](http://github.com/ivanderbu2) |
-| **[Giphy Bot](https://github.com/tywong/lambda-workshop-2016/tree/master/giphy-bot)**
giphy-bot for Facebook chat | [tywong](http://github.com/tywong) |
-| **[Jwt Lambda Python](https://github.com/mikaelmork/jwt-auth.serverless)**
Minimal proof-of-concept implementation of JWT with Serverless / AWS Lambda | [mikaelmork](http://github.com/mikaelmork) |
-| **[Sls Access Counter](https://github.com/takahashim/sls-access-counter)**
Site visitor counter | [takahashim](http://github.com/takahashim) |
-| **[Sls Form Mail](https://github.com/takahashim/sls-form-mail)**
Send SNS email from form data | [takahashim](http://github.com/takahashim) |
-| **[Serverless Python Sample](https://github.com/bennybauer/serverless-python-sample)**
A simple serverless python sample with REST API endpoints and dependencies | [bennybauer](http://github.com/bennybauer) |
-| **[Serverless Msg Gateway](https://github.com/yonahforst/msg-gateway)**
A messaging aggregator for kik, skype, twilio, telegram, & messenger. Send and receive messages in a standard format. | [yonahforst](http://github.com/yonahforst) |
-| **[Serverless Aws Rekognition Finpics](https://github.com/rgfindl/finpics)**
Use AWS Rekognition to provide a faces search of finpics.com | [rgfindl](http://github.com/rgfindl) |
-| **[Serverless Slack Emojibot](https://github.com/markhobson/emojibot)**
Serverless slack bot for emoji | [markhobson](http://github.com/markhobson) |
-| **[Keboola Developer Portal](https://github.com/keboola/developer-portal)**
Keboola developer portal built with Serverless | [keboola](http://github.com/keboola) |
-| **[Serverless Cloudwatch Rds Custom Metrics](https://github.com/AndrewFarley/serverless-cloudwatch-rds-custom-metrics)**
A NodeJS-based MySQL RDS Data Collection script to push Custom Metrics to Cloudwatch with Serverless | [AndrewFarley](http://github.com/AndrewFarley) |
-| **[Jrestless Examples](https://github.com/bbilger/jrestless-examples)**
[JRestless](https://github.com/bbilger/jrestless) (Java / JAX-RS) examples for [API Gateway Functions](https://github.com/bbilger/jrestless-examples/tree/master/aws/gateway) ([plain JAX-RS](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-showcase), [Spring](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-spring), [binary data requests/responses](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-binary), [custom authorizers](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-security-custom-authorizer) and [Cognito User Pool authorizers](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-security-cognito-authorizer)), [SNS Functions](https://github.com/bbilger/jrestless-examples/blob/master/aws/sns/aws-sns-usage-example) (asynchronous communication between functions) and [Service Functions](https://github.com/bbilger/jrestless-examples/blob/master/aws/service/aws-service-usage-example) (synchronous HTTP-like communication between functions - transparent through Feign) | [bbilger](http://github.com/bbilger) |
-| **[Sc5 Serverless Boilerplate](https://github.com/SC5/sc5-serverless-boilerplate)**
A boilerplate that contains setup for test-driven development | [SC5](http://github.com/SC5) |
-| **[Serverless Blog To Podcast](https://github.com/SC5/serverless-blog-to-podcast)**
Service that reads RSS feed and converts the entries to a podcast feed and audio files using Amazon Polly | [SC5](http://github.com/SC5) |
-| **[Offset Trump](https://github.com/FLGMwt/offset-trump)**
Single page app using Serverless (C# runtime) and S3 site hosting. Pledge to do a good thing for the next four years to offset the potential negative effects of the US Presidency | [FLGMwt](http://github.com/FLGMwt) |
-| **[Serverless Url Shortener](https://github.com/aletheia/serverless-url-shortener)**
A simple url-shortener, using Serverless framework | [aletheia](http://github.com/aletheia) |
-| **[Serverless Html Pdf](https://github.com/calvintychan/serverless-html-pdf)**
Service that convert HTML to PDF using PhantomJS's rasterize example. | [calvintychan](http://github.com/calvintychan) |
-| **[Serverless Examples Cached Rds Ws](https://github.com/mugglmenzel/serverless-examples-cached-rds-ws)**
A serverless framework example project that uses API Gateway, ElastiCache, and RDS PostgreSQL. | [mugglmenzel](http://github.com/mugglmenzel) |
-| **[Bittman](https://github.com/rhlsthrm/bittman)**
A serverless project that follows a stock trading algorithm and uses scheduled functions to save data to DynamoDB and send emails through Mailgun. | [rhlsthrm](http://github.com/rhlsthrm) |
-| **[Adoptable Pet Bot](https://github.com/lynnaloo/adoptable-pet-bot)**
Tweets adoptable pets using Serverless (Node.js) and AWS Lambda | [lynnaloo](http://github.com/lynnaloo) |
-| **[Owntracks Serverless](https://github.com/dschep/owntracks-serverless)**
A serverless implementation of the OwnTracks HTTP backend | [dschep](http://github.com/dschep) |
-| **[Serverless Modern Koa](https://github.com/barczaG/serverless-modern-koa)**
Serverless modern koa starter kit | [barczaG](http://github.com/barczaG) |
-| **[Serverless Reactjs Universal Rendering Boilerplate](https://github.com/TylorShin/react-universal-in-serverless)**
ReactJS web app Starter kit does universal (isomorphic) rendering with Serverless | [TylorShin](http://github.com/TylorShin) |
-| **[Open Bot](https://github.com/open-bot/open-bot)**
An unoptionated Github bot driven by a configuration file in the repository | [open-bot](http://github.com/open-bot) |
-| **[Aws Ses Serverless Example](https://github.com/lakshmantgld/aws-ses-serverless-example)**
AWS SES example in NodeJS using lambda | [lakshmantgld](http://github.com/lakshmantgld) |
-| **[Aws Api Gateway Serverless Project Written In Go](https://github.com/yunspace/serverless-golang)**
A serverless project that contains an API Gateway endpoint powered by a Lambda function written in golang and built using [eawsy/aws-lambda-go-shim](https://github.com/eawsy/aws-lambda-go-shim). | [yunspace](http://github.com/yunspace) |
-| **[Video Preview And Analysis Service](https://github.com/laardee/video-preview-and-analysis-service)**
An event-driven service that generates labels using Amazon Rekognition and creates preview GIF animation from a video file. | [laardee](http://github.com/laardee) |
+| **[Serverless Graphql Api](https://github.com/boazdejong/serverless-graphql-api)**
Serverless GraphQL API using Lambda and DynamoDB | [boazdejong](http://github.com/boazdejong) |
+| **[Serverless Screenshot](https://github.com/svdgraaf/serverless-screenshot)**
Serverless Screenshot Service using PhantomJS | [svdgraaf](http://github.com/svdgraaf) |
+| **[Serverless Postgraphql](https://github.com/rentrop/serverless-postgraphql)**
GraphQL endpoint for PostgreSQL using postgraphql | [rentrop](http://github.com/rentrop) |
+| **[Serverless Messenger Boilerplate](https://github.com/SC5/serverless-messenger-boilerplate)**
Serverless messenger bot boilerplate | [SC5](http://github.com/SC5) |
+| **[Serverless Npm Registry](https://github.com/craftship/yith)**
Serverless private npm registry, proxy and cache. | [craftship](http://github.com/craftship) |
+| **[Serverless Pokego](https://github.com/jch254/pokego-serverless)**
Serverless-powered API to fetch nearby Pokemon Go data | [jch254](http://github.com/jch254) |
+| **[Serverless Weekly2pocket App](https://github.com/s0enke/weekly2pocket)**
Serverless-powered API for sending posts to pocket app | [s0enke](http://github.com/s0enke) |
+| **[Serverless Facebook Quotebot](https://github.com/pmuens/quotebot)**
100% Serverless Facebook messenger chatbot which will respond with inspiring quotes | [pmuens](http://github.com/pmuens) |
+| **[Serverless Slack Trevorbot](https://github.com/conveyal/trevorbot)**
Slack bot for info on where in the world is Trevor Gerhardt? | [conveyal](http://github.com/conveyal) |
+| **[Serverless Garden Aid](https://github.com/garden-aid/web-bff)**
IoT Garden Aid Backend | [garden-aid](http://github.com/garden-aid) |
+| **[Serverless React Boilerplate](https://github.com/99xt/serverless-react-boilerplate)**
A serverless react boilerplate for offline development | [99xt](http://github.com/99xt) |
+| **[Serverless Delivery Framework](https://github.com/99xt/serverless-delivery-framework)**
This is a boilerplate for version release pipeline with serverless framework | [99xt](http://github.com/99xt) |
+| **[Serverless Mailgun Slack](https://github.com/Marcus-L/serverless-mailgun-slack)**
A Serverless function for posting to a Slack Webhook in response to a Mailgun route | [Marcus-L](http://github.com/Marcus-L) |
+| **[Pfs Email Serverless](https://github.com/SCPR/pfs-email-serverless)**
This is a lambda function created by the serverless framework. It searches through members in our mongodb who have not been sent emails and sends them an email with their custom token to unlock the pledge free stream. It then marks those members off as already receiving the email. | [SCPR](http://github.com/SCPR) |
+| **[Plaid Cashburndown Service](https://github.com/cplee/cashburndown-service)**
Service for calculating cash burndown with plaid. Frontend code can be found here: https://github.com/cplee/cashburndown-site | [cplee](http://github.com/cplee) |
+| **[Cordis Serverless](https://github.com/marzeelabs/cordis-serverless)**
A serverless API for EU Cordis data | [marzeelabs](http://github.com/marzeelabs) |
+| **[Serverless Newsletter Signup](https://github.com/ivanderbu2/serverless-newsletter-signup)**
Saves user details into DynamoDB table. Required values are email, first_name and last_name. | [ivanderbu2](http://github.com/ivanderbu2) |
+| **[Serverless Slack Cron](https://github.com/ivanderbu2/serverless-slack-cron)**
Lambda function which sends messages to Slack channel in regular intervals via cron trigger. | [ivanderbu2](http://github.com/ivanderbu2) |
+| **[Giphy Bot](https://github.com/tywong/lambda-workshop-2016/tree/master/giphy-bot)**
giphy-bot for Facebook chat | [tywong](http://github.com/tywong) |
+| **[Jwt Lambda Python](https://github.com/mikaelmork/jwt-auth.serverless)**
Minimal proof-of-concept implementation of JWT with Serverless / AWS Lambda | [mikaelmork](http://github.com/mikaelmork) |
+| **[Sls Access Counter](https://github.com/takahashim/sls-access-counter)**
Site visitor counter | [takahashim](http://github.com/takahashim) |
+| **[Sls Form Mail](https://github.com/takahashim/sls-form-mail)**
Send SNS email from form data | [takahashim](http://github.com/takahashim) |
+| **[Serverless Python Sample](https://github.com/bennybauer/serverless-python-sample)**
A simple serverless python sample with REST API endpoints and dependencies | [bennybauer](http://github.com/bennybauer) |
+| **[Serverless Msg Gateway](https://github.com/yonahforst/msg-gateway)**
A messaging aggregator for kik, skype, twilio, telegram, & messenger. Send and receive messages in a standard format. | [yonahforst](http://github.com/yonahforst) |
+| **[Serverless Aws Rekognition Finpics](https://github.com/rgfindl/finpics)**
Use AWS Rekognition to provide a faces search of finpics.com | [rgfindl](http://github.com/rgfindl) |
+| **[Serverless Slack Emojibot](https://github.com/markhobson/emojibot)**
Serverless slack bot for emoji | [markhobson](http://github.com/markhobson) |
+| **[Keboola Developer Portal](https://github.com/keboola/developer-portal)**
Keboola developer portal built with Serverless | [keboola](http://github.com/keboola) |
+| **[Serverless Cloudwatch Rds Custom Metrics](https://github.com/AndrewFarley/serverless-cloudwatch-rds-custom-metrics)**
A NodeJS-based MySQL RDS Data Collection script to push Custom Metrics to Cloudwatch with Serverless | [AndrewFarley](http://github.com/AndrewFarley) |
+| **[Jrestless Examples](https://github.com/bbilger/jrestless-examples)**
[JRestless](https://github.com/bbilger/jrestless) (Java / JAX-RS) examples for [API Gateway Functions](https://github.com/bbilger/jrestless-examples/tree/master/aws/gateway) ([plain JAX-RS](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-showcase), [Spring](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-spring), [binary data requests/responses](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-binary), [custom authorizers](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-security-custom-authorizer) and [Cognito User Pool authorizers](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-security-cognito-authorizer)), [SNS Functions](https://github.com/bbilger/jrestless-examples/blob/master/aws/sns/aws-sns-usage-example) (asynchronous communication between functions) and [Service Functions](https://github.com/bbilger/jrestless-examples/blob/master/aws/service/aws-service-usage-example) (synchronous HTTP-like communication between functions - transparent through Feign) | [bbilger](http://github.com/bbilger) |
+| **[Sc5 Serverless Boilerplate](https://github.com/SC5/sc5-serverless-boilerplate)**
A boilerplate that contains setup for test-driven development | [SC5](http://github.com/SC5) |
+| **[Serverless Blog To Podcast](https://github.com/SC5/serverless-blog-to-podcast)**
Service that reads RSS feed and converts the entries to a podcast feed and audio files using Amazon Polly | [SC5](http://github.com/SC5) |
+| **[Offset Trump](https://github.com/FLGMwt/offset-trump)**
Single page app using Serverless (C# runtime) and S3 site hosting. Pledge to do a good thing for the next four years to offset the potential negative effects of the US Presidency | [FLGMwt](http://github.com/FLGMwt) |
+| **[Serverless Url Shortener](https://github.com/aletheia/serverless-url-shortener)**
A simple url-shortener, using Serverless framework | [aletheia](http://github.com/aletheia) |
+| **[Serverless Html Pdf](https://github.com/calvintychan/serverless-html-pdf)**
Service that convert HTML to PDF using PhantomJS's rasterize example. | [calvintychan](http://github.com/calvintychan) |
+| **[Serverless Examples Cached Rds Ws](https://github.com/mugglmenzel/serverless-examples-cached-rds-ws)**
A serverless framework example project that uses API Gateway, ElastiCache, and RDS PostgreSQL. | [mugglmenzel](http://github.com/mugglmenzel) |
+| **[Bittman](https://github.com/rhlsthrm/bittman)**
A serverless project that follows a stock trading algorithm and uses scheduled functions to save data to DynamoDB and send emails through Mailgun. | [rhlsthrm](http://github.com/rhlsthrm) |
+| **[Adoptable Pet Bot](https://github.com/lynnaloo/adoptable-pet-bot)**
Tweets adoptable pets using Serverless (Node.js) and AWS Lambda | [lynnaloo](http://github.com/lynnaloo) |
+| **[Owntracks Serverless](https://github.com/dschep/owntracks-serverless)**
A serverless implementation of the OwnTracks HTTP backend | [dschep](http://github.com/dschep) |
+| **[Serverless Modern Koa](https://github.com/barczaG/serverless-modern-koa)**
Serverless modern koa starter kit | [barczaG](http://github.com/barczaG) |
+| **[Serverless Reactjs Universal Rendering Boilerplate](https://github.com/TylorShin/react-universal-in-serverless)**
ReactJS web app Starter kit does universal (isomorphic) rendering with Serverless | [TylorShin](http://github.com/TylorShin) |
+| **[Open Bot](https://github.com/open-bot/open-bot)**
An unoptionated Github bot driven by a configuration file in the repository | [open-bot](http://github.com/open-bot) |
+| **[Aws Ses Serverless Example](https://github.com/lakshmantgld/aws-ses-serverless-example)**
AWS SES example in NodeJS using lambda | [lakshmantgld](http://github.com/lakshmantgld) |
+| **[Aws Api Gateway Serverless Project Written In Go](https://github.com/yunspace/serverless-golang)**
A serverless project that contains an API Gateway endpoint powered by a Lambda function written in golang and built using [eawsy/aws-lambda-go-shim](https://github.com/eawsy/aws-lambda-go-shim). | [yunspace](http://github.com/yunspace) |
+| **[Video Preview And Analysis Service](https://github.com/laardee/video-preview-and-analysis-service)**
An event-driven service that generates labels using Amazon Rekognition and creates preview GIF animation from a video file. | [laardee](http://github.com/laardee) |
| **[Serverless Es6/7 Crud Api](https://github.com/AnomalyInnovations/serverless-stack-demo-api)**
[Serverless Stack](http://serverless-stack.com) examples of backend CRUD APIs (DynamoDB + Lambda + API Gateway + Cognito User Pool authorizer) for [React.js single-page app](http://demo.serverless-stack.com) | [AnomalyInnovations](http://github.com/AnomalyInnovations) |
diff --git a/RELEASE_CHECKLIST.md b/RELEASE_CHECKLIST.md
index 568eefbb1..d3f0c9dcf 100644
--- a/RELEASE_CHECKLIST.md
+++ b/RELEASE_CHECKLIST.md
@@ -2,50 +2,45 @@
This checklist should be worked through when releasing a new Serverless version.
+More info about our release process can be found in the [`RELEASE_PROCESS.md`](./RELEASE_PROCESS.md) document.
+
## Pre-Release
+
- [ ] Look through all open issues and PRs (if any) of that milestone and close them / move them to another
milestone if still open
-- [ ] Look through all closed issues and PRs of that milestone to see what has changed. Run `./scripts/pr-since-last tag` or if you want to run against a specific tag `./scripts/pr-since-last tag v1.0.3` to get a list of all merged PR's since a specific tag
-- [ ] Close milestone on Github
-- [ ] Create a new release in GitHub for Release Notes (including breaking changes)
+- [ ] Look through all closed issues and PRs of that milestone to see what has changed. Run `./scripts/prs-since-last tag` or if you want to run against a specific tag `./scripts/prs-since-last tag v1.20.0` to get a list of all merged PR's since a specific tag
+- [ ] Close milestone on GitHub
+- [ ] Create a new draft release in GitHub
# Testing
+
- [ ] Create a Serverless service (with some events), deploy and test it intensively
-- [ ] Run integration test repository against the current release
- [ ] Look through the milestone and test all of the new major changes
-- [ ] Run "npm test"
-- [ ] Run "npm run simple-integration-test"
-- [ ] Run "npm run complex-integration-test"
+- [ ] Run `npm test`
+- [ ] Run `npm run simple-integration-test`
+- [ ] Run `npm run complex-integration-test`
## Prepare Package
-- [ ] Create a new branch to bump version in package.json
-- [ ] Install the latest NPM version or Docker container with latest Node and NPM
-- [ ] Bump version in package.json, remove `node_modules` folder and run `npm install` and `npm prune --production && npm shrinkwrap`
-- [ ] Update CHANGELOG.md (including breaking changes)
+
+- [ ] Create a new branch to bump version in `package.json`
+- [ ] Install the latest `npm` version or Docker container with latest `node` and `npm`
+- [ ] Bump version in `package.json`, remove `node_modules` folder and run `npm install` and `npm prune --production && npm shrinkwrap`
+- [ ] Look through closed PRs and update `CHANGELOG.md`
- [ ] Make sure all files that need to be pushed are included in `package.json -> files`
- [ ] Send PR and merge PR with new version to be released
-- [ ] Go back to branch you want to release from (e.g. master or v1) and pull bumped version changes from Github
+- [ ] Add the changes you made to `CHANGELOG.md` to the description of the GitHub release draft
+- [ ] Go back to branch you want to release from (e.g. `master`) and pull bumped version changes from GitHub
- [ ] Make sure there are no local changes to your repository (or reset with `git reset --hard HEAD`)
-- [ ] Check package.json and npm-shrinkwrap.json version config to make sure it fits what we want to release. *DO THIS, DON'T SKIP, DON'T BE LAZY!!!*
+- [ ] Check `package.json`, `package-lock.json` and `npm-shrinkwrap.json` version config to make sure it fits what we want to release
-## Git Tagging
-- [ ] Create a git tag with the version (`git tag `: `git tag v1.0.0`)
-- [ ] Push the git tag (`git push origin `)
+## Releasing
-## Segment Configuration
-- [ ] Update Segment.io key in [segment.js file](https://github.com/serverless/serverless/blob/d31057239d232181128d978c392bdecbcb9fcf1b/lib/utils/segment.js#L7) (never push the key to GitHub and revert afterwards with `git checkout .`)
-- [ ] Check twice if you've used the correct key (**if in doubt ask which one to pick!**)
-- [ ] Run `./bin/serverless help` and filter for this new version in the Segment debugger to make sure data is sent to Segment for this new version
-
-## Release to NPM
-- [ ] Log into npm (`npm login`)
-- [ ] Publish to NPM (`npm publish —-tag `, e.g. `npm publish --tag beta` or `npm publish` to release latest production framework)
-- [ ] Update Alpha/Beta accordingly so they point to the latest release. If its an Alpha Release the Beta tag should point to the latest stable release. This way Alpha/Beta always either point to something stable or the highest priority release in Alpha/Beta stage (`npm dist-tag add serverless@ alpha`, `npm dist-tag add serverless@ beta`)
+- [ ] Publish the GitHub release draft (Travis CI will automatically publish the new release to `npm`)
## Validate Release
-- [ ] Validate NPM install works (`npm install -g serverless@` or `npm install -g serverless` if latest is released)
-- [ ] Check Segment.com production data if events are coming in correctly with the new version
-- [ ] Make sure you run `git checkout .` to revert adding Segment write key
+
+- [ ] Validate that `npm install` works (`npm install -g serverless@` or `npm install -g serverless` if latest is released)
## Post-Release
+
- [ ] Run `./scripts/generate-release-contributors-list ` and hand the generated list over to the release blog post author
diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md
new file mode 100644
index 000000000..22db95c76
--- /dev/null
+++ b/RELEASE_PROCESS.md
@@ -0,0 +1,51 @@
+# Release Process
+
+This document contains all the necessary information about out release process.
+
+### Merge freeze
+
+A "merge freeze" will be applied a few days before the release. This means that **NOTHING** will be added to the release branch.
+
+A "merge freeze" ends once the release was published.
+
+## Different types of releases
+
+**Note:** More about versioning can be found in our dedicated [VERSIONING file](https://github.com/serverless/serverless/blob/master/VERSIONING.md).
+
+Releases can come in different flavors. Here's a list with the most common release types and how they're treated
+
+### Minor / Major release
+
+The minor / major release is a planned release which includes all the changes added since the last minor / major release (including bugfixes). The user should pick up the latest minor / major release automatically when installing / updating Serverless.
+
+The minor / major releases is released at a pre-defined time.
+
+#### Versioning / tagging
+
+Assuming our current version is `v1.1.0`.
+
+The minor release would be `v1.2.0`. The major release would be `v2.0.0`.
+
+### Patch release
+
+Patch releases should **only** include critical bug fixes and released ASAP. The user should pick up the latest patch release automatically when installing / updating Serverless.
+
+#### Versioning / tagging
+
+Assuming our current version is `v1.1.0`.
+
+The patch release would be `v1.1.1`.
+
+### Alpha release
+
+Alpha releases are created to have a sneak peek into the upcoming feature set of the new release. They're also used for pre-release QA / internal usage.
+
+Alpha releases are not scheduled and can be pushed multiple times throughout a development phase.
+
+Alpha releases should never be installed automatically when the user installs / updates Serverless. The user should be forced to explicitly name the alpha release during the installation / update phase (e.g. via `npm install --global serverless@alpha`).
+
+#### Versioning / tagging
+
+Assuming our current version is `v1.1.0`.
+
+The alpha releas would be `v1.2.0-alpha.1`. A subsequent alpha release would be `v1.2.0-alpha.2` etc.
diff --git a/assets/.gitkeep b/assets/.gitkeep
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/assets/.gitkeep
@@ -0,0 +1 @@
+
diff --git a/assets/framework_repo.png b/assets/framework_repo.png
new file mode 100644
index 000000000..f614cbcb1
Binary files /dev/null and b/assets/framework_repo.png differ
diff --git a/docker-compose.yml b/docker-compose.yml
index 227462503..d8c1287ec 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -51,6 +51,14 @@ services:
image: microsoft/dotnet:1.0.4-sdk
volumes:
- ./tmp/serverless-integration-test-aws-fsharp:/app
+ aws-nodejs-typescript:
+ image: node:6.10.3
+ volumes:
+ - ./tmp/serverless-integration-test-aws-nodejs-typescript:/app
+ aws-nodejs-ecma-script:
+ image: node:6.10.3
+ volumes:
+ - ./tmp/serverless-integration-test-aws-nodejs-ecma-script:/app
google-nodejs:
image: node:6.9.1
volumes:
diff --git a/docs/platform/README.md b/docs/platform/README.md
new file mode 100644
index 000000000..dc31e0333
--- /dev/null
+++ b/docs/platform/README.md
@@ -0,0 +1,67 @@
+
+
+
+### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform)
+
+
+# Serverless Platform (Beta)
+
+The Serverless Platform is currently in experimental beta. If you'd like to participate in the beta, simply follow the instructions below.
+
+## Set-Up
+
+Make sure you have Node.js installed and run:
+
+```sh
+$ npm i serverless -g
+```
+
+Then, check the version to make sure you are using V1.20.0, or later:
+
+```sh
+$ serverless -v
+```
+
+## Usage
+
+First, register or log in to the Serverless platform in via the CLI
+
+```sh
+$ serverless login
+```
+
+After logging into the platform via the Serverless framework CLI every deploy will be published **privately** to the Serverless Platform. It allows you to view and share your deployed services.
+
+Give it a try with a new service, or an existing service:
+
+```sh
+$ serverless deploy
+```
+
+Then visit https://platform.serverless.com/ in your browser.
+
+
+## Beta CLI Commands
+
+Logging in to the platform enables access to beta features of the Serverless framework.
+
+### [`serverless run`](./commands/run.md)
+Start local development mode for a Serverless service. This mode downloads and installs the [event-gateway](https://github.com/serverless/event-gateway) and the [serverless emulator](https://github.com/serverless/emulator). Both of these are used to emulate a serverless service and develop against them locally.
+
+### [`serverless emit`](./commands/emit.md)
+Emit an event to an event-gateway.
+
+### [`serverless login`](./commands/login.md)
+Register or log in to the platform.
+
+### [`serverless logout`](./commands/logout.md)
+Logout of the platform.
diff --git a/docs/platform/commands/README.md b/docs/platform/commands/README.md
new file mode 100644
index 000000000..7ff5ac407
--- /dev/null
+++ b/docs/platform/commands/README.md
@@ -0,0 +1,26 @@
+
+
+
+### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform)
+
+
+
+## Beta CLI Commands
+
+Logging in to the platform enables access to beta features of the Serverless framework.
+
+### [`serverless run`](./run.md)
+Start local development mode for a Serverless service. This mode downloads and installs the [event-gateway](https://github.com/serverless/event-gateway) and the [serverless emulator](https://github.com/serverless/emulator). Both of these are used to emulate a serverless service and develop against them locally.
+
+### [`serverless emit`](./emit.md)
+Emit an event to an event-gateway.
+
+### [`serverless login`](./login.md)
+Register or log in to the platform.
+
+### [`serverless logout`](./logout.md)
+Logout of the platform.
diff --git a/docs/platform/commands/emit.md b/docs/platform/commands/emit.md
new file mode 100644
index 000000000..bc77b4e1c
--- /dev/null
+++ b/docs/platform/commands/emit.md
@@ -0,0 +1,49 @@
+
+
+
+### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform/commands/emit)
+
+
+# Emit
+
+The `emit` command emits an event to a serverless service
+
+```bash
+serverless emit -n my.event -d '{"foo":"bar"}'
+
+# Shorthand
+sls emit -n my.event -d '{"foo":"bar"}'
+```
+
+
+## Options
+- `--name` or `-n` The event name. **Required**.
+- `--data` or `-d` The event data
+- `--path` or `-p` Path to JSON or YAML file holding event data',
+- `--url` or `-u` Event Gateway address
+- `--datatype` or `-t` Data type for the event data. By default set to application/json
+
+
+
+## Provided lifecycle Events
+- `emit:emit`
+
+## Examples
+
+### Emitting an Event to locally running Event Gateway
+
+```bash
+serverless emit -n my.event -d '{"foo":"bar"}'
+```
+
+### Emitting an Event to a remote Event Gateway
+
+```bash
+serverless emit -n foo.bar -d '{"foo":"bar"}' -u https://mygateway.com
+```
diff --git a/docs/platform/commands/login.md b/docs/platform/commands/login.md
new file mode 100644
index 000000000..af07b7099
--- /dev/null
+++ b/docs/platform/commands/login.md
@@ -0,0 +1,26 @@
+
+
+
+### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform/commands/login)
+
+
+# Login
+
+The `login` command logs users into the serverless platform.
+
+It will create a new serverless platform account if one doesn't already exist.
+
+*This command opens a browser window*
+
+```bash
+serverless login
+
+# Shorthand
+sls login
+```
diff --git a/docs/platform/commands/logout.md b/docs/platform/commands/logout.md
new file mode 100644
index 000000000..f39b55342
--- /dev/null
+++ b/docs/platform/commands/logout.md
@@ -0,0 +1,22 @@
+
+
+
+### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform/commands/logout)
+
+
+# Logout
+
+The `logout` command logs users out the serverless platform.
+
+```bash
+serverless logout
+
+# Shorthand
+sls logout
+```
diff --git a/docs/platform/commands/run.md b/docs/platform/commands/run.md
new file mode 100644
index 000000000..a04fd376c
--- /dev/null
+++ b/docs/platform/commands/run.md
@@ -0,0 +1,39 @@
+
+
+
+### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform/commands/run)
+
+
+# Run
+
+The `run` command starts the serverless service locally.
+
+```bash
+serverless run
+
+# Shorthand
+sls run
+```
+
+## Supported Languages
+NOTE: *currently supports node js 6.3+ only*
+
+## Supported Providers
+- AWS Lambda
+- Google Cloud Functions (Pub/Sub only, HTTP coming soon)
+
+## Options
+- `--debug` or `-d` Start the emulator in debug mode
+- `--eport` or `-e` The Event Gateway API port. Defaults to 4000
+- `--cport` or `-c` The Event Gateway configuration port. Defaults to 4001
+- `--lport` or `-l` The Emulator port. Defaults to 4002
+
+
+## Provided lifecycle events
+- `run:run`
diff --git a/docs/providers/aws/README.md b/docs/providers/aws/README.md
index cda12a386..3ae4e335b 100644
--- a/docs/providers/aws/README.md
+++ b/docs/providers/aws/README.md
@@ -12,7 +12,7 @@ layout: Doc
Welcome to the Serverless AWS Functions documentation!
-If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://gitter.im/serverless/serverless)
+If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** [AWS system credentials](./guide/credentials.md) are required for using serverless + AWS.
diff --git a/docs/providers/aws/cli-reference/README.md b/docs/providers/aws/cli-reference/README.md
index 7553319ef..cddf4206f 100644
--- a/docs/providers/aws/cli-reference/README.md
+++ b/docs/providers/aws/cli-reference/README.md
@@ -14,4 +14,4 @@ Welcome to the Serverless AWS Lambda CLI Reference! Please select a section on
**Note:** Before continuing [AWS system credentials](../guide/credentials.md) are required for using the CLI.
-If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://gitter.im/serverless/serverless)
+If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
diff --git a/docs/providers/aws/cli-reference/config-credentials.md b/docs/providers/aws/cli-reference/config-credentials.md
index 79d8751b3..c8586988f 100644
--- a/docs/providers/aws/cli-reference/config-credentials.md
+++ b/docs/providers/aws/cli-reference/config-credentials.md
@@ -22,6 +22,7 @@ serverless config credentials --provider provider --key key --secret secret
- `--key` or `-k` The `aws_access_key_id`. **Required**.
- `--secret` or `-s` The `aws_secret_access_key`. **Required**.
- `--profile` or `-n` The name of the profile which should be created.
+- `--overwrite` or `-o` Overwrite the profile if it exists.
## Provided lifecycle events
@@ -44,3 +45,13 @@ serverless config credentials --provider aws --key 1234 --secret 5678 --profile
```
This example create and configure a `custom-profile` profile with the `aws_access_key_id` of `1234` and the `aws_secret_access_key` of `5678`.
+
+### Update an existing profile
+
+```bash
+serverless config credentials --provider aws --key 1234 --secret 5678 --profile custom-profile --overwrite
+```
+
+This example overwrite `custom-profile` profile with the `aws_access_key_id` of `1234` and the `aws_secret_access_key` of `5678`.
+
+If the profile do not exist, it will be added anyway.
diff --git a/docs/providers/aws/cli-reference/create.md b/docs/providers/aws/cli-reference/create.md
index 6d2a2296c..e27f01014 100644
--- a/docs/providers/aws/cli-reference/create.md
+++ b/docs/providers/aws/cli-reference/create.md
@@ -41,6 +41,8 @@ To see a list of available templates run `serverless create --help`
Most commonly used templates:
- aws-nodejs
+- aws-nodejs-typescript
+- aws-nodejs-ecma-script
- aws-python
- aws-python3
- aws-groovy-gradle
diff --git a/docs/providers/aws/cli-reference/invoke-local.md b/docs/providers/aws/cli-reference/invoke-local.md
index 5967b495e..a22689e11 100644
--- a/docs/providers/aws/cli-reference/invoke-local.md
+++ b/docs/providers/aws/cli-reference/invoke-local.md
@@ -23,6 +23,9 @@ serverless invoke local --function functionName
- `--function` or `-f` The name of the function in your service that you want to invoke locally. **Required**.
- `--path` or `-p` The path to a json file holding input data to be passed to the invoked function as the `event`. This path is relative to the root directory of the service.
- `--data` or `-d` String data to be passed as an event to your function. Keep in mind that if you pass both `--path` and `--data`, the data included in the `--path` file will overwrite the data you passed with the `--data` flag.
+- `--raw` Pass data as a raw string even if it is JSON. If not set, JSON data are parsed and passed as an object.
+- `--contextPath` or `-x`, The path to a json file holding input context to be passed to the invoked function. This path is relative to the root directory of the service.
+- `--context` or `-c`, String data to be passed as a context to your function. Same like with `--data`, context included in `--contextPath` will overwrite the context you passed with `--context` flag.
## Environment
@@ -51,6 +54,13 @@ serverless invoke local --function functionName --data "hello world"
serverless invoke local --function functionName --data '{"a":"bar"}'
```
+### Local function invocation with custom context
+
+```bash
+serverless invoke local --function functionName --context "hello world"
+```
+
+
### Local function invocation with data from standard input
```bash
@@ -76,6 +86,12 @@ This example will pass the json data in the `lib/data.json` file (relative to th
}
```
+### Local function invocation with context passing
+```bash
+serverless invoke local --function functionName --contextPath lib/context.json
+```
+This example will pass the json context in the `lib/context.json` file (relative to the root of the service) while invoking the specified/deployed function.
+
### Limitations
Currently, `invoke local` only supports the NodeJs and Python runtimes.
diff --git a/docs/providers/aws/cli-reference/invoke.md b/docs/providers/aws/cli-reference/invoke.md
index e52eeab20..668a2ee3d 100644
--- a/docs/providers/aws/cli-reference/invoke.md
+++ b/docs/providers/aws/cli-reference/invoke.md
@@ -23,6 +23,7 @@ serverless invoke [local] --function functionName
- `--stage` or `-s` The stage in your service you want to invoke your function in.
- `--region` or `-r` The region in your stage that you want to invoke your function in.
- `--data` or `-d` String data to be passed as an event to your function. By default data is read from standard input.
+- `--raw` Pass data as a raw string even if it is JSON. If not set, JSON data are parsed and passed as an object.
- `--path` or `-p` The path to a json file with input data to be passed to the invoked function. This path is relative to the root directory of the service.
- `--type` or `-t` The type of invocation. Either `RequestResponse`, `Event` or `DryRun`. Default is `RequestResponse`.
- `--log` or `-l` If set to `true` and invocation type is `RequestResponse`, it will output logging data of the invocation. Default is `false`.
@@ -44,6 +45,7 @@ serverless invoke local --function functionName
- `--path` or `-p` The path to a json file holding input data to be passed to the invoked function as the `event`. This path is relative to the
root directory of the service.
- `--data` or `-d` String data to be passed as an event to your function. Keep in mind that if you pass both `--path` and `--data`, the data included in the `--path` file will overwrite the data you passed with the `--data` flag.
+- `--raw` Pass data as a raw string even if it is JSON. If not set, JSON data are parsed and passed as an object.
## Examples
diff --git a/docs/providers/aws/events/README.md b/docs/providers/aws/events/README.md
index 376f6b7d1..8f2403e58 100644
--- a/docs/providers/aws/events/README.md
+++ b/docs/providers/aws/events/README.md
@@ -14,6 +14,6 @@ Welcome to the Serverless AWS Lambda Events Glossary!
Please select a section on the left to get started.
-If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://gitter.im/serverless/serverless)
+If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** Before continuing [AWS system credentials](../guide/credentials.md) are required for using the CLI.
diff --git a/docs/providers/aws/examples/README.md b/docs/providers/aws/examples/README.md
index 877c6d79b..853496698 100644
--- a/docs/providers/aws/examples/README.md
+++ b/docs/providers/aws/examples/README.md
@@ -28,4 +28,4 @@ Have an example? Submit a PR or [open an issue](https://github.com/serverless/ex
| [Serverless Data Pipeline](https://github.com/serverless/examples/tree/master/aws-node-text-analysis-via-sns-post-processing)
Example demonstrates how to setup a simple data processing pipeline | nodeJS |
| [Aws Python Simple Http Endpoint](https://github.com/serverless/examples/tree/master/aws-python-simple-http-endpoint)
Example demonstrates how to setup a simple HTTP GET endpoint with python | python |
-If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://gitter.im/serverless/serverless)
+If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
diff --git a/docs/providers/aws/guide/README.md b/docs/providers/aws/guide/README.md
index a30c1b13c..12835d123 100644
--- a/docs/providers/aws/guide/README.md
+++ b/docs/providers/aws/guide/README.md
@@ -14,6 +14,6 @@ Welcome to the Serverless AWS Lambda Guide!
Get started with the **[Introduction to the framework](./intro.md)**
-If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://gitter.im/serverless/serverless)
+If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** Before continuing [AWS system credentials](./credentials.md) are required for using the CLI.
diff --git a/docs/providers/aws/guide/credentials.md b/docs/providers/aws/guide/credentials.md
index 2c0e2da55..9bcf390b0 100644
--- a/docs/providers/aws/guide/credentials.md
+++ b/docs/providers/aws/guide/credentials.md
@@ -63,6 +63,8 @@ export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=
# AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are now available for serverless to use
serverless deploy
+
+# 'export' command is valid only for unix shells. In Windows - use 'set' instead of 'export'
```
#### Using AWS Profiles
@@ -130,7 +132,7 @@ The AWS region setting is to prevent issues with specific services, so adapt if
##### Using the `aws-profile` option
-You can always speficy the profile which should be used via the `aws-profile` option like this:
+You can always specify the profile which should be used via the `aws-profile` option like this:
```bash
serverless deploy --aws-profile devProfile
diff --git a/docs/providers/aws/guide/functions.md b/docs/providers/aws/guide/functions.md
index 305465162..b36791e4a 100644
--- a/docs/providers/aws/guide/functions.md
+++ b/docs/providers/aws/guide/functions.md
@@ -303,16 +303,18 @@ provider:
These versions are not cleaned up by serverless, so make sure you use a plugin or other tool to prune sufficiently old versions. The framework can't clean up versions because it doesn't have information about whether older versions are invoked or not. This feature adds to the number of total stack outputs and resources because a function version is a separate resource from the function it refers to.
-## DeadLetterConfig
+## Dead Letter Queue (DLQ)
-You can setup `DeadLetterConfig` with the help of a SNS topic and the `onError` config parameter.
+When AWS lambda functions fail, they are [retried](http://docs.aws.amazon.com/lambda/latest/dg/retries-on-errors.html). If the retries also fail, AWS has a feature to send information about the failed request to a SNS topic or SNS queue, called the [Dead Letter Queue](http://docs.aws.amazon.com/lambda/latest/dg/dlq.html), which you can use to track and diagnose and react to lambda failures.
-The SNS topic needs to be created beforehand and provided as an `arn` on the function level.
+You can setup a dead letter queue for your serverless functions with the help of a SNS topic and the `onError` config parameter.
**Note:** You can only provide one `onError` config per function.
### DLQ with SNS
+The SNS topic needs to be created beforehand and provided as an `arn` on the function level.
+
```yml
service: service
@@ -328,7 +330,7 @@ functions:
### DLQ with SQS
-The `onError` config currently only supports SNS topic arns due to a race condition when using SQS queue arns and updating the IAM role.
+Although Dead Letter Queues support both SNS topics and SQS queues, the `onError` config currently only supports SNS topic arns due to a race condition when using SQS queue arns and updating the IAM role.
We're working on a fix so that SQS queue arns will be supported in the future.
diff --git a/docs/providers/aws/guide/iam.md b/docs/providers/aws/guide/iam.md
index d8f22e243..19aacd6f3 100644
--- a/docs/providers/aws/guide/iam.md
+++ b/docs/providers/aws/guide/iam.md
@@ -169,7 +169,14 @@ resources:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- Resource: arn:aws:logs:${region}:${accountId}:log-group:/aws/lambda/*:*:*
+ Resource:
+ - 'Fn::Join':
+ - ':'
+ -
+ - 'arn:aws:logs'
+ - Ref: 'AWS::Region'
+ - Ref: 'AWS::AccountId'
+ - 'log-group:/aws/lambda/*:*:*'
- Effect: Allow
Action:
- ec2:CreateNetworkInterface
@@ -200,7 +207,14 @@ resources:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- Resource: arn:aws:logs:${region}:${accountId}:log-group:/aws/lambda/*:*:*
+ Resource:
+ - 'Fn::Join':
+ - ':'
+ -
+ - 'arn:aws:logs'
+ - Ref: 'AWS::Region'
+ - Ref: 'AWS::AccountId'
+ - 'log-group:/aws/lambda/*:*:*'
- Effect: "Allow"
Action:
- "s3:PutObject"
@@ -252,7 +266,14 @@ resources:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- Resource: arn:aws:logs:${region}:${accountId}:log-group:/aws/lambda/*:*:*
+ Resource:
+ - 'Fn::Join':
+ - ':'
+ -
+ - 'arn:aws:logs'
+ - Ref: 'AWS::Region'
+ - Ref: 'AWS::AccountId'
+ - 'log-group:/aws/lambda/*:*:*'
- Effect: "Allow"
Action:
- "s3:PutObject"
@@ -284,7 +305,14 @@ resources:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- Resource: arn:aws:logs:${region}:${accountId}:log-group:/aws/lambda/*:*:*
+ Resource:
+ - 'Fn::Join':
+ - ':'
+ -
+ - 'arn:aws:logs'
+ - Ref: 'AWS::Region'
+ - Ref: 'AWS::AccountId'
+ - 'log-group:/aws/lambda/*:*:*'
- Effect: Allow
Action:
- ec2:CreateNetworkInterface
diff --git a/docs/providers/aws/guide/installation.md b/docs/providers/aws/guide/installation.md
index 638117230..3b8806f6a 100644
--- a/docs/providers/aws/guide/installation.md
+++ b/docs/providers/aws/guide/installation.md
@@ -20,7 +20,7 @@ Go to the official [Node.js website](https://nodejs.org), download and follow th
**Note:** Serverless runs on Node v4 or higher.
-You can verify that Node.js is installed successfully by runnning `node --version` in your terminal. You should see the corresponding Node version number printed out.
+You can verify that Node.js is installed successfully by running `node --version` in your terminal. You should see the corresponding Node version number printed out.
### Installing the Serverless Framework
diff --git a/docs/providers/aws/guide/quick-start.md b/docs/providers/aws/guide/quick-start.md
index db41d6b15..22bb04482 100644
--- a/docs/providers/aws/guide/quick-start.md
+++ b/docs/providers/aws/guide/quick-start.md
@@ -47,7 +47,7 @@ $ cd my-service
3. **Invoke the Function**
- Invokes an Function and returns logs.
+ Invokes a Function and returns logs.
```bash
serverless invoke -f hello -l
diff --git a/docs/providers/aws/guide/serverless.yml.md b/docs/providers/aws/guide/serverless.yml.md
index 8463439c1..93521b402 100644
--- a/docs/providers/aws/guide/serverless.yml.md
+++ b/docs/providers/aws/guide/serverless.yml.md
@@ -200,5 +200,6 @@ resources:
Description: The ARN for the User's Table
Value:
"Fn::GetAtt": [ usersTable, Arn ]
- Export: ${self:service}:${opt:stage}:UsersTableArn # see Fn::ImportValue to use in other services and http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html for documentation on use.
+ Export:
+ Name: ${self:service}:${opt:stage}:UsersTableArn # see Fn::ImportValue to use in other services and http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html for documentation on use.
```
diff --git a/docs/providers/aws/guide/services.md b/docs/providers/aws/guide/services.md
index 63a44b0c2..12c1389b8 100644
--- a/docs/providers/aws/guide/services.md
+++ b/docs/providers/aws/guide/services.md
@@ -37,7 +37,7 @@ comments/
```
This makes sense since related functions usually use common infrastructure resources, and you want to keep those functions and resources together as a single unit of deployment, for better organization and separation of concerns.
-**Note:** Currently, every service will create a separate REST API on AWS API Gateway. Due to a limitation with AWS API Gateway, you can only have a custom domain per one REST API. If you plan on making a large REST API, please make note of this limitation. Also, [a fix is in the works][https://github.com/serverless/serverless/issues/3078] and is a top priority.
+**Note:** Currently, every service will create a separate REST API on AWS API Gateway. Due to a limitation with AWS API Gateway, you can only have a custom domain per one REST API. If you plan on making a large REST API, please make note of this limitation. Also, [a fix is in the works](https://github.com/serverless/serverless/issues/3078) and is a top priority.
## Creation
@@ -51,6 +51,8 @@ serverless create --template aws-nodejs --path myService
Here are the available runtimes for AWS Lambda:
* aws-nodejs
+* aws-nodejs-typescript
+* aws-nodejs-ecma-script
* aws-python
* aws-python3
* aws-groovy-gradle
@@ -160,7 +162,13 @@ Create this file and add event data so you can invoke your function with the dat
When you deploy a Service, all of the Functions, Events and Resources in your `serverless.yml` are translated to an AWS CloudFormation template and deployed as a single CloudFormation stack.
-To deploy a service, use the `deploy` command:
+To deploy a service, first `cd` into the relevant service directory:
+
+```bash
+cd my-service
+```
+
+Then use the `deploy` command:
```bash
serverless deploy
diff --git a/docs/providers/aws/guide/variables.md b/docs/providers/aws/guide/variables.md
index 81fb19116..9c52bd496 100644
--- a/docs/providers/aws/guide/variables.md
+++ b/docs/providers/aws/guide/variables.md
@@ -123,8 +123,9 @@ functions:
handler: handler.hello
```
In the above example, the value for `myKey` in the `myBucket` S3 bucket will be looked up and used to populate the variable.
-## Reference Variables in Other Files
-To reference variables in other YAML or JSON files, use the `${file(./myFile.yml):someProperty}` syntax in your `serverless.yml` configuration file. This functionality is recursive, so you can go as deep in that file as you want. Here's an example:
+
+## Reference Variables in other Files
+You can reference variables in other YAML or JSON files. To reference variables in other YAML files use the `${file(./myFile.yml):someProperty}` syntax in your `serverless.yml` configuration file. To reference variables in other JSON files use the `${file(./myFile.json):someProperty}` syntax. It is important that the file you are referencing has the correct suffix, or file extension, for its file type (`.yml` for YAML or `.json` for JSON) in order for it to be interpreted correctly. Here's an example:
```yml
# myCustomFile.yml
@@ -147,7 +148,43 @@ functions:
- schedule: ${self:custom.globalSchedule} # This would also work in this case
```
-In the above example, you're referencing the entire `myCustomFile.yml` file in the `custom` property. You need to pass the path relative to your service directory. You can also request specific properties in that file as shown in the `schedule` property. It's completely recursive and you can go as deep as you want.
+In the above example, you're referencing the entire `myCustomFile.yml` file in the `custom` property. You need to pass the path relative to your service directory. You can also request specific properties in that file as shown in the `schedule` property. It's completely recursive and you can go as deep as you want. Additionally you can request properties that contain arrays from either YAML or JSON reference files. Here's a YAML example for an events array:
+
+```yml
+myevents:
+ - schedule:
+ rate: rate(1 minute)
+```
+
+and for JSON:
+
+```json
+{
+ "myevents": [{
+ "schedule" : {
+ "rate" : "rate(1 minute)"
+ }
+ }]
+}
+```
+
+In your `serverless.yml`, depending on the type of your source file, either have the following syntax for YAML:
+
+```yml
+functions:
+ hello:
+ handler: handler.hello
+ events: ${file(./myCustomFile.yml):myevents
+```
+
+or for a JSON reference file use this sytax:
+
+```yml
+functions:
+ hello:
+ handler: handler.hello
+ events: ${file(./myCustomFile.json):myevents
+```
## Reference Variables in Javascript Files
@@ -273,6 +310,7 @@ provider:
stage: dev
custom:
myStage: ${opt:stage, self:provider.stage}
+ myRegion: ${opt:region, 'us-west-1'}
functions:
hello:
@@ -292,7 +330,7 @@ service: new-service
provider:
name: aws
runtime: nodejs6.10
- variableSyntax: "\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}" # notice the double quotes for yaml to ignore the escape characters!
+ variableSyntax: "\\${([ ~:a-zA-Z0-9._\'\",\\-\\/\\(\\)]+?)}" # notice the double quotes for yaml to ignore the escape characters!
custom:
myStage: ${{opt:stage}}
diff --git a/docs/providers/azure/README.md b/docs/providers/azure/README.md
index dc2567e71..d0f7300f7 100644
--- a/docs/providers/azure/README.md
+++ b/docs/providers/azure/README.md
@@ -12,7 +12,7 @@ layout: Doc
Welcome to the Serverless Azure Functions documentation!
-If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://gitter.im/serverless/serverless)
+If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** [Azure Functions system credentials](./guide/credentials.md) are required for using serverless + Azure Functions.
diff --git a/docs/providers/azure/examples/README.md b/docs/providers/azure/examples/README.md
index 9fdd3e918..6fe0e1756 100644
--- a/docs/providers/azure/examples/README.md
+++ b/docs/providers/azure/examples/README.md
@@ -16,4 +16,4 @@ Have an example? Submit a PR or [open an issue](https://github.com/serverless/ex
|:--------------------------- |:-----|
| [azure Node Simple](https://github.com/serverless/examples/tree/master/azure-node-simple-http-endpoint)
Boilerplate project repository for Azure provider with Serverless Framework. | nodeJS |
-If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](http://forum.serverless.com/)
+If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
diff --git a/docs/providers/azure/guide/services.md b/docs/providers/azure/guide/services.md
index e00dda5a0..1ab4bdbe6 100644
--- a/docs/providers/azure/guide/services.md
+++ b/docs/providers/azure/guide/services.md
@@ -115,7 +115,13 @@ When you deploy a Service, all of the Functions, and Events in your
`serverless.yml` are translated into calls to the platform API to dynamically
define those resources.
-To deploy a service, use the `deploy` command:
+To deploy a service, first `cd` into the relevant service directory:
+
+```bash
+cd my-service
+```
+
+Then use the `deploy` command:
```bash
serverless deploy
diff --git a/docs/providers/azure/guide/variables.md b/docs/providers/azure/guide/variables.md
index dae754aac..c442994c3 100644
--- a/docs/providers/azure/guide/variables.md
+++ b/docs/providers/azure/guide/variables.md
@@ -41,19 +41,78 @@ custom:
functions:
hello:
- handler: handler.hello
- events:
- - timer: ${self:custom.globalSchedule}
+ handler: handler.hello
+ events:
+ - timer: ${self:custom.globalSchedule}
world:
- handler: handler.world
- events:
- - timer: ${self:custom.globalSchedule}
+ handler: handler.world
+ events:
+ - timer: ${self:custom.globalSchedule}
```
In the above example you're setting a global schedule for all functions by
referencing the `globalSchedule` property in the same `serverless.yml` file. This
way, you can easily change the schedule for all functions whenever you like.
+## Reference Variables in other Files
+You can reference variables in other YAML or JSON files. To reference variables in other YAML files use the `${file(./myFile.yml):someProperty}` syntax in your `serverless.yml` configuration file. To reference variables in other JSON files use the `${file(./myFile.json):someProperty}` syntax. It is important that the file you are referencing has the correct suffix, or file extension, for its file type (`.yml` for YAML or `.json` for JSON) in order for it to be interpreted correctly. Here's an example:
+
+```yml
+# myCustomFile.yml
+cron: cron(0 * * * *)
+```
+
+```yml
+# serverless.yml
+service: new-service
+provider: azure
+
+custom: ${file(./myCustomFile.yml)} # You can reference the entire file
+
+functions:
+ hello:
+ handler: handler.hello
+ events:
+ - timer: ${file(./myCustomFile.yml):cron} # Or you can reference a specific property
+ world:
+ handler: handler.world
+ events:
+ - timer: ${self:custom.cron} # This would also work in this case
+```
+
+
+In the above example, you're referencing the entire `myCustomFile.yml` file in the `custom` property. You need to pass the path relative to your service directory. You can also request specific properties in that file as shown in the `cron` property. It's completely recursive and you can go as deep as you want. Additionally you can request properties that contain arrays from either YAML or JSON reference files. Here's a YAML example for an events array:
+
+```yml
+myevents:
+ - timer: cron(0 * * * *)
+```
+
+and for JSON:
+```json
+{
+ "myevents": [{
+ "timer" : "cron(0 * * * *)"
+ }]
+}
+```
+
+In your serverless.yml, depending on the type of your source file, either have the following syntax for YAML
+```yml
+functions:
+ hello:
+ handler: handler.hello
+ events: ${file(./myCustomFile.yml):myevents
+```
+
+or for a JSON reference file use this sytax:
+```yml
+functions:
+ hello:
+ handler: handler.hello
+ events: ${file(./myCustomFile.json):myevents
+```
+
## Reference Variables in JavaScript Files
You can reference JavaScript files to add dynamic data into your variables.
diff --git a/docs/providers/google/README.md b/docs/providers/google/README.md
index 1029653d3..5010a5b41 100644
--- a/docs/providers/google/README.md
+++ b/docs/providers/google/README.md
@@ -12,7 +12,7 @@ layout: Doc
Welcome to the Serverless Google Cloud Functions documentation!
-If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://gitter.im/serverless/serverless)
+If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** [Google Cloud system credentials](./guide/credentials.md) are required for using the CLI.
diff --git a/docs/providers/google/examples/README.md b/docs/providers/google/examples/README.md
index e30465174..e6a791dee 100644
--- a/docs/providers/google/examples/README.md
+++ b/docs/providers/google/examples/README.md
@@ -16,4 +16,4 @@ Have an example? Submit a PR or [open an issue](https://github.com/serverless/ex
|:--------------------------- |:-----|
| [Google Node Simple](https://github.com/serverless/examples/tree/master/google-node-simple-http-endpoint)
Boilerplate project repository for Google Cloud provider with Serverless Framework. | nodeJS |
-If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](http://forum.serverless.com/)
+If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
diff --git a/docs/providers/google/guide/installation.md b/docs/providers/google/guide/installation.md
index 7660ca087..914c7d1c4 100644
--- a/docs/providers/google/guide/installation.md
+++ b/docs/providers/google/guide/installation.md
@@ -18,7 +18,7 @@ Serverless is a [Node.js](https://nodejs.org) CLI tool so the first thing you ne
Go to the official [Node.js website](https://nodejs.org), download and follow the [installation instructions](https://nodejs.org/en/download/) to install Node.js on your local machine.
-You can verify that Node.js is installed successfully by runnning `node --version` in your terminal. You should see the corresponding Node version number printed out.
+You can verify that Node.js is installed successfully by running `node --version` in your terminal. You should see the corresponding Node version number printed out.
### Installing the Serverless Framework
diff --git a/docs/providers/google/guide/services.md b/docs/providers/google/guide/services.md
index ccfd1239a..44d32d894 100644
--- a/docs/providers/google/guide/services.md
+++ b/docs/providers/google/guide/services.md
@@ -100,7 +100,13 @@ The `index.js` file contains your exported functions.
When you deploy a Service, all of the Functions, and Events in your `serverless.yml` are translated into calls to the Google Cloud API to dynamically define those resources.
-To deploy a service, use the `deploy` command:
+To deploy a service, first `cd` into the relevant service directory:
+
+```bash
+cd my-service
+```
+
+Then use the `deploy` command:
```bash
serverless deploy
diff --git a/docs/providers/google/guide/variables.md b/docs/providers/google/guide/variables.md
index 95d51d105..e55cdb2f2 100644
--- a/docs/providers/google/guide/variables.md
+++ b/docs/providers/google/guide/variables.md
@@ -50,6 +50,72 @@ functions:
In the above example you're setting a global event resource for all functions by referencing the `resource` property in the same `serverless.yml` file. This way, you can easily change the event resource for all functions whenever you like.
+## Reference Variables in other Files
+You can reference variables in other YAML or JSON files. To reference variables in other YAML files use the `${file(./myFile.yml):someProperty}` syntax in your `serverless.yml` configuration file. To reference variables in other JSON files use the `${file(./myFile.json):someProperty}` syntax. It is important that the file you are referencing has the correct suffix, or file extension, for its file type (`.yml` for YAML or `.json` for JSON) in order for it to be interpreted correctly. Here's an example:
+
+```yml
+# myCustomFile.yml
+topic: projects/*/topics/my-topic
+```
+
+```yml
+# serverless.yml
+service: new-service
+provider: google
+
+custom: ${file(./myCustomFile.yml)} # You can reference the entire file
+
+functions:
+ hello:
+ handler: pubSub.hello
+ events:
+ - event:
+ eventType: providers/cloud.pubsub/eventTypes/topics.publish
+ resource: ${file(./myCustomFile.yml):topic} # Or you can reference a specific property
+ world:
+ handler: pubSub.hello
+ events:
+ eventType: providers/cloud.pubsub/eventTypes/topics.publish
+ resource: ${self:custom.topic} # This would also work in this case
+```
+
+In the above example, you're referencing the entire `myCustomFile.yml` file in the `custom` property. You need to pass the path relative to your service directory. You can also request specific properties in that file as shown in the `topic` property. It's completely recursive and you can go as deep as you want. Additionally you can request properties that contain arrays from either YAML or JSON reference files. Here's a YAML example for an events array:
+
+```yml
+myevents:
+ - event:
+ eventType: providers/cloud.pubsub/eventTypes/topic.publish
+ resource: projects/*/topics/my-topic
+```
+
+and for JSON:
+```json
+{
+ "myevents": [{
+ "event" : {
+ "eventType": "providers/cloud.pubsub/eventTypes/topic.publish",
+ "resource" : "projects/*/topics/my-topic"
+ }
+ }]
+}
+```
+
+In your serverless.yml, depending on the type of your source file, either have the following syntax for YAML
+```yml
+functions:
+ hello:
+ handler: pubSub.hello
+ events: ${file(./myCustomFile.yml):myevents
+```
+
+or for a JSON reference file use this sytax:
+```yml
+functions:
+ hello:
+ handler: pubSub.hello
+ events: ${file(./myCustomFile.json):myevents
+```
+
## Reference Variables in JavaScript Files
You can reference JavaScript files to add dynamic data into your variables.
diff --git a/docs/providers/openwhisk/README.md b/docs/providers/openwhisk/README.md
index 99998aa29..e09360f45 100644
--- a/docs/providers/openwhisk/README.md
+++ b/docs/providers/openwhisk/README.md
@@ -12,7 +12,7 @@ layout: Doc
Welcome to the Serverless Apache OpenWhisk documentation!
-If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://gitter.im/serverless/serverless)
+If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** [Apache OpenWhisk system credentials](./guide/credentials.md) are required for using serverless + openwhisk.
diff --git a/docs/providers/openwhisk/examples/README.md b/docs/providers/openwhisk/examples/README.md
index 059bbc95e..8325ef375 100644
--- a/docs/providers/openwhisk/examples/README.md
+++ b/docs/providers/openwhisk/examples/README.md
@@ -18,4 +18,4 @@ Have an example? Submit a PR or [open an issue](https://github.com/serverless/ex
| [OpenWhisk Python Simple](https://github.com/serverless/examples/tree/master/openwhisk-python-simple)
Boilerplate project repository for OpenWhisk provider with Serverless Framework. | python |
| [OpenWhisk Swift Simple](https://github.com/serverless/examples/tree/master/openwhisk-swift-simple)
Boilerplate project repository for OpenWhisk provider with Serverless Framework. | swift |
-If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](http://forum.serverless.com/)
+If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
diff --git a/docs/providers/openwhisk/guide/installation.md b/docs/providers/openwhisk/guide/installation.md
index cab867e69..627f7f6d4 100644
--- a/docs/providers/openwhisk/guide/installation.md
+++ b/docs/providers/openwhisk/guide/installation.md
@@ -20,7 +20,7 @@ Go to the official [Node.js website](https://nodejs.org), download and follow th
**Note:** Serverless runs on Node v4 or higher.
-You can verify that Node.js is installed successfully by runnning `node --version` in your terminal. You should see the corresponding Node version number printed out.
+You can verify that Node.js is installed successfully by running `node --version` in your terminal. You should see the corresponding Node version number printed out.
### Installing the Serverless Framework
diff --git a/docs/providers/openwhisk/guide/services.md b/docs/providers/openwhisk/guide/services.md
index 563855927..ae8de4b02 100644
--- a/docs/providers/openwhisk/guide/services.md
+++ b/docs/providers/openwhisk/guide/services.md
@@ -107,7 +107,13 @@ Create this file and add event data so you can invoke your function with the dat
When you deploy a Service, all of the Functions, Events and Resources in your `serverless.yml` are translated into calls to the platform API to dynamically define those resources.
-To deploy a service, use the `deploy` command:
+To deploy a service, first `cd` into the relevant service directory:
+
+```bash
+cd my-service
+```
+
+Then use the `deploy` command:
```bash
serverless deploy
diff --git a/docs/providers/openwhisk/guide/variables.md b/docs/providers/openwhisk/guide/variables.md
index eb7d60b97..8219a7fad 100644
--- a/docs/providers/openwhisk/guide/variables.md
+++ b/docs/providers/openwhisk/guide/variables.md
@@ -79,8 +79,8 @@ functions:
In the above example, you're dynamically adding a prefix to the function names by referencing the `stage` option that you pass in the CLI when you run `serverless deploy --stage dev`. So when you deploy, the function name will always include the stage you're deploying to.
-## Reference Variables in Other Files
-To reference variables in other YAML or JSON files, use the `${file(./myFile.yml):someProperty}` syntax in your `serverless.yml` configuration file. This functionality is recursive, so you can go as deep in that file as you want. Here's an example:
+## Reference Variables in other Files
+To reference variables in other YAML or JSON files, use the `${file(./myFile.yml):someProperty}` syntax in your `serverless.yml` configuration file. Here's an example:
```yml
# myCustomFile.yml
@@ -103,7 +103,37 @@ functions:
- schedule: ${self:custom.globalSchedule} # This would also work in this case
```
-In the above example, you're referencing the entire `myCustomFile.yml` file in the `custom` property. You need to pass the path relative to your service directory. You can also request specific properties in that file as shown in the `schedule` property. It's completely recursive and you can go as deep as you want.
+In the above example, you're referencing the entire `myCustomFile.yml` file in the `custom` property. You need to pass the path relative to your service directory. You can also request specific properties in that file as shown in the `schedule` property. It's completely recursive and you can go as deep as you want. Additionally you can request properties that contain arrays from either YAML or JSON reference files. Here's a YAML example for an events array:
+
+```yml
+myevents:
+ - schedule: cron(0 * * * *)
+```
+
+and for JSON:
+```json
+{
+ "myevents": [{
+ "schedule" : "cron(0 * * * *)"
+ }]
+}
+```
+
+In your serverless.yml, depending on the type of your source file, either have the following syntax for YAML
+```yml
+functions:
+ hello:
+ handler: handler.hello
+ events: ${file(./myCustomFile.yml):myevents
+```
+
+or for a JSON reference file use this sytax:
+```yml
+functions:
+ hello:
+ handler: handler.hello
+ events: ${file(./myCustomFile.json):myevents
+```
## Reference Variables in Javascript Files
diff --git a/lib/classes/CLI.js b/lib/classes/CLI.js
index 594d2279b..4a186a1a5 100644
--- a/lib/classes/CLI.js
+++ b/lib/classes/CLI.js
@@ -120,24 +120,54 @@ class CLI {
}
generateMainHelp() {
+ let platformCommands;
+ let frameworkCommands;
+ if (this.loadedCommands) {
+ const commandKeys = Object.keys(this.loadedCommands);
+ const sortedCommandKeys = _.sortBy(commandKeys);
+ const partitionedCommandKeys = _.partition(sortedCommandKeys,
+ (key) => this.loadedCommands[key].platform);
+ platformCommands = _.fromPairs(
+ _.map(partitionedCommandKeys[0], key => [key, this.loadedCommands[key]])
+ );
+ frameworkCommands = _.fromPairs(
+ _.map(partitionedCommandKeys[1], key => [key, this.loadedCommands[key]])
+ );
+ }
+
this.consoleLog('');
this.consoleLog(chalk.yellow.underline('Commands'));
- this.consoleLog(chalk.dim('* Serverless documentation: http://docs.serverless.com'));
this.consoleLog(chalk.dim('* You can run commands with "serverless" or the shortcut "sls"'));
this.consoleLog(chalk.dim('* Pass "--verbose" to this command to get in-depth plugin info'));
this.consoleLog(chalk.dim('* Pass "--help" after any for contextual help'));
this.consoleLog('');
- if (this.loadedCommands) {
- const commandKeys = Object.keys(this.loadedCommands);
- const sortedCommandKeys = _.sortBy(commandKeys);
- const sortedCommands = _.fromPairs(
- _.map(sortedCommandKeys, key => [key, this.loadedCommands[key]])
- );
+ this.consoleLog(chalk.yellow.underline('Framework'));
+ this.consoleLog(chalk.dim('* Documentation: https://serverless.com/framework/docs/'));
- _.forEach(sortedCommands, (details, command) => {
+ this.consoleLog('');
+
+ if (!_.isEmpty(frameworkCommands)) {
+ _.forEach(frameworkCommands, (details, command) => {
+ this.displayCommandUsage(details, command);
+ });
+ } else {
+ this.consoleLog('No commands found');
+ }
+
+ this.consoleLog('');
+
+ this.consoleLog(chalk.yellow.underline('Platform (Beta)'));
+ // eslint-disable-next-line max-len
+ this.consoleLog(chalk.dim('* The Serverless Platform is currently in experimental beta. Follow the docs below to get started.'));
+ this.consoleLog(chalk.dim('* Documentation: https://serverless.com/platform/docs/'));
+
+ this.consoleLog('');
+
+ if (!_.isEmpty(platformCommands)) {
+ _.forEach(platformCommands, (details, command) => {
this.displayCommandUsage(details, command);
});
} else {
diff --git a/lib/classes/PluginManager.js b/lib/classes/PluginManager.js
index d32efc31c..7001cc9c7 100644
--- a/lib/classes/PluginManager.js
+++ b/lib/classes/PluginManager.js
@@ -71,6 +71,11 @@ class PluginManager {
this.addPlugin(Plugin);
} catch (error) {
+ // Rethrow the original error in case we're in debug mode.
+ if (process.env.SLS_DEBUG) {
+ throw error;
+ }
+
const errorMessage = [
`Serverless plugin "${plugin}" not found.`,
' Make sure it\'s installed and listed in the "plugins" section',
diff --git a/lib/classes/PluginManager.test.js b/lib/classes/PluginManager.test.js
index 5211df188..bab03ad66 100644
--- a/lib/classes/PluginManager.test.js
+++ b/lib/classes/PluginManager.test.js
@@ -6,6 +6,7 @@ const Serverless = require('../../lib/Serverless');
const CLI = require('../../lib/classes/CLI');
const Create = require('../../lib/plugins/create/create');
+const _ = require('lodash');
const path = require('path');
const fs = require('fs');
const fse = require('fs-extra');
@@ -26,6 +27,12 @@ describe('PluginManager', () => {
class ServicePluginMock2 {}
+ class BrokenPluginMock {
+ constructor() {
+ throw new Error('Broken plugin');
+ }
+ }
+
class Provider1PluginMock {
constructor() {
this.provider = 'provider1';
@@ -528,6 +535,7 @@ describe('PluginManager', () => {
describe('#loadPlugins()', () => {
beforeEach(() => {
mockRequire('ServicePluginMock1', ServicePluginMock1);
+ mockRequire('BrokenPluginMock', BrokenPluginMock);
});
it('should throw an error when trying to load unknown plugin', () => {
@@ -549,6 +557,26 @@ describe('PluginManager', () => {
expect(consoleLogStub.calledOnce).to.equal(true);
});
+ it('should throw an error when trying to load a broken plugin (without SLS_DEBUG)', () => {
+ const servicePlugins = ['BrokenPluginMock'];
+
+ expect(() => pluginManager.loadPlugins(servicePlugins))
+ .to.throw(serverless.classes.Error);
+ });
+
+ it('should forward any errors when trying to load a broken plugin (with SLS_DEBUG)', () => {
+ const servicePlugins = ['BrokenPluginMock'];
+
+ return BbPromise.try(() => {
+ _.set(process.env, 'SLS_DEBUG', '*');
+ expect(() => pluginManager.loadPlugins(servicePlugins))
+ .to.throw(/Broken plugin/);
+ })
+ .finally(() => {
+ _.unset(process.env, 'SLS_DEBUG');
+ });
+ });
+
afterEach(() => {
mockRequire.stop('ServicePluginMock1');
});
diff --git a/lib/classes/Service.js b/lib/classes/Service.js
index 40d13e7be..c69686c81 100644
--- a/lib/classes/Service.js
+++ b/lib/classes/Service.js
@@ -16,7 +16,7 @@ class Service {
this.provider = {
stage: 'dev',
region: 'us-east-1',
- variableSyntax: '\\${([ ~:a-zA-Z0-9._,\\-\\/\\(\\)]+?)}',
+ variableSyntax: '\\${([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}',
};
this.custom = {};
this.plugins = [];
diff --git a/lib/classes/Service.test.js b/lib/classes/Service.test.js
index df73074f3..44981dca1 100644
--- a/lib/classes/Service.test.js
+++ b/lib/classes/Service.test.js
@@ -31,7 +31,7 @@ describe('Service', () => {
expect(serviceInstance.provider).to.deep.equal({
stage: 'dev',
region: 'us-east-1',
- variableSyntax: '\\${([ ~:a-zA-Z0-9._,\\-\\/\\(\\)]+?)}',
+ variableSyntax: '\\${([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}',
});
expect(serviceInstance.custom).to.deep.equal({});
expect(serviceInstance.plugins).to.deep.equal([]);
@@ -131,7 +131,7 @@ describe('Service', () => {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
- variableSyntax: '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}',
+ variableSyntax: '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}',
},
plugins: ['testPlugin'],
functions: {
@@ -165,7 +165,7 @@ describe('Service', () => {
expect(serviceInstance.service).to.be.equal('new-service');
expect(serviceInstance.provider.name).to.deep.equal('aws');
expect(serviceInstance.provider.variableSyntax).to.equal(
- '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}'
+ '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}'
);
expect(serviceInstance.plugins).to.deep.equal(['testPlugin']);
expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' });
@@ -188,7 +188,7 @@ describe('Service', () => {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
- variableSyntax: '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}',
+ variableSyntax: '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}',
},
plugins: ['testPlugin'],
functions: {
@@ -221,7 +221,7 @@ describe('Service', () => {
expect(serviceInstance.service).to.be.equal('new-service');
expect(serviceInstance.provider.name).to.deep.equal('aws');
expect(serviceInstance.provider.variableSyntax).to.equal(
- '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}'
+ '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}'
);
expect(serviceInstance.plugins).to.deep.equal(['testPlugin']);
expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' });
@@ -244,7 +244,7 @@ describe('Service', () => {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
- variableSyntax: '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}',
+ variableSyntax: '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}',
},
plugins: ['testPlugin'],
functions: {
@@ -277,7 +277,7 @@ describe('Service', () => {
expect(serviceInstance.service).to.be.equal('new-service');
expect(serviceInstance.provider.name).to.deep.equal('aws');
expect(serviceInstance.provider.variableSyntax).to.equal(
- '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}'
+ '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}'
);
expect(serviceInstance.plugins).to.deep.equal(['testPlugin']);
expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' });
@@ -299,7 +299,7 @@ describe('Service', () => {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
- variableSyntax: '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}',
+ variableSyntax: '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}',
},
plugins: ['testPlugin'],
functions: {
@@ -712,7 +712,7 @@ describe('Service', () => {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
- variableSyntax: '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}',
+ variableSyntax: '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}',
},
plugins: ['testPlugin'],
functions: {
diff --git a/lib/classes/Utils.js b/lib/classes/Utils.js
index 52f2c35d5..7c01b147c 100644
--- a/lib/classes/Utils.js
+++ b/lib/classes/Utils.js
@@ -10,7 +10,7 @@ const fileExistsSync = require('../utils/fs/fileExistsSync');
const writeFileSync = require('../utils/fs/writeFileSync');
const readFileSync = require('../utils/fs/readFileSync');
const walkDirSync = require('../utils/fs/walkDirSync');
-const isDockerContainer = require('../utils/isDockerContainer');
+const isDockerContainer = require('is-docker');
const version = require('../../package.json').version;
const segment = require('../utils/segment');
const configUtils = require('../utils/config');
@@ -256,7 +256,7 @@ class Utils {
}
let hasCustomVariableSyntaxDefined = false;
- const defaultVariableSyntax = '\\${([ ~:a-zA-Z0-9._,\\-\\/\\(\\)]+?)}';
+ const defaultVariableSyntax = '\\${([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}';
// check if the variableSyntax in the provider section is defined
if (provider && provider.variableSyntax
diff --git a/lib/classes/Utils.test.js b/lib/classes/Utils.test.js
index ede2a2790..bb54ec7b3 100644
--- a/lib/classes/Utils.test.js
+++ b/lib/classes/Utils.test.js
@@ -10,21 +10,15 @@ const testUtils = require('../../tests/utils');
const configUtils = require('../utils/config');
const serverlessVersion = require('../../package.json').version;
const segment = require('../utils/segment');
-const proxyquire = require('proxyquire');
chai.use(require('chai-as-promised'));
const expect = require('chai').expect;
+const Utils = require('../../lib/classes/Utils');
describe('Utils', () => {
let utils;
let serverless;
- let isDockerContainerStub;
- let Utils;
beforeEach(() => {
- isDockerContainerStub = sinon.stub().returns(true);
- Utils = proxyquire('../../lib/classes/Utils.js', {
- '../utils/isDockerContainer': isDockerContainerStub,
- });
serverless = new Serverless();
utils = new Utils(serverless);
serverless.init();
@@ -363,22 +357,6 @@ describe('Utils', () => {
});
});
- it('should be able to detect Docker containers', () => {
- getConfigStub.returns({
- trackingDisabled: false,
- frameworkId: '1234wasd',
- });
-
- return expect(utils.logStat(serverless)).to.be.fulfilled.then(() => {
- expect(getConfigStub.calledOnce).to.equal(true);
- expect(isDockerContainerStub.calledOnce).to.equal(true);
- expect(trackStub.calledOnce).to.equal(true);
-
- const data = trackStub.args[0][0];
- expect(data.properties.general.isDockerContainer).to.equal(true);
- });
- });
-
it('should be able to detect IAM Authorizers using the authorizer string format', () => {
getConfigStub.returns({
trackingDisabled: false,
diff --git a/lib/classes/Variables.js b/lib/classes/Variables.js
index 567974abd..d68cc2b90 100644
--- a/lib/classes/Variables.js
+++ b/lib/classes/Variables.js
@@ -19,7 +19,8 @@ class Variables {
this.optRefSyntax = RegExp(/^opt:/g);
this.selfRefSyntax = RegExp(/^self:/g);
this.cfRefSyntax = RegExp(/^cf:/g);
- this.s3RefSynax = RegExp(/^s3:(.+?)\/(.+)$/);
+ this.s3RefSyntax = RegExp(/^s3:(.+?)\/(.+)$/);
+ this.stringRefSynax = RegExp(/('.*')|(".*")/g);
}
loadVariableSyntax() {
@@ -174,8 +175,10 @@ class Variables {
return this.getValueFromFile(variableString);
} else if (variableString.match(this.cfRefSyntax)) {
return this.getValueFromCf(variableString);
- } else if (variableString.match(this.s3RefSynax)) {
+ } else if (variableString.match(this.s3RefSyntax)) {
return this.getValueFromS3(variableString);
+ } else if (variableString.match(this.stringRefSynax)) {
+ return this.getValueFromString(variableString);
}
const errorMessage = [
`Invalid variable reference syntax for variable ${variableString}.`,
@@ -196,6 +199,11 @@ class Variables {
return BbPromise.resolve(valueToPopulate);
}
+ getValueFromString(variableString) {
+ const valueToPopulate = variableString.replace(/'/g, '');
+ return BbPromise.resolve(valueToPopulate);
+ }
+
getValueFromOptions(variableString) {
const requestedOption = variableString.split(':')[1];
let valueToPopulate;
@@ -325,7 +333,7 @@ class Variables {
}
getValueFromS3(variableString) {
- const groups = variableString.match(this.s3RefSynax);
+ const groups = variableString.match(this.s3RefSyntax);
const bucket = groups[1];
const key = groups[2];
return this.serverless.getProvider('aws')
diff --git a/lib/classes/Variables.test.js b/lib/classes/Variables.test.js
index e4b9db61a..bf4d5b82e 100644
--- a/lib/classes/Variables.test.js
+++ b/lib/classes/Variables.test.js
@@ -33,7 +33,7 @@ describe('Variables', () => {
it('should set variableSyntax', () => {
const serverless = new Serverless();
- serverless.service.provider.variableSyntax = '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}';
+ serverless.service.provider.variableSyntax = '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}';
serverless.variables.loadVariableSyntax();
expect(serverless.variables.variableSyntax).to.be.a('RegExp');
@@ -56,7 +56,7 @@ describe('Variables', () => {
it('should use variableSyntax', () => {
const serverless = new Serverless();
- const variableSyntax = '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}';
+ const variableSyntax = '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}';
const fooValue = '${clientId()}';
const barValue = 'test';
@@ -157,6 +157,50 @@ describe('Variables', () => {
});
});
+ it('should allow a single-quoted string if overwrite syntax provided', () => {
+ const serverless = new Serverless();
+ const property = "my stage is ${opt:stage, 'prod'}";
+
+ serverless.variables.loadVariableSyntax();
+
+ const overwriteStub = sinon
+ .stub(serverless.variables, 'overwrite').resolves('\'prod\'');
+ const populateVariableStub = sinon
+ .stub(serverless.variables, 'populateVariable').resolves('my stage is prod');
+
+ return serverless.variables.populateProperty(property).then(newProperty => {
+ expect(overwriteStub.called).to.equal(true);
+ expect(populateVariableStub.called).to.equal(true);
+ expect(newProperty).to.equal('my stage is prod');
+
+ serverless.variables.overwrite.restore();
+ serverless.variables.populateVariable.restore();
+ return BbPromise.resolve();
+ });
+ });
+
+ it('should allow a double-quoted string if overwrite syntax provided', () => {
+ const serverless = new Serverless();
+ const property = 'my stage is ${opt:stage, "prod"}';
+
+ serverless.variables.loadVariableSyntax();
+
+ const overwriteStub = sinon
+ .stub(serverless.variables, 'overwrite').resolves('\'prod\'');
+ const populateVariableStub = sinon
+ .stub(serverless.variables, 'populateVariable').resolves('my stage is prod');
+
+ return serverless.variables.populateProperty(property).then(newProperty => {
+ expect(overwriteStub.called).to.equal(true);
+ expect(populateVariableStub.called).to.equal(true);
+ expect(newProperty).to.equal('my stage is prod');
+
+ serverless.variables.overwrite.restore();
+ serverless.variables.populateVariable.restore();
+ return BbPromise.resolve();
+ });
+ });
+
it('should call getValueFromSource if no overwrite syntax provided', () => {
const serverless = new Serverless();
const property = 'my stage is ${opt:stage}';
diff --git a/lib/plugins/Plugins.json b/lib/plugins/Plugins.json
index 0346b2ddb..58a0acdfb 100644
--- a/lib/plugins/Plugins.json
+++ b/lib/plugins/Plugins.json
@@ -1,5 +1,6 @@
{
"plugins": [
+ "./run/index.js",
"./config/config.js",
"./create/create.js",
"./install/install.js",
@@ -15,6 +16,7 @@
"./rollback/index.js",
"./slstats/slstats.js",
"./plugin/plugin.js",
+ "./emit/index.js",
"./aws/configCredentials/awsConfigCredentials.js",
"./aws/provider/awsProvider.js",
"./aws/common/index.js",
diff --git a/lib/plugins/aws/configCredentials/awsConfigCredentials.js b/lib/plugins/aws/configCredentials/awsConfigCredentials.js
index 066018a96..4e5906bae 100644
--- a/lib/plugins/aws/configCredentials/awsConfigCredentials.js
+++ b/lib/plugins/aws/configCredentials/awsConfigCredentials.js
@@ -1,9 +1,12 @@
'use strict';
const BbPromise = require('bluebird');
+const constants = require('constants');
const path = require('path');
+const fs = require('fs');
const fse = require('fs-extra');
const os = require('os');
+const _ = require('lodash');
class AwsConfigCredentials {
constructor(serverless, options) {
@@ -35,12 +38,25 @@ class AwsConfigCredentials {
usage: 'Name of the profile you wish to create. Defaults to "default"',
shortcut: 'n',
},
+ overwrite: {
+ usage: 'Overwrite the existing profile configuration in the credentials file',
+ shortcut: 'o',
+ },
},
},
},
},
};
+ if (!os.homedir()) {
+ throw new this.serverless.classes
+ .Error('Can\'t find home directory on your local file system.');
+ }
+
+ this.credentialsFilePath = path.join(os.homedir(), '.aws', 'credentials');
+ // Create the credentials file alongside the .aws directory if it's not yet present
+ fse.ensureFileSync(this.credentialsFilePath);
+
this.hooks = {
'config:credentials:config': () => BbPromise.bind(this)
.then(this.configureCredentials),
@@ -63,45 +79,104 @@ class AwsConfigCredentials {
}
this.serverless.cli.log('Setting up AWS...');
- this.serverless.cli.log('Saving your AWS profile in "~/.aws/credentials"...');
- if (!os.homedir()) {
- throw new this.serverless.classes
- .Error('Can\'t find home directory on your local file system.');
- }
+ this.credentials = this.getCredentials();
- // check if ~/.aws/credentials exists
- const configDir = path.join(os.homedir(), '.aws');
- const credsPath = path.join(configDir, 'credentials');
+ // Get the profile start line and end line numbers inside the credentials array
+ const profileBoundaries = this.getProfileBoundaries();
- if (this.serverless.utils.fileExistsSync(credsPath)) {
- // check if credentials files contains anything
- const credsFile = this.serverless.utils.readFileSync(credsPath);
-
- // if credentials file exists w/ profile, exit
- if (credsFile.length && credsFile.indexOf(`[${this.options.profile}]`) > -1) {
- this.serverless.cli.log(
- `Failed! ~/.aws/credentials exists and already has a "${this.options.profile}" profile.`);
+ // Check if the profile exists
+ const isNewProfile = profileBoundaries.start === -1;
+ if (isNewProfile) {
+ this.addProfile();
+ } else {
+ // Only update the profile if the overwrite flag was set
+ if (!this.options.overwrite) {
+ const message = [
+ `Failed! ~/.aws/credentials already has a "${this.options.profile}" profile.`,
+ ' Use the overwrite flag ("-o" or "--overwrite") to force the update',
+ ].join('');
+ this.serverless.cli.log(message);
return BbPromise.resolve();
}
- } else {
- // create the credentials file alongside the .aws directory if it's not yet present
- fse.ensureFileSync(credsPath);
+
+ this.updateProfile(profileBoundaries);
}
- // write credentials file with 'default' profile
- this.serverless.utils.appendFileSync(
- credsPath,
- `[${this.options.profile}]
-aws_access_key_id=${this.options.key}
-aws_secret_access_key=${this.options.secret}
-`); // Keep line break at the end. Otherwise will break AWS CLI.
-
- this.serverless.cli.log(
- `Success! Your AWS access keys were stored under the "${this.options.profile}" profile.`);
-
- return BbPromise.resolve();
+ return this.saveCredentialsFile();
}
+
+ getCredentials() {
+ // Get the credentials file lines
+ const credentialsFileContent = this.serverless.utils.readFileSync(this.credentialsFilePath);
+ return credentialsFileContent ? credentialsFileContent.split('\n') : [];
+ }
+
+ addProfile() {
+ this.credentials.push(`[${this.options.profile}]`,
+ `aws_access_key_id = ${this.options.key}`,
+ `aws_secret_access_key = ${this.options.secret}`);
+ }
+
+ updateProfile(profileBoundries) {
+ let currentLine = profileBoundries.start;
+ let endLine = profileBoundries.end;
+
+ // Remove existing 'aws_access_key_id' and 'aws_secret_access_key' properties
+ while (currentLine < endLine) {
+ const line = this.credentials[currentLine];
+ if (
+ line.indexOf('aws_access_key_id') > -1 ||
+ line.indexOf('aws_secret_access_key') > -1
+ ) {
+ this.credentials.splice(currentLine, 1);
+ endLine--;
+ } else {
+ currentLine++;
+ }
+ }
+
+ // Add the key and the secret to the beginning of the section
+ const keyLine = `aws_access_key_id = ${this.options.key}`;
+ const secretLine = `aws_secret_access_key = ${this.options.secret}`;
+
+ this.credentials.splice(profileBoundries.start + 1, 0, secretLine);
+ this.credentials.splice(profileBoundries.start + 1, 0, keyLine);
+ }
+
+ saveCredentialsFile() {
+ // Generate the file content and add a line break at the end
+ const updatedCredsFileContent = `${this.credentials.join('\n')}\n`;
+
+ this.serverless.cli.log('Saving your AWS profile in "~/.aws/credentials"...');
+
+ return this.serverless.utils.writeFile(this.credentialsFilePath, updatedCredsFileContent)
+ .then(() => {
+ // set file permissions to only readable/writable by owner (equivalent to 'chmod 600')
+ // NOTE: `chmod` doesn't behave as intended on Windows, so skip if we're on Windows.
+ if (os.platform() !== 'win32') {
+ fs.chmodSync(
+ this.credentialsFilePath,
+ (fs.constants || constants).S_IRUSR | (fs.constants || constants).S_IWUSR
+ );
+ }
+
+ this.serverless.cli.log(
+ `Success! Your AWS access keys were stored under the "${this.options.profile}" profile.`);
+ });
+ }
+
+ getProfileBoundaries() {
+ // Get the line number of the aws profile definition, defaults to -1
+ const start = this.credentials.indexOf(`[${this.options.profile}]`);
+
+ const nextProfile = _.findIndex(this.credentials, line => /\[[^\]]+\]/.test(line), start + 1);
+ // Get the line number of the next aws profile definition, defaults to the file lines number
+ const end = nextProfile + 1 || this.credentials.length;
+
+ return { start, end };
+ }
+
}
module.exports = AwsConfigCredentials;
diff --git a/lib/plugins/aws/configCredentials/awsConfigCredentials.test.js b/lib/plugins/aws/configCredentials/awsConfigCredentials.test.js
index 6daad7908..05e9a6f2b 100644
--- a/lib/plugins/aws/configCredentials/awsConfigCredentials.test.js
+++ b/lib/plugins/aws/configCredentials/awsConfigCredentials.test.js
@@ -2,6 +2,7 @@
const expect = require('chai').expect;
const sinon = require('sinon');
+const constants = require('constants');
const fs = require('fs');
const fse = require('fs-extra');
const os = require('os');
@@ -12,9 +13,24 @@ const Serverless = require('../../../Serverless');
describe('AwsConfigCredentials', () => {
let awsConfigCredentials;
+ let credentialsFileContent;
+ let credentialsFilePath;
let serverless;
+ let sandbox;
+ let tmpDirPath;
beforeEach(() => {
+ sandbox = sinon.sandbox.create();
+
+ tmpDirPath = testUtils.getTmpDirPath();
+ credentialsFilePath = path.join(tmpDirPath, '.aws', 'credentials');
+ credentialsFileContent = '[my-profile]\n';
+ credentialsFileContent += 'aws_access_key_id = my-old-profile-key\n';
+ credentialsFileContent += 'aws_secret_access_key = my-old-profile-secret\n';
+
+ // stub homedir handler to return the tmpDirPath
+ sandbox.stub(os, 'homedir').returns(tmpDirPath);
+
serverless = new Serverless();
serverless.init();
const options = {
@@ -25,6 +41,10 @@ describe('AwsConfigCredentials', () => {
awsConfigCredentials = new AwsConfigCredentials(serverless, options);
});
+ afterEach(() => {
+ sandbox.restore();
+ });
+
describe('#constructor()', () => {
it('should have the command "config"', () => {
expect(awsConfigCredentials.commands.config).to.not.equal(undefined);
@@ -66,29 +86,24 @@ describe('AwsConfigCredentials', () => {
awsConfigCredentials.configureCredentials.restore();
});
});
+
+ it('should throw an error if the home directory was not found', () => {
+ os.homedir.returns(null);
+ expect(() => new AwsConfigCredentials(serverless, {})).to.throw(Error);
+ });
+
+ it('should create the .aws/credentials file if not yet present', () => {
+ // remove the .aws directory which was created in the before hook of the test
+ const awsDirectoryPath = path.join(tmpDirPath, '.aws');
+ fse.removeSync(awsDirectoryPath);
+
+ awsConfigCredentials = new AwsConfigCredentials(serverless, {});
+ const isCredentialsFilePresent = fs.existsSync(path.join(awsDirectoryPath, 'credentials'));
+ expect(isCredentialsFilePresent).to.equal(true);
+ });
});
describe('#configureCredentials()', () => {
- let homeDir;
- let tmpDirPath;
- let credentialsFilePath;
-
- beforeEach(() => {
- // create a new tmpDir for the homeDir path
- tmpDirPath = testUtils.getTmpDirPath();
- fse.mkdirsSync(tmpDirPath);
-
- // create the .aws/credetials directory and file
- credentialsFilePath = path.join(tmpDirPath, '.aws', 'credentials');
- fse.ensureFileSync(credentialsFilePath);
-
- // save the homeDir so that we can reset this later on
- homeDir = os.homedir();
- process.env.HOME = tmpDirPath;
- process.env.HOMEPATH = tmpDirPath;
- process.env.USERPROFILE = tmpDirPath;
- });
-
it('should lowercase the provider option', () => {
awsConfigCredentials.options.provider = 'SOMEPROVIDER';
@@ -116,11 +131,75 @@ describe('AwsConfigCredentials', () => {
expect(() => awsConfigCredentials.configureCredentials()).to.throw(Error);
});
- it('should resolve if profile is already given in credentials file', (done) => {
+ it('should not update the profile if the overwrite flag is not set', () => {
awsConfigCredentials.options.profile = 'my-profile';
- serverless.utils.appendFileSync(credentialsFilePath, '[my-profile]');
+ awsConfigCredentials.options.key = 'my-new-profile-key';
+ awsConfigCredentials.options.secret = 'my-new-profile-secret';
- awsConfigCredentials.configureCredentials().then(() => done());
+ fse.outputFileSync(credentialsFilePath, credentialsFileContent);
+
+ return awsConfigCredentials.configureCredentials();
+ });
+
+ it('should update the profile', () => {
+ awsConfigCredentials.options.profile = 'my-profile';
+ awsConfigCredentials.options.key = 'my-new-profile-key';
+ awsConfigCredentials.options.secret = 'my-new-profile-secret';
+ awsConfigCredentials.options.overwrite = true;
+
+ fse.outputFileSync(credentialsFilePath, credentialsFileContent);
+
+ return awsConfigCredentials.configureCredentials().then(() => {
+ const UpdatedCredentialsFileContent = fs.readFileSync(credentialsFilePath).toString();
+ const lineByLineContent = UpdatedCredentialsFileContent.split('\n');
+
+ expect(lineByLineContent[0]).to.equal('[my-profile]');
+ expect(lineByLineContent[1]).to.equal('aws_access_key_id = my-new-profile-key');
+ expect(lineByLineContent[2]).to.equal('aws_secret_access_key = my-new-profile-secret');
+ });
+ });
+
+ it('should not alter other profiles when updating a profile', () => {
+ awsConfigCredentials.options.profile = 'my-profile';
+ awsConfigCredentials.options.key = 'my-new-profile-key';
+ awsConfigCredentials.options.secret = 'my-new-profile-secret';
+ awsConfigCredentials.options.overwrite = true;
+
+ credentialsFileContent += '[my-other-profile]\n';
+ credentialsFileContent += 'aws_secret_access_key = my-other-profile-secret\n';
+
+ fse.outputFileSync(credentialsFilePath, credentialsFileContent);
+
+ return awsConfigCredentials.configureCredentials().then(() => {
+ const UpdatedCredentialsFileContent = fs.readFileSync(credentialsFilePath).toString();
+ const lineByLineContent = UpdatedCredentialsFileContent.split('\n');
+
+ expect(lineByLineContent[0]).to.equal('[my-profile]');
+ expect(lineByLineContent[1]).to.equal('aws_access_key_id = my-new-profile-key');
+ expect(lineByLineContent[2]).to.equal('aws_secret_access_key = my-new-profile-secret');
+ expect(lineByLineContent[4]).to.equal('aws_secret_access_key = my-other-profile-secret');
+ });
+ });
+
+ it('should add the missing credentials to the updated profile', () => {
+ credentialsFileContent = '[my-profile]\n';
+ credentialsFileContent += 'aws_secret_access_key = my-profile-secret\n';
+
+ awsConfigCredentials.options.profile = 'my-profile';
+ awsConfigCredentials.options.key = 'my-new-profile-key';
+ awsConfigCredentials.options.secret = 'my-new-profile-secret';
+ awsConfigCredentials.options.overwrite = true;
+
+ fse.outputFileSync(credentialsFilePath, credentialsFileContent);
+
+ return awsConfigCredentials.configureCredentials().then(() => {
+ const UpdatedCredentialsFileContent = fs.readFileSync(credentialsFilePath).toString();
+ const lineByLineContent = UpdatedCredentialsFileContent.split('\n');
+
+ expect(lineByLineContent[0]).to.equal('[my-profile]');
+ expect(lineByLineContent[1]).to.equal('aws_access_key_id = my-new-profile-key');
+ expect(lineByLineContent[2]).to.equal('aws_secret_access_key = my-new-profile-secret');
+ });
});
it('should append the profile to the credentials file', () => {
@@ -129,32 +208,85 @@ describe('AwsConfigCredentials', () => {
awsConfigCredentials.options.secret = 'my-profile-secret';
return awsConfigCredentials.configureCredentials().then(() => {
- const credentialsFileContent = fs.readFileSync(credentialsFilePath).toString();
- const lineByLineContent = credentialsFileContent.split('\n');
+ const UpdatedCredentialsFileContent = fs.readFileSync(credentialsFilePath).toString();
+ const lineByLineContent = UpdatedCredentialsFileContent.split('\n');
expect(lineByLineContent[0]).to.equal('[my-profile]');
- expect(lineByLineContent[1]).to.equal('aws_access_key_id=my-profile-key');
- expect(lineByLineContent[2]).to.equal('aws_secret_access_key=my-profile-secret');
+ expect(lineByLineContent[1]).to.equal('aws_access_key_id = my-profile-key');
+ expect(lineByLineContent[2]).to.equal('aws_secret_access_key = my-profile-secret');
});
});
- it('should create the .aws/credentials file if not yet present', () => {
- // remove the .aws directory which was created in the before hook of the test
- const awsDirectoryPath = path.join(tmpDirPath, '.aws');
- fse.removeSync(awsDirectoryPath);
+ if (os.platform() !== 'win32') {
+ it('should set the permissions of the credentials file to be owner-only read/write', () =>
+ awsConfigCredentials.configureCredentials().then(() => {
+ const fileMode = fs.statSync(credentialsFilePath).mode;
+ const filePermissions = fileMode & ~(fs.constants || constants).S_IFMT;
- return awsConfigCredentials.configureCredentials().then(() => {
- const isCredentialsFilePresent = fs.existsSync(path.join(awsDirectoryPath, 'credentials'));
+ const readableByOwnerPermission = (fs.constants || constants).S_IRUSR;
+ const writableByOwnerPermission = (fs.constants || constants).S_IWUSR;
+ const expectedFilePermissions = readableByOwnerPermission | writableByOwnerPermission;
- expect(isCredentialsFilePresent).to.equal(true);
- });
+ expect(filePermissions).to.equal(expectedFilePermissions);
+ })
+ );
+ }
+ });
+
+ describe('#getCredentials()', () => {
+ it('should load credentials file and return the credentials lines', () => {
+ fse.outputFileSync(credentialsFilePath, credentialsFileContent);
+ const credentials = awsConfigCredentials.getCredentials();
+
+ expect(credentials[0]).to.equal('[my-profile]');
+ expect(credentials[1]).to.equal('aws_access_key_id = my-old-profile-key');
});
- afterEach(() => {
- // recover the homeDir
- process.env.HOME = homeDir;
- process.env.HOMEPATH = homeDir;
- process.env.USERPROFILE = homeDir;
+ it('should return an empty array if the file is empty', () => {
+ const credentials = awsConfigCredentials.getCredentials();
+
+ expect(credentials.length).to.equal(0);
+ });
+ });
+
+ describe('#getProfileBoundaries()', () => {
+ it('should return the start and end numbers of the profile', () => {
+ awsConfigCredentials.options.profile = 'my-profile';
+ awsConfigCredentials.credentials = [
+ '[my-profile]',
+ 'aws_access_key_id = my-other-profile-key',
+ ];
+
+ const profileBoundaries = awsConfigCredentials.getProfileBoundaries();
+
+ expect(profileBoundaries.start).to.equal(0);
+ expect(profileBoundaries.end).to.equal(2);
+ });
+
+ it('should set the start property to -1 if the profile was not found', () => {
+ awsConfigCredentials.options.profile = 'my-not-yet-saved-profile';
+ awsConfigCredentials.credentials = [
+ '[my-profile]',
+ 'aws_access_key_id = my-other-profile-key',
+ ];
+
+ const profileBoundaries = awsConfigCredentials.getProfileBoundaries();
+
+ expect(profileBoundaries.start).to.equal(-1);
+ });
+
+ it('should set the end to the credentials length if no other profile was found', () => {
+ awsConfigCredentials.options.profile = 'my-profile';
+ awsConfigCredentials.credentials = [
+ '[my-profile]',
+ 'aws_access_key_id = my-other-profile-key',
+ '# a comment',
+ 'aws_secret_access_key = my-profile-secret',
+ ];
+
+ const profileBoundaries = awsConfigCredentials.getProfileBoundaries();
+
+ expect(profileBoundaries.end).to.equal(4);
});
});
});
diff --git a/lib/plugins/aws/deploy/lib/checkForChanges.test.js b/lib/plugins/aws/deploy/lib/checkForChanges.test.js
index 35e08bb7d..b382bbbf9 100644
--- a/lib/plugins/aws/deploy/lib/checkForChanges.test.js
+++ b/lib/plugins/aws/deploy/lib/checkForChanges.test.js
@@ -335,7 +335,7 @@ describe('checkForChanges', () => {
}
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
- 'my-service/.serverless/my-service.zip'
+ path.join('my-service/.serverless/my-service.zip')
);
expect(awsDeploy.serverless.service.provider.shouldNotDeploy).to.equal(undefined);
});
@@ -369,7 +369,7 @@ describe('checkForChanges', () => {
}
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
- 'my-service/.serverless/my-service.zip'
+ path.join('my-service/.serverless/my-service.zip')
);
expect(awsDeploy.serverless.service.provider.shouldNotDeploy).to.equal(undefined);
});
@@ -405,10 +405,10 @@ describe('checkForChanges', () => {
}
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
- 'my-service/.serverless/func1.zip'
+ path.join('my-service/.serverless/func1.zip')
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
- 'my-service/.serverless/func2.zip'
+ path.join('my-service/.serverless/func2.zip')
);
expect(awsDeploy.serverless.service.provider.shouldNotDeploy).to.equal(undefined);
});
@@ -442,7 +442,7 @@ describe('checkForChanges', () => {
}
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
- 'my-service/.serverless/my-service.zip'
+ path.join('my-service/.serverless/my-service.zip')
);
expect(awsDeploy.serverless.service.provider.shouldNotDeploy).to.equal(true);
});
@@ -479,10 +479,10 @@ describe('checkForChanges', () => {
}
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
- 'my-service/.serverless/func1.zip'
+ path.join('my-service/.serverless/func1.zip')
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
- 'my-service/.serverless/func2.zip'
+ path.join('my-service/.serverless/func2.zip')
);
expect(awsDeploy.serverless.service.provider.shouldNotDeploy).to.equal(true);
});
diff --git a/lib/plugins/aws/deployList/index.js b/lib/plugins/aws/deployList/index.js
index 2d2186286..91c255cce 100644
--- a/lib/plugins/aws/deployList/index.js
+++ b/lib/plugins/aws/deployList/index.js
@@ -92,22 +92,32 @@ class AwsDeployList {
}).then((result) => _.map(result, (item) => item.Configuration));
}
+ getFunctionPaginatedVersions(params, totalVersions) {
+ return this.provider.request('Lambda',
+ 'listVersionsByFunction',
+ params,
+ this.options.stage,
+ this.options.region)
+ .then((response) => {
+ const Versions = (totalVersions || []).concat(response.Versions);
+ if (response.NextMarker) {
+ return this.getFunctionPaginatedVersions(
+ Object.assign({}, params, { Marker: response.NextMarker }), Versions);
+ }
+
+ return Promise.resolve({ Versions });
+ });
+ }
+
getFunctionVersions(funcs) {
const requestPromises = [];
funcs.forEach((func) => {
const params = {
FunctionName: func.FunctionName,
- MaxItems: 5,
};
- const request = this.provider.request('Lambda',
- 'listVersionsByFunction',
- params,
- this.options.stage,
- this.options.region);
-
- requestPromises.push(request);
+ requestPromises.push(this.getFunctionPaginatedVersions(params));
});
return BbPromise.all(requestPromises);
@@ -125,7 +135,8 @@ class AwsDeployList {
name = name.replace(`${this.options.stage}-`, '');
message += `${name}: `;
- const versions = func.Versions.map((funcEntry) => funcEntry.Version).reverse();
+ const versions = func.Versions.map((funcEntry) => funcEntry.Version)
+ .slice(Math.max(0, func.Versions.length - 5));
message += versions.join(', ');
this.serverless.cli.log(message);
diff --git a/lib/plugins/aws/deployList/index.test.js b/lib/plugins/aws/deployList/index.test.js
index 2400be6ec..3b7304c74 100644
--- a/lib/plugins/aws/deployList/index.test.js
+++ b/lib/plugins/aws/deployList/index.test.js
@@ -163,6 +163,47 @@ describe('AwsDeployList', () => {
});
});
+ describe('#getFunctionPaginatedVersions()', () => {
+ beforeEach(() => {
+ sinon
+ .stub(awsDeployList.provider, 'request')
+ .onFirstCall()
+ .resolves({
+ Versions: [
+ { FunctionName: 'listDeployments-dev-func', Version: '1' },
+ ],
+ NextMarker: '123',
+ })
+ .onSecondCall()
+ .resolves({
+ Versions: [
+ { FunctionName: 'listDeployments-dev-func', Version: '2' },
+ ],
+ });
+ });
+
+ afterEach(() => {
+ awsDeployList.provider.request.restore();
+ });
+
+ it('should return the versions for the provided function when response is paginated', () => {
+ const params = {
+ FunctionName: 'listDeployments-dev-func',
+ };
+
+ return awsDeployList.getFunctionPaginatedVersions(params).then((result) => {
+ const expectedResult = {
+ Versions: [
+ { FunctionName: 'listDeployments-dev-func', Version: '1' },
+ { FunctionName: 'listDeployments-dev-func', Version: '2' },
+ ],
+ };
+
+ expect(result).to.deep.equal(expectedResult);
+ });
+ });
+ });
+
describe('#getFunctionVersions()', () => {
let listVersionsByFunctionStub;
@@ -210,13 +251,17 @@ describe('AwsDeployList', () => {
const funcs = [
{
Versions: [
- { FunctionName: 'listDeployments-dev-func-1', Version: '$LATEST' },
+ { FunctionName: 'listDeployments-dev-func-1', Version: '1337' },
],
},
{
Versions: [
- { FunctionName: 'listDeployments-dev-func-2', Version: '$LATEST' },
- { FunctionName: 'listDeployments-dev-func-2', Version: '4711' },
+ { FunctionName: 'listDeployments-dev-func-2', Version: '2' },
+ { FunctionName: 'listDeployments-dev-func-2', Version: '3' },
+ { FunctionName: 'listDeployments-dev-func-2', Version: '4' },
+ { FunctionName: 'listDeployments-dev-func-2', Version: '5' },
+ { FunctionName: 'listDeployments-dev-func-2', Version: '6' },
+ { FunctionName: 'listDeployments-dev-func-2', Version: '7' },
],
},
];
@@ -229,8 +274,8 @@ describe('AwsDeployList', () => {
.to.be.equal(true);
expect(log.calledWithExactly('-------------')).to.be.equal(true);
- expect(log.calledWithExactly('func-1: $LATEST')).to.be.equal(true);
- expect(log.calledWithExactly('func-2: 4711, $LATEST')).to.be.equal(true);
+ expect(log.calledWithExactly('func-1: 1337')).to.be.equal(true);
+ expect(log.calledWithExactly('func-2: 3, 4, 5, 6, 7')).to.be.equal(true);
});
});
});
diff --git a/lib/plugins/aws/info/display.js b/lib/plugins/aws/info/display.js
index 0ba36cbf4..10cf9a6b3 100644
--- a/lib/plugins/aws/info/display.js
+++ b/lib/plugins/aws/info/display.js
@@ -11,7 +11,8 @@ module.exports = {
message += `${chalk.yellow.underline('Service Information')}\n`;
message += `${chalk.yellow('service:')} ${info.service}\n`;
message += `${chalk.yellow('stage:')} ${info.stage}\n`;
- message += `${chalk.yellow('region:')} ${info.region}`;
+ message += `${chalk.yellow('region:')} ${info.region}\n`;
+ message += `${chalk.yellow('stack:')} ${info.stack}`;
this.serverless.cli.consoleLog(message);
return message;
diff --git a/lib/plugins/aws/info/display.test.js b/lib/plugins/aws/info/display.test.js
index 84f64f586..22b955c9e 100644
--- a/lib/plugins/aws/info/display.test.js
+++ b/lib/plugins/aws/info/display.test.js
@@ -28,6 +28,7 @@ describe('#display()', () => {
service: 'my-first',
stage: 'dev',
region: 'eu-west-1',
+ stack: 'my-first-dev',
endpoint: null,
functions: [],
apiKeys: [],
@@ -46,7 +47,8 @@ describe('#display()', () => {
expectedMessage += `${chalk.yellow.underline('Service Information')}\n`;
expectedMessage += `${chalk.yellow('service:')} my-first\n`;
expectedMessage += `${chalk.yellow('stage:')} dev\n`;
- expectedMessage += `${chalk.yellow('region:')} eu-west-1`;
+ expectedMessage += `${chalk.yellow('region:')} eu-west-1\n`;
+ expectedMessage += `${chalk.yellow('stack:')} my-first-dev`;
const message = awsInfo.displayServiceInfo();
expect(consoleLogStub.calledOnce).to.equal(true);
diff --git a/lib/plugins/aws/info/getStackInfo.js b/lib/plugins/aws/info/getStackInfo.js
index 7c124f802..74b1a6bfb 100644
--- a/lib/plugins/aws/info/getStackInfo.js
+++ b/lib/plugins/aws/info/getStackInfo.js
@@ -12,6 +12,7 @@ module.exports = {
service: this.serverless.service.service,
stage: this.options.stage,
region: this.options.region,
+ stack: this.provider.naming.getStackName(this.options.stage),
},
outputs: [],
};
diff --git a/lib/plugins/aws/info/getStackInfo.test.js b/lib/plugins/aws/info/getStackInfo.test.js
index 05f4e1ada..af95a837e 100644
--- a/lib/plugins/aws/info/getStackInfo.test.js
+++ b/lib/plugins/aws/info/getStackInfo.test.js
@@ -86,6 +86,7 @@ describe('#getStackInfo()', () => {
service: 'my-service',
stage: 'dev',
region: 'us-east-1',
+ stack: 'my-service-dev',
},
outputs: [
{
@@ -134,6 +135,7 @@ describe('#getStackInfo()', () => {
service: 'my-service',
stage: 'dev',
region: 'us-east-1',
+ stack: 'my-service-dev',
},
outputs: [],
};
diff --git a/lib/plugins/aws/invoke/index.js b/lib/plugins/aws/invoke/index.js
index 0b70875cb..a272a2d1f 100644
--- a/lib/plugins/aws/invoke/index.js
+++ b/lib/plugins/aws/invoke/index.js
@@ -55,7 +55,9 @@ class AwsInvoke {
}
}).then(() => {
try {
- this.options.data = JSON.parse(this.options.data);
+ if (!this.options.raw) {
+ this.options.data = JSON.parse(this.options.data);
+ }
} catch (exception) {
// do nothing if it's a simple string or object already
}
diff --git a/lib/plugins/aws/invoke/index.test.js b/lib/plugins/aws/invoke/index.test.js
index ea60ca102..e6a2e15f0 100644
--- a/lib/plugins/aws/invoke/index.test.js
+++ b/lib/plugins/aws/invoke/index.test.js
@@ -105,6 +105,15 @@ describe('AwsInvoke', () => {
});
});
+ it('should skip parsing data if "raw" requested', () => {
+ awsInvoke.options.data = '{"key": "value"}';
+ awsInvoke.options.raw = true;
+
+ return awsInvoke.extendedValidate().then(() => {
+ expect(awsInvoke.options.data).to.deep.equal('{"key": "value"}');
+ });
+ });
+
it('it should parse file if relative file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
const data = {
diff --git a/lib/plugins/aws/invokeLocal/fixture/__init__.py b/lib/plugins/aws/invokeLocal/fixture/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/lib/plugins/aws/invokeLocal/fixture/handler.py b/lib/plugins/aws/invokeLocal/fixture/handler.py
new file mode 100644
index 000000000..3a36db642
--- /dev/null
+++ b/lib/plugins/aws/invokeLocal/fixture/handler.py
@@ -0,0 +1,11 @@
+from time import sleep
+
+def withRemainingTime(event, context):
+ start = context.get_remaining_time_in_millis()
+ sleep(0.001)
+ stop = context.get_remaining_time_in_millis()
+
+ return {
+ "start": start,
+ "stop": stop
+ }
\ No newline at end of file
diff --git a/lib/plugins/aws/invokeLocal/fixture/handlerWithSuccess.js b/lib/plugins/aws/invokeLocal/fixture/handlerWithSuccess.js
index 22b7c6de9..256621b48 100644
--- a/lib/plugins/aws/invokeLocal/fixture/handlerWithSuccess.js
+++ b/lib/plugins/aws/invokeLocal/fixture/handlerWithSuccess.js
@@ -20,3 +20,15 @@ module.exports.withMessageByLambdaProxy = (event, context) => {
}),
});
};
+
+module.exports.withRemainingTime = (event, context) => {
+ const start = context.getRemainingTimeInMillis();
+
+ const stopAt = new Date().getTime() + 1;
+ while (new Date().getTime() < stopAt);
+
+ context.done(null, {
+ start,
+ stop: context.getRemainingTimeInMillis(),
+ });
+};
diff --git a/lib/plugins/aws/invokeLocal/index.js b/lib/plugins/aws/invokeLocal/index.js
index 954488492..927c212a1 100644
--- a/lib/plugins/aws/invokeLocal/index.js
+++ b/lib/plugins/aws/invokeLocal/index.js
@@ -25,6 +25,22 @@ class AwsInvokeLocal {
};
}
+ validateFile(filePath, key) {
+ const absolutePath = path.isAbsolute(filePath) ?
+ filePath :
+ path.join(this.serverless.config.servicePath, filePath);
+ if (!this.serverless.utils.fileExistsSync(absolutePath)) {
+ throw new this.serverless.classes.Error('The file you provided does not exist.');
+ }
+
+ if (absolutePath.endsWith('.js')) {
+ // to support js - export as an input data
+ this.options[key] = require(absolutePath); // eslint-disable-line global-require
+ } else {
+ this.options[key] = this.serverless.utils.readFileSync(absolutePath);
+ }
+ }
+
extendedValidate() {
this.validate();
@@ -33,23 +49,14 @@ class AwsInvokeLocal {
this.options.data = this.options.data || '';
return new BbPromise(resolve => {
+ if (this.options.contextPath) {
+ this.validateFile(this.options.contextPath, 'context');
+ }
+
if (this.options.data) {
resolve();
} else if (this.options.path) {
- const absolutePath = path.isAbsolute(this.options.path) ?
- this.options.path :
- path.join(this.serverless.config.servicePath, this.options.path);
- if (!this.serverless.utils.fileExistsSync(absolutePath)) {
- throw new this.serverless.classes.Error('The file you provided does not exist.');
- }
- //
-
- if (absolutePath.endsWith('.js')) {
- // to support js - export as an input data
- this.options.data = require(absolutePath); // eslint-disable-line global-require
- } else {
- this.options.data = this.serverless.utils.readFileSync(absolutePath);
- }
+ this.validateFile(this.options.path, 'data');
resolve();
} else {
@@ -65,7 +72,10 @@ class AwsInvokeLocal {
}
}).then(() => {
try {
- this.options.data = JSON.parse(this.options.data);
+ if (!this.options.raw) {
+ this.options.data = JSON.parse(this.options.data);
+ this.options.context = JSON.parse(this.options.context);
+ }
} catch (exception) {
// do nothing if it's a simple string or object already
}
@@ -79,7 +89,6 @@ class AwsInvokeLocal {
|| 1024;
const lambdaDefaultEnvVars = {
- PATH: '/usr/local/lib64/node-v4.3.x/bin:/usr/local/bin:/usr/bin/:/bin',
LANG: 'en_US.UTF-8',
LD_LIBRARY_PATH: '/usr/local/lib64/node-v4.3.x/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib', // eslint-disable-line max-len
LAMBDA_TASK_ROOT: '/var/task',
@@ -114,37 +123,45 @@ class AwsInvokeLocal {
return this.invokeLocalNodeJs(
handlerPath,
handlerName,
- this.options.data);
+ this.options.data,
+ this.options.context);
}
if (runtime === 'python2.7' || runtime === 'python3.6') {
return this.invokeLocalPython(
- runtime,
+ process.platform === 'win32' ? 'python.exe' : runtime,
handlerPath,
handlerName,
- this.options.data);
+ this.options.data,
+ this.options.context);
}
throw new this.serverless.classes
.Error('You can only invoke Node.js & Python functions locally.');
}
- invokeLocalPython(runtime, handlerPath, handlerName, event) {
+ invokeLocalPython(runtime, handlerPath, handlerName, event, context) {
+ const input = JSON.stringify({
+ event: event || {},
+ context,
+ });
+
if (process.env.VIRTUAL_ENV) {
process.env.PATH = `${process.env.VIRTUAL_ENV}/bin:${process.env.PATH}`;
}
+
return new BbPromise(resolve => {
const python = spawn(runtime,
[path.join(__dirname, 'invoke.py'), handlerPath, handlerName], { env: process.env });
python.stdout.on('data', (buf) => this.serverless.cli.consoleLog(buf.toString()));
python.stderr.on('data', (buf) => this.serverless.cli.consoleLog(buf.toString()));
- python.stdin.write(JSON.stringify(event || {}));
+ python.stdin.write(input);
python.stdin.end();
python.on('close', () => resolve());
});
}
- invokeLocalNodeJs(handlerPath, handlerName, event) {
+ invokeLocalNodeJs(handlerPath, handlerName, event, customContext) {
let lambda;
try {
@@ -201,7 +218,10 @@ class AwsInvokeLocal {
const startTime = new Date();
- const context = {
+ const timeout = Number(this.options.functionObj.timeout)
+ || Number(this.serverless.service.provider.timeout)
+ || 6;
+ let context = {
awsRequestId: 'id',
invokeid: 'id',
logGroupName: this.provider.naming.getLogGroupName(this.options.functionObj.name),
@@ -222,10 +242,14 @@ class AwsInvokeLocal {
return callback(error, result);
},
getRemainingTimeInMillis() {
- return (new Date()).valueOf() - startTime.valueOf();
+ return Math.max((timeout * 1000) - ((new Date()).valueOf() - startTime.valueOf()), 0);
},
};
+ if (customContext) {
+ context = customContext;
+ }
+
return lambda(event, context, callback);
}
}
diff --git a/lib/plugins/aws/invokeLocal/index.test.js b/lib/plugins/aws/invokeLocal/index.test.js
index 2ac9b2fa0..48414c278 100644
--- a/lib/plugins/aws/invokeLocal/index.test.js
+++ b/lib/plugins/aws/invokeLocal/index.test.js
@@ -106,6 +106,15 @@ describe('AwsInvokeLocal', () => {
});
});
+ it('should skip parsing data if "raw" requested', () => {
+ awsInvokeLocal.options.data = '{"key": "value"}';
+ awsInvokeLocal.options.raw = true;
+
+ return awsInvokeLocal.extendedValidate().then(() => {
+ expect(awsInvokeLocal.options.data).to.deep.equal('{"key": "value"}');
+ });
+ });
+
it('it should parse file if relative file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
const data = {
@@ -113,10 +122,10 @@ describe('AwsInvokeLocal', () => {
};
serverless.utils.writeFileSync(path
.join(serverless.config.servicePath, 'data.json'), JSON.stringify(data));
- awsInvokeLocal.options.path = 'data.json';
+ awsInvokeLocal.options.contextPath = 'data.json';
return awsInvokeLocal.extendedValidate().then(() => {
- expect(awsInvokeLocal.options.data).to.deep.equal(data);
+ expect(awsInvokeLocal.options.context).to.deep.equal(data);
});
});
@@ -130,6 +139,7 @@ describe('AwsInvokeLocal', () => {
const dataFile = path.join(serverless.config.servicePath, 'data.json');
serverless.utils.writeFileSync(dataFile, JSON.stringify(data));
awsInvokeLocal.options.path = dataFile;
+ awsInvokeLocal.options.contextPath = false;
return awsInvokeLocal.extendedValidate().then(() => {
expect(awsInvokeLocal.options.data).to.deep.equal(data);
@@ -226,8 +236,6 @@ describe('AwsInvokeLocal', () => {
it('it should load default lambda env vars', () => awsInvokeLocal
.loadEnvVars().then(() => {
- expect(process.env.PATH)
- .to.equal('/usr/local/lib64/node-v4.3.x/bin:/usr/local/bin:/usr/bin/:/bin');
expect(process.env.LANG).to.equal('en_US.UTF-8');
expect(process.env.LD_LIBRARY_PATH)
.to.equal('/usr/local/lib64/node-v4.3.x/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib'); // eslint-disable-line max-len
@@ -298,7 +306,8 @@ describe('AwsInvokeLocal', () => {
expect(invokeLocalNodeJsStub.calledWithExactly(
'handler',
'hello',
- {}
+ {},
+ undefined
)).to.be.equal(true);
awsInvokeLocal.invokeLocalNodeJs.restore();
})
@@ -318,6 +327,21 @@ describe('AwsInvokeLocal', () => {
});
});
+ it('should call invokeLocalNodeJs with custom context if provided', () => {
+ awsInvokeLocal.options.context = 'custom context';
+ awsInvokeLocal.invokeLocal()
+ .then(() => {
+ expect(invokeLocalNodeJsStub.calledOnce).to.be.equal(true);
+ expect(invokeLocalNodeJsStub.calledWithExactly(
+ 'handler',
+ 'hello',
+ {},
+ 'custom context'
+ )).to.be.equal(true);
+ awsInvokeLocal.invokeLocalNodeJs.restore();
+ });
+ });
+
it('should call invokeLocalPython when python2.7 runtime is set', () => {
awsInvokeLocal.options.functionObj.runtime = 'python2.7';
awsInvokeLocal.invokeLocal()
@@ -385,6 +409,37 @@ describe('AwsInvokeLocal', () => {
});
});
+ describe('context.remainingTimeInMillis', () => {
+ it('should become lower over time', () => {
+ awsInvokeLocal.serverless.config.servicePath = __dirname;
+
+ awsInvokeLocal.invokeLocalNodeJs('fixture/handlerWithSuccess', 'withRemainingTime');
+
+ const remainingTimes = JSON.parse(serverless.cli.consoleLog.lastCall.args[0]);
+ expect(remainingTimes.start).to.be.above(remainingTimes.stop);
+ });
+
+ it('should start with the timeout value', () => {
+ awsInvokeLocal.serverless.config.servicePath = __dirname;
+ awsInvokeLocal.serverless.service.provider.timeout = 5;
+
+ awsInvokeLocal.invokeLocalNodeJs('fixture/handlerWithSuccess', 'withRemainingTime');
+
+ const remainingTimes = JSON.parse(serverless.cli.consoleLog.lastCall.args[0]);
+ expect(remainingTimes.start).to.eql(5000);
+ });
+
+ it('should never become negative', () => {
+ awsInvokeLocal.serverless.config.servicePath = __dirname;
+ awsInvokeLocal.serverless.service.provider.timeout = 0.00001;
+
+ awsInvokeLocal.invokeLocalNodeJs('fixture/handlerWithSuccess', 'withRemainingTime');
+
+ const remainingTimes = JSON.parse(serverless.cli.consoleLog.lastCall.args[0]);
+ expect(remainingTimes.stop).to.eql(0);
+ });
+ });
+
describe('with extraServicePath', () => {
it('should succeed if succeed', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;
@@ -421,4 +476,37 @@ describe('AwsInvokeLocal', () => {
expect(serverless.cli.consoleLog.lastCall.args[0]).to.contain('"errorMessage": "failed"');
});
});
+
+ // Ignored because it fails in CI
+ // See https://github.com/serverless/serverless/pull/4047#issuecomment-320460285
+ describe.skip('#invokeLocalPython', () => {
+ beforeEach(() => {
+ awsInvokeLocal.options = {
+ functionObj: {
+ name: '',
+ },
+ };
+
+ serverless.cli = new CLI(serverless);
+ sinon.stub(serverless.cli, 'consoleLog');
+ });
+
+ afterEach(() => {
+ serverless.cli.consoleLog.restore();
+ });
+
+ describe('context.remainingTimeInMillis', () => {
+ it('should become lower over time', () => {
+ awsInvokeLocal.serverless.config.servicePath = __dirname;
+
+ return awsInvokeLocal.invokeLocalPython(
+ 'python2.7',
+ 'fixture/handler',
+ 'withRemainingTime').then(() => {
+ const remainingTimes = JSON.parse(serverless.cli.consoleLog.lastCall.args[0]);
+ expect(remainingTimes.start).to.be.above(remainingTimes.stop);
+ });
+ });
+ });
+ });
});
diff --git a/lib/plugins/aws/invokeLocal/invoke.py b/lib/plugins/aws/invokeLocal/invoke.py
index 2fac90bbf..912025853 100755
--- a/lib/plugins/aws/invokeLocal/invoke.py
+++ b/lib/plugins/aws/invokeLocal/invoke.py
@@ -9,9 +9,10 @@ class FakeLambdaContext(object):
self.name = name
self.version = version
self.created = time()
+ self.timeout = timeout
def get_remaining_time_in_millis(self):
- return (self.created - time()) * 1000
+ return int(max((self.timeout * 1000) - (int(round(time() * 1000)) - int(round(self.created * 1000))), 0))
@property
def function_name(self):
@@ -54,6 +55,9 @@ if __name__ == '__main__':
module = import_module(args.handler_path.replace('/', '.'))
handler = getattr(module, args.handler_name)
- event = json.load(sys.stdin)
- result = handler(event, FakeLambdaContext())
+ input = json.load(sys.stdin)
+ context = FakeLambdaContext()
+ if 'context' in input:
+ context = input['context']
+ result = handler(input['event'], context)
sys.stdout.write(json.dumps(result, indent=4))
diff --git a/lib/plugins/aws/lib/monitorStack.js b/lib/plugins/aws/lib/monitorStack.js
index e870d5f3e..3f21d9b0b 100644
--- a/lib/plugins/aws/lib/monitorStack.js
+++ b/lib/plugins/aws/lib/monitorStack.js
@@ -102,12 +102,13 @@ module.exports = {
// Handle stack create/update/delete failures
if ((stackLatestError && !this.options.verbose)
|| (stackStatus
- && stackStatus.endsWith('ROLLBACK_COMPLETE')
+ && (stackStatus.endsWith('ROLLBACK_COMPLETE')
+ || stackStatus === 'DELETE_FAILED')
&& this.options.verbose)) {
// empty console.log for a prettier output
if (!this.options.verbose) this.serverless.cli.consoleLog('');
- this.serverless.cli.log('Deployment failed!');
- let errorMessage = 'An error occurred while provisioning your stack: ';
+ this.serverless.cli.log('Operation failed!');
+ let errorMessage = 'An error occurred: ';
errorMessage += `${stackLatestError.LogicalResourceId} - `;
errorMessage += `${stackLatestError.ResourceStatusReason}.`;
return reject(new this.serverless.classes.Error(errorMessage));
diff --git a/lib/plugins/aws/lib/monitorStack.test.js b/lib/plugins/aws/lib/monitorStack.test.js
index 00108ca66..8555ce858 100644
--- a/lib/plugins/aws/lib/monitorStack.test.js
+++ b/lib/plugins/aws/lib/monitorStack.test.js
@@ -467,7 +467,7 @@ describe('monitorStack', () => {
describeStackEventsStub.onCall(3).resolves(updateRollbackComplete);
return awsPlugin.monitorStack('update', cfDataMock, 10).catch((e) => {
- let errorMessage = 'An error occurred while provisioning your stack: ';
+ let errorMessage = 'An error occurred: ';
errorMessage += 'mochaS3 - Bucket already exists.';
expect(e.name).to.be.equal('ServerlessError');
expect(e.message).to.be.equal(errorMessage);
@@ -628,7 +628,7 @@ describe('monitorStack', () => {
describeStackEventsStub.onCall(3).resolves(updateRollbackFailedEvent);
return awsPlugin.monitorStack('update', cfDataMock, 10).catch((e) => {
- let errorMessage = 'An error occurred while provisioning your stack: ';
+ let errorMessage = 'An error occurred: ';
errorMessage += 'mochaS3 - Bucket already exists.';
expect(e.name).to.be.equal('ServerlessError');
expect(e.message).to.be.equal(errorMessage);
@@ -647,6 +647,168 @@ describe('monitorStack', () => {
});
});
+ it('should throw an error and exit immediately if stack status is DELETE_FAILED', () => {
+ const describeStackEventsStub = sinon.stub(awsPlugin.provider, 'request');
+ const cfDataMock = {
+ StackId: 'new-service-dev',
+ };
+ const deleteStartEvent = {
+ StackEvents: [
+ {
+ EventId: '1a2b3c4d',
+ StackName: 'new-service-dev',
+ LogicalResourceId: 'new-service-dev',
+ ResourceType: 'AWS::CloudFormation::Stack',
+ Timestamp: new Date(),
+ ResourceStatus: 'DELETE_IN_PROGRESS',
+ },
+ ],
+ };
+ const deleteItemEvent = {
+ StackEvents: [
+ {
+ EventId: '1e2f3g4h',
+ StackName: 'new-service-dev',
+ LogicalResourceId: 'mochaLambda',
+ ResourceType: 'AWS::Lambda::Function',
+ Timestamp: new Date(),
+ ResourceStatus: 'DELETE_IN_PROGRESS',
+ },
+ ],
+ };
+ const deleteItemFailedEvent = {
+ StackEvents: [
+ {
+ EventId: '1i2j3k4l',
+ StackName: 'new-service-dev',
+ LogicalResourceId: 'mochaLambda',
+ ResourceType: 'AWS::Lambda::Function',
+ Timestamp: new Date(),
+ ResourceStatus: 'DELETE_FAILED',
+ ResourceStatusReason: 'You are not authorized to perform this operation',
+ },
+ ],
+ };
+ const deleteFailedEvent = {
+ StackEvents: [
+ {
+ EventId: '1m2n3o4p',
+ StackName: 'new-service-dev',
+ LogicalResourceId: 'new-service-dev',
+ ResourceType: 'AWS::CloudFormation::Stack',
+ Timestamp: new Date(),
+ ResourceStatus: 'DELETE_FAILED',
+ },
+ ],
+ };
+
+ describeStackEventsStub.onCall(0).resolves(deleteStartEvent);
+ describeStackEventsStub.onCall(1).resolves(deleteItemEvent);
+ describeStackEventsStub.onCall(2).resolves(deleteItemFailedEvent);
+ describeStackEventsStub.onCall(3).resolves(deleteFailedEvent);
+
+ return awsPlugin.monitorStack('removal', cfDataMock, 10).catch((e) => {
+ let errorMessage = 'An error occurred: ';
+ errorMessage += 'mochaLambda - You are not authorized to perform this operation.';
+ expect(e.name).to.be.equal('ServerlessError');
+ expect(e.message).to.be.equal(errorMessage);
+ // callCount is 2 because Serverless will immediately exits and shows the error
+ expect(describeStackEventsStub.callCount).to.be.equal(3);
+ expect(describeStackEventsStub.calledWithExactly(
+ 'CloudFormation',
+ 'describeStackEvents',
+ {
+ StackName: cfDataMock.StackId,
+ },
+ awsPlugin.options.stage,
+ awsPlugin.options.region
+ )).to.be.equal(true);
+ awsPlugin.provider.request.restore();
+ });
+ });
+
+ it('should throw an error if stack status is DELETE_FAILED and should output all ' +
+ 'stack events information with the --verbose option', () => {
+ awsPlugin.options.verbose = true;
+ const describeStackEventsStub = sinon.stub(awsPlugin.provider, 'request');
+ const cfDataMock = {
+ StackId: 'new-service-dev',
+ };
+ const deleteStartEvent = {
+ StackEvents: [
+ {
+ EventId: '1a2b3c4d',
+ StackName: 'new-service-dev',
+ LogicalResourceId: 'new-service-dev',
+ ResourceType: 'AWS::CloudFormation::Stack',
+ Timestamp: new Date(),
+ ResourceStatus: 'DELETE_IN_PROGRESS',
+ },
+ ],
+ };
+ const deleteItemEvent = {
+ StackEvents: [
+ {
+ EventId: '1e2f3g4h',
+ StackName: 'new-service-dev',
+ LogicalResourceId: 'mochaLambda',
+ ResourceType: 'AWS::Lambda::Function',
+ Timestamp: new Date(),
+ ResourceStatus: 'DELETE_IN_PROGRESS',
+ },
+ ],
+ };
+ const deleteItemFailedEvent = {
+ StackEvents: [
+ {
+ EventId: '1i2j3k4l',
+ StackName: 'new-service-dev',
+ LogicalResourceId: 'mochaLambda',
+ ResourceType: 'AWS::Lambda::Function',
+ Timestamp: new Date(),
+ ResourceStatus: 'DELETE_FAILED',
+ ResourceStatusReason: 'You are not authorized to perform this operation',
+ },
+ ],
+ };
+ const deleteFailedEvent = {
+ StackEvents: [
+ {
+ EventId: '1m2n3o4p',
+ StackName: 'new-service-dev',
+ LogicalResourceId: 'new-service-dev',
+ ResourceType: 'AWS::CloudFormation::Stack',
+ Timestamp: new Date(),
+ ResourceStatus: 'DELETE_FAILED',
+ },
+ ],
+ };
+
+ describeStackEventsStub.onCall(0).resolves(deleteStartEvent);
+ describeStackEventsStub.onCall(1).resolves(deleteItemEvent);
+ describeStackEventsStub.onCall(2).resolves(deleteItemFailedEvent);
+ describeStackEventsStub.onCall(3).resolves(deleteFailedEvent);
+
+ return awsPlugin.monitorStack('removal', cfDataMock, 10).catch((e) => {
+ let errorMessage = 'An error occurred: ';
+ errorMessage += 'mochaLambda - You are not authorized to perform this operation.';
+ expect(e.name).to.be.equal('ServerlessError');
+ expect(e.message).to.be.equal(errorMessage);
+ // callCount is 2 because Serverless will immediately exits and shows the error
+ expect(describeStackEventsStub.callCount).to.be.equal(4);
+ expect(describeStackEventsStub.calledWithExactly(
+ 'CloudFormation',
+ 'describeStackEvents',
+ {
+ StackName: cfDataMock.StackId,
+ },
+ awsPlugin.options.stage,
+ awsPlugin.options.region
+ )).to.be.equal(true);
+ awsPlugin.provider.request.restore();
+ });
+ });
+
it('should record an error and fail if status is UPDATE_ROLLBACK_IN_PROGRESS', () => {
const describeStackEventsStub = sinon.stub(awsPlugin.provider, 'request');
const cfDataMock = {
@@ -692,7 +854,7 @@ describe('monitorStack', () => {
describeStackEventsStub.onCall(2).resolves(updateRollbackCompleteEvent);
return awsPlugin.monitorStack('update', cfDataMock, 10).catch((e) => {
- let errorMessage = 'An error occurred while provisioning your stack: ';
+ let errorMessage = 'An error occurred: ';
errorMessage += 'mocha - Export is in use.';
expect(e.name).to.be.equal('ServerlessError');
expect(e.message).to.be.equal(errorMessage);
diff --git a/lib/plugins/aws/provider/awsProvider.js b/lib/plugins/aws/provider/awsProvider.js
index c7354fb43..fffecdef6 100644
--- a/lib/plugins/aws/provider/awsProvider.js
+++ b/lib/plugins/aws/provider/awsProvider.js
@@ -195,21 +195,19 @@ class AwsProvider {
const result = {};
const stageUpper = this.getStage() ? this.getStage().toUpperCase() : null;
- let profile;
- if (this.options['aws-profile']) {
- profile = this.options['aws-profile'];
- } else if (this.serverless.service.provider.profile) {
- profile = this.serverless.service.provider.profile;
- }
-
// add specified credentials, overriding with more specific declarations
impl.addCredentials(result, this.serverless.service.provider.credentials); // config creds
- impl.addProfileCredentials(result, profile);
+ if (this.serverless.service.provider.profile) {
+ // config profile
+ impl.addProfileCredentials(result, this.serverless.service.provider.profile);
+ }
impl.addEnvironmentCredentials(result, 'AWS'); // creds for all stages
impl.addEnvironmentProfile(result, 'AWS');
impl.addEnvironmentCredentials(result, `AWS_${stageUpper}`); // stage specific creds
impl.addEnvironmentProfile(result, `AWS_${stageUpper}`);
-
+ if (this.options['aws-profile']) {
+ impl.addProfileCredentials(result, this.options['aws-profile']); // CLI option profile
+ }
result.region = this.getRegion();
const deploymentBucketObject = this.serverless.service.provider.deploymentBucketObject;
diff --git a/lib/plugins/aws/provider/awsProvider.test.js b/lib/plugins/aws/provider/awsProvider.test.js
index f4b8e7705..12bb50f07 100644
--- a/lib/plugins/aws/provider/awsProvider.test.js
+++ b/lib/plugins/aws/provider/awsProvider.test.js
@@ -461,6 +461,7 @@ describe('AwsProvider', () => {
});
it('should get credentials when profile is provied via --aws-profile option', () => {
+ process.env.AWS_PROFILE = 'envDefault';
newAwsProvider.options['aws-profile'] = 'notDefault';
const credentials = newAwsProvider.getCredentials();
diff --git a/lib/plugins/aws/remove/lib/stack.js b/lib/plugins/aws/remove/lib/stack.js
index 71ef16590..4b4ce182f 100644
--- a/lib/plugins/aws/remove/lib/stack.js
+++ b/lib/plugins/aws/remove/lib/stack.js
@@ -5,7 +5,7 @@ const BbPromise = require('bluebird');
module.exports = {
remove() {
this.serverless.cli.log('Removing Stack...');
- const stackName = `${this.serverless.service.service}-${this.options.stage}`;
+ const stackName = this.provider.naming.getStackName();
const params = {
StackName: stackName,
};
diff --git a/lib/plugins/create/create.js b/lib/plugins/create/create.js
index eb62cc843..76efe88f8 100644
--- a/lib/plugins/create/create.js
+++ b/lib/plugins/create/create.js
@@ -9,6 +9,8 @@ const userStats = require('../../utils/userStats');
// class wide constants
const validTemplates = [
'aws-nodejs',
+ 'aws-nodejs-typescript',
+ 'aws-nodejs-ecma-script',
'aws-python',
'aws-python3',
'aws-groovy-gradle',
@@ -18,10 +20,12 @@ const validTemplates = [
'aws-csharp',
'aws-fsharp',
'azure-nodejs',
+ 'google-nodejs',
+ 'kubeless-python',
+ 'kubeless-nodejs',
'openwhisk-nodejs',
'openwhisk-python',
'openwhisk-swift',
- 'google-nodejs',
'plugin',
// this template is used to streamline the onboarding process
diff --git a/lib/plugins/create/create.test.js b/lib/plugins/create/create.test.js
index f77496b3d..90b03a5f4 100644
--- a/lib/plugins/create/create.test.js
+++ b/lib/plugins/create/create.test.js
@@ -99,6 +99,46 @@ describe('Create', () => {
});
});
+ it('should generate scaffolding for "aws-nodejs-typescript" template', () => {
+ process.chdir(tmpDir);
+ create.options.template = 'aws-nodejs-typescript';
+
+ return create.create().then(() => {
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'serverless.yml')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'handler.ts')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'tsconfig.json')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'package.json')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'webpack.config.js')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, '.gitignore')))
+ .to.be.equal(true);
+ });
+ });
+
+ it('should generate scaffolding for "aws-nodejs-ecma-script" template', () => {
+ process.chdir(tmpDir);
+ create.options.template = 'aws-nodejs-ecma-script';
+
+ return create.create().then(() => {
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'serverless.yml')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'first.js')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'second.js')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'package.json')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'webpack.config.js')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, '.gitignore')))
+ .to.be.equal(true);
+ });
+ });
+
it('should generate scaffolding for "aws-csharp" template', () => {
process.chdir(tmpDir);
create.options.template = 'aws-csharp';
@@ -387,6 +427,38 @@ describe('Create', () => {
});
});
+ it('should generate scaffolding for "kubeless-python" template', () => {
+ process.chdir(tmpDir);
+ create.options.template = 'kubeless-python';
+
+ return create.create().then(() => {
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'package.json')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'serverless.yml')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'handler.py')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, '.gitignore')))
+ .to.be.equal(true);
+ });
+ });
+
+ it('should generate scaffolding for "kubeless-nodejs" template', () => {
+ process.chdir(tmpDir);
+ create.options.template = 'kubeless-nodejs';
+
+ return create.create().then(() => {
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'package.json')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'serverless.yml')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'handler.js')))
+ .to.be.equal(true);
+ expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, '.gitignore')))
+ .to.be.equal(true);
+ });
+ });
+
it('should generate scaffolding for "plugin" template', () => {
process.chdir(tmpDir);
create.options.template = 'plugin';
diff --git a/lib/plugins/create/templates/aws-nodejs-ecma-script/first.js b/lib/plugins/create/templates/aws-nodejs-ecma-script/first.js
new file mode 100644
index 000000000..8b8e34077
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-ecma-script/first.js
@@ -0,0 +1,12 @@
+// eslint-disable-next-line import/prefer-default-export
+export const hello = (event, context, callback) => {
+ const p = new Promise((resolve) => {
+ resolve('success');
+ });
+ p
+ .then(() => callback(null, {
+ message: 'Go Serverless Webpack (Ecma Script) v1.0! First module!',
+ event,
+ }))
+ .catch(e => callback(e));
+};
diff --git a/lib/plugins/create/templates/aws-nodejs-ecma-script/gitignore b/lib/plugins/create/templates/aws-nodejs-ecma-script/gitignore
new file mode 100644
index 000000000..983749343
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-ecma-script/gitignore
@@ -0,0 +1,9 @@
+# package directories
+node_modules
+jspm_packages
+
+# Serverless directories
+.serverless
+
+# Webpack directories
+.webpack
\ No newline at end of file
diff --git a/lib/plugins/create/templates/aws-nodejs-ecma-script/package.json b/lib/plugins/create/templates/aws-nodejs-ecma-script/package.json
new file mode 100644
index 000000000..e6e8c12a2
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-ecma-script/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "aws-nodejs-ecma-script",
+ "version": "1.0.0",
+ "description": "Serverless webpack example using ecma script",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "devDependencies": {
+ "babel-core": "^6.25.0",
+ "babel-loader": "^7.1.1",
+ "babel-plugin-transform-runtime": "^6.23.0",
+ "babel-polyfill": "^6.23.0",
+ "babel-preset-env": "^1.6.0",
+ "serverless-webpack": "^2.2.0",
+ "webpack": "^3.3.0"
+ },
+ "author": "The serverless webpack authors (https://github.com/elastic-coders/serverless-webpack)",
+ "license": "MIT"
+}
\ No newline at end of file
diff --git a/lib/plugins/create/templates/aws-nodejs-ecma-script/second.js b/lib/plugins/create/templates/aws-nodejs-ecma-script/second.js
new file mode 100644
index 000000000..8da564f9e
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-ecma-script/second.js
@@ -0,0 +1,16 @@
+// eslint-disable-next-line import/prefer-default-export
+export const hello = (event, context, cb) => {
+ const p = new Promise((resolve) => {
+ resolve('success');
+ });
+ const response = {
+ statusCode: 200,
+ body: JSON.stringify({
+ message: 'Go Serverless Webpack (Ecma Script) v1.0! Second module!',
+ input: event,
+ }),
+ };
+ p
+ .then(() => cb(null, response))
+ .catch(e => cb(e));
+};
diff --git a/lib/plugins/create/templates/aws-nodejs-ecma-script/serverless.yml b/lib/plugins/create/templates/aws-nodejs-ecma-script/serverless.yml
new file mode 100644
index 000000000..f732c5a9c
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-ecma-script/serverless.yml
@@ -0,0 +1,27 @@
+service:
+ name: aws-nodejs-ecma-script
+
+# Add the serverless-webpack plugin
+plugins:
+ - serverless-webpack
+
+provider:
+ name: aws
+ runtime: nodejs6.10
+
+functions:
+ # Example without LAMBDA-PROXY integration
+ # Invoking locally:
+ # sls webpack invoke -f first
+ first:
+ handler: first.hello
+ # Example with LAMBDA-PROXY integration
+ # Invoking locally:
+ # sls webpack invoke -f second
+ second:
+ handler: second.hello
+ events:
+ - http:
+ method: get
+ path: second
+ integration: lambda
diff --git a/lib/plugins/create/templates/aws-nodejs-ecma-script/webpack.config.js b/lib/plugins/create/templates/aws-nodejs-ecma-script/webpack.config.js
new file mode 100644
index 000000000..4d173e306
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-ecma-script/webpack.config.js
@@ -0,0 +1,21 @@
+const path = require('path');
+// eslint-disable-next-line import/no-unresolved
+const slsw = require('serverless-webpack');
+
+module.exports = {
+ entry: slsw.lib.entries,
+ target: 'node',
+ module: {
+ loaders: [{
+ test: /\.js$/,
+ loaders: ['babel-loader'],
+ include: __dirname,
+ exclude: /node_modules/,
+ }],
+ },
+ output: {
+ libraryTarget: 'commonjs',
+ path: path.join(__dirname, '.webpack'),
+ filename: '[name].js',
+ },
+};
diff --git a/lib/plugins/create/templates/aws-nodejs-typescript/gitignore b/lib/plugins/create/templates/aws-nodejs-typescript/gitignore
new file mode 100644
index 000000000..983749343
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-typescript/gitignore
@@ -0,0 +1,9 @@
+# package directories
+node_modules
+jspm_packages
+
+# Serverless directories
+.serverless
+
+# Webpack directories
+.webpack
\ No newline at end of file
diff --git a/lib/plugins/create/templates/aws-nodejs-typescript/handler.ts b/lib/plugins/create/templates/aws-nodejs-typescript/handler.ts
new file mode 100644
index 000000000..280d14b94
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-typescript/handler.ts
@@ -0,0 +1,3 @@
+export const hello = (event, context, cb) => cb(null,
+ { message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!', event }
+);
\ No newline at end of file
diff --git a/lib/plugins/create/templates/aws-nodejs-typescript/package.json b/lib/plugins/create/templates/aws-nodejs-typescript/package.json
new file mode 100644
index 000000000..dd30cbaae
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-typescript/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "aws-nodejs-typescript",
+ "version": "1.0.0",
+ "description": "Serverless webpack example using Typescript",
+ "main": "handler.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "devDependencies": {
+ "serverless-webpack": "^2.2.0",
+ "ts-loader": "^2.3.1",
+ "typescript": "^2.4.2",
+ "webpack": "^3.3.0"
+ },
+ "author": "The serverless webpack authors (https://github.com/elastic-coders/serverless-webpack)",
+ "license": "MIT"
+}
\ No newline at end of file
diff --git a/lib/plugins/create/templates/aws-nodejs-typescript/serverless.yml b/lib/plugins/create/templates/aws-nodejs-typescript/serverless.yml
new file mode 100644
index 000000000..ec6923fd5
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-typescript/serverless.yml
@@ -0,0 +1,22 @@
+service:
+ name: aws-nodejs-typescript
+
+# Add the serverless-webpack plugin
+plugins:
+ - serverless-webpack
+
+provider:
+ name: aws
+ runtime: nodejs6.10
+
+functions:
+ # Example with LAMBDA-PROXY integration
+ # Invoking locally:
+ # sls webpack invoke -f hello
+ hello:
+ handler: handler.hello
+ events:
+ - http:
+ method: get
+ path: hello
+ integration: lambda
diff --git a/lib/plugins/create/templates/aws-nodejs-typescript/tsconfig.json b/lib/plugins/create/templates/aws-nodejs-typescript/tsconfig.json
new file mode 100644
index 000000000..8415c58c4
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-typescript/tsconfig.json
@@ -0,0 +1,5 @@
+{
+ "compilerOptions": {
+ "sourceMap": true
+ }
+}
diff --git a/lib/plugins/create/templates/aws-nodejs-typescript/webpack.config.js b/lib/plugins/create/templates/aws-nodejs-typescript/webpack.config.js
new file mode 100644
index 000000000..58534724e
--- /dev/null
+++ b/lib/plugins/create/templates/aws-nodejs-typescript/webpack.config.js
@@ -0,0 +1,18 @@
+const path = require('path');
+// eslint-disable-next-line import/no-unresolved
+const slsw = require('serverless-webpack');
+
+module.exports = {
+ entry: slsw.lib.entries,
+ output: {
+ libraryTarget: 'commonjs',
+ path: path.join(__dirname, '.webpack'),
+ filename: '[name].js',
+ },
+ target: 'node',
+ module: {
+ loaders: [
+ { test: /\.ts(x?)$/, loader: 'ts-loader' },
+ ],
+ },
+};
diff --git a/lib/plugins/create/templates/azure-nodejs/serverless.yml b/lib/plugins/create/templates/azure-nodejs/serverless.yml
index 0db7a9677..b529a4ea2 100644
--- a/lib/plugins/create/templates/azure-nodejs/serverless.yml
+++ b/lib/plugins/create/templates/azure-nodejs/serverless.yml
@@ -42,7 +42,7 @@ functions:
authLevel : anonymous
- http: true
x-azure-settings:
- diections: out
+ direction: out
name: res
# The following are a few examples of other events you can configure:
diff --git a/lib/plugins/create/templates/kubeless-nodejs/gitignore b/lib/plugins/create/templates/kubeless-nodejs/gitignore
new file mode 100644
index 000000000..2b48c8bd5
--- /dev/null
+++ b/lib/plugins/create/templates/kubeless-nodejs/gitignore
@@ -0,0 +1,6 @@
+# package directories
+node_modules
+jspm_packages
+
+# Serverless directories
+.serverless
\ No newline at end of file
diff --git a/lib/plugins/create/templates/kubeless-nodejs/handler.js b/lib/plugins/create/templates/kubeless-nodejs/handler.js
new file mode 100644
index 000000000..1ed9667ac
--- /dev/null
+++ b/lib/plugins/create/templates/kubeless-nodejs/handler.js
@@ -0,0 +1,17 @@
+'use strict';
+
+const _ = require('lodash');
+
+module.exports = {
+ capitalize(req, res) {
+ let body = [];
+ req.on('error', (err) => {
+ console.error(err);
+ }).on('data', (chunk) => {
+ body.push(chunk);
+ }).on('end', () => {
+ body = Buffer.concat(body).toString();
+ res.end(_.capitalize(body));
+ });
+ },
+};
diff --git a/lib/plugins/create/templates/kubeless-nodejs/package.json b/lib/plugins/create/templates/kubeless-nodejs/package.json
new file mode 100644
index 000000000..d09d445ff
--- /dev/null
+++ b/lib/plugins/create/templates/kubeless-nodejs/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "kubeless-nodejs",
+ "version": "1.0.0",
+ "description": "Example function for serverless kubeless",
+ "dependencies": {
+ "serverless-kubeless": "^0.1.8",
+ "lodash": "^4.1.0"
+ },
+ "devDependencies": {},
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "serverless",
+ "kubeless"
+ ],
+ "author": "The Kubeless Authors",
+ "license": "Apache-2.0"
+}
diff --git a/lib/plugins/create/templates/kubeless-nodejs/serverless.yml b/lib/plugins/create/templates/kubeless-nodejs/serverless.yml
new file mode 100644
index 000000000..af3ea9fe7
--- /dev/null
+++ b/lib/plugins/create/templates/kubeless-nodejs/serverless.yml
@@ -0,0 +1,27 @@
+# Welcome to Serverless!
+#
+# For full config options, check the kubeless plugin docs:
+# https://github.com/serverless/serverless-kubeless
+#
+# For documentation on kubeless itself:
+# http://kubeless.io
+
+# Update the service name below with your own service name
+service: capitalize
+
+# Please ensure the serverless-kubeless provider plugin is installed globally.
+# $ npm install -g serverless-kubeless
+#
+# ...before installing project dependencies to register this provider.
+# $ npm install
+
+provider:
+ name: kubeless
+ runtime: nodejs6
+
+plugins:
+ - serverless-kubeless
+
+functions:
+ capitalize:
+ handler: handler.capitalize
diff --git a/lib/plugins/create/templates/kubeless-python/gitignore b/lib/plugins/create/templates/kubeless-python/gitignore
new file mode 100644
index 000000000..2b48c8bd5
--- /dev/null
+++ b/lib/plugins/create/templates/kubeless-python/gitignore
@@ -0,0 +1,6 @@
+# package directories
+node_modules
+jspm_packages
+
+# Serverless directories
+.serverless
\ No newline at end of file
diff --git a/lib/plugins/create/templates/kubeless-python/handler.py b/lib/plugins/create/templates/kubeless-python/handler.py
new file mode 100644
index 000000000..3b176717f
--- /dev/null
+++ b/lib/plugins/create/templates/kubeless-python/handler.py
@@ -0,0 +1,14 @@
+import json
+
+def hello(request):
+ body = {
+ "message": "Go Serverless v1.0! Your function executed successfully!",
+ "input": request.json
+ }
+
+ response = {
+ "statusCode": 200,
+ "body": json.dumps(body)
+ }
+
+ return response
diff --git a/lib/plugins/create/templates/kubeless-python/package.json b/lib/plugins/create/templates/kubeless-python/package.json
new file mode 100644
index 000000000..58b82e524
--- /dev/null
+++ b/lib/plugins/create/templates/kubeless-python/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "kubeless-python",
+ "version": "1.0.0",
+ "description": "Sample Kubeless Python serverless framework service.",
+ "dependencies": {
+ "serverless-kubeless": "^0.1.8"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "serverless",
+ "kubeless"
+ ],
+ "author": "The Kubeless Authors",
+ "license": "Apache-2.0"
+}
diff --git a/lib/plugins/create/templates/kubeless-python/serverless.yml b/lib/plugins/create/templates/kubeless-python/serverless.yml
new file mode 100644
index 000000000..310d0d1df
--- /dev/null
+++ b/lib/plugins/create/templates/kubeless-python/serverless.yml
@@ -0,0 +1,27 @@
+# Welcome to Serverless!
+#
+# For full config options, check the kubeless plugin docs:
+# https://github.com/serverless/serverless-kubeless
+#
+# For documentation on kubeless itself:
+# http://kubeless.io
+
+# Update the service name below with your own service name
+service: hello-world
+
+# Please ensure the serverless-kubeless provider plugin is installed globally.
+# $ npm install -g serverless-kubeless
+#
+# ...before installing project dependencies to register this provider.
+# $ npm install
+
+provider:
+ name: kubeless
+ runtime: python2.7
+
+plugins:
+ - serverless-kubeless
+
+functions:
+ hello:
+ handler: handler.hello
diff --git a/lib/plugins/emit/index.js b/lib/plugins/emit/index.js
new file mode 100644
index 000000000..89745a241
--- /dev/null
+++ b/lib/plugins/emit/index.js
@@ -0,0 +1,160 @@
+'use strict';
+
+const os = require('os');
+const BbPromise = require('bluebird');
+const fdk = require('@serverless/fdk');
+const path = require('path');
+const stdin = require('get-stdin');
+const getAuthToken = require('../../utils/getAuthToken');
+const userStats = require('../../utils/userStats');
+const chalk = require('chalk');
+
+const spaceSmall = ' ';
+const spaceLarge = ' ';
+const colorDim = chalk.hex('#777777');
+const colorPrefix = chalk.hex('#bdb018');
+const prefix = colorPrefix(` Serverless ${spaceSmall}`);
+
+const prettifyValue = value => {
+ const prettified = JSON.stringify(value, null, 2).replace(
+ new RegExp('\\n', 'g'),
+ `\n${spaceLarge}`
+ );
+ return `${spaceLarge}${colorDim(prettified)}`;
+};
+
+class Emit {
+ constructor(serverless, options) {
+ this.serverless = serverless;
+ this.options = options || {};
+ this.data = null;
+
+ this.commands = {
+ emit: {
+ usage: 'Emits an event to a running Event Gateway',
+ lifecycleEvents: ['emit'],
+ options: {
+ name: {
+ usage: 'Event type',
+ required: true,
+ shortcut: 'n',
+ },
+ path: {
+ usage: 'Path to JSON or YAML file holding input data',
+ shortcut: 'p',
+ },
+ data: {
+ usage: 'Input data',
+ shortcut: 'd',
+ },
+ url: {
+ usage: 'Event Gateway address',
+ shortcut: 'u',
+ },
+ datatype: {
+ usage: 'Data type for the input data. By default set to application/json',
+ shortcut: 't',
+ },
+ },
+ platform: true,
+ },
+ };
+
+ this.hooks = {
+ 'emit:emit': () =>
+ BbPromise.bind(this)
+ .then(this.retrieveData)
+ .then(this.parseData)
+ .then(this.emitEvent),
+ };
+ }
+
+ retrieveData() {
+ return new BbPromise((resolve, reject) => {
+ if (this.options.data) {
+ if (this.options.datatype) {
+ this.data = this.options.data;
+ resolve();
+ } else {
+ try {
+ this.data = JSON.parse(this.options.data);
+ resolve();
+ } catch (exception) {
+ reject(new Error("Couldn't parse the provided data to a JSON structure."));
+ }
+ }
+ } else if (this.options.path) {
+ const absolutePath = path.isAbsolute(this.options.path)
+ ? this.options.path
+ : path.join(this.serverless.config.servicePath, this.options.path);
+ if (!this.serverless.utils.fileExistsSync(absolutePath)) {
+ reject(new Error('The file you provided does not exist.'));
+ }
+ this.data = this.serverless.utils.readFileSync(absolutePath);
+ resolve();
+ } else {
+ try {
+ stdin().then(input => {
+ if (this.options.datatype) {
+ this.data = this.options.data;
+ resolve();
+ } else {
+ try {
+ this.data = JSON.parse(input);
+ resolve();
+ } catch (exception) {
+ reject(new Error("Couldn't parse the provided data to a JSON structure."));
+ }
+ resolve();
+ }
+ });
+ } catch (exception) {
+ reject(
+ new Error(
+ 'Event data is missing. Please provide it either via stdin or the args: data or path.'
+ )
+ );
+ }
+ }
+ });
+ }
+
+ emitEvent() {
+ const authToken = getAuthToken();
+ if (!authToken) {
+ return BbPromise.reject(new this.serverless.classes
+ .Error('Must be logged in to use this command. Please run "serverless login".'));
+ }
+
+ userStats.track('service_emitted');
+ const url = this.options.url || 'http://localhost:4000';
+ const eventGateway = fdk.eventGateway({
+ url,
+ });
+
+ const name = this.options.name;
+ const data = this.data;
+ const emitParams = {
+ event: name,
+ data,
+ };
+ if (this.options.datatype) {
+ emitParams.dataType = this.options.datatype;
+ }
+ return eventGateway
+ .emit(emitParams)
+ .then(() => {
+ const msg = `${prefix}Emitted the event ${name} as datatype ${emitParams.dataType ||
+ 'application/json'}:`;
+ this.serverless.cli.consoleLog(`${msg}${os.EOL}${prettifyValue(data)}`);
+ })
+ .catch(() => {
+ const msg = `${prefix}Failed to emit the event ${name} as datatype ${emitParams.dataType ||
+ 'application/json'}:`;
+ this.serverless.cli.consoleLog(`${msg}${os.EOL}${prettifyValue(data)}`);
+ throw new Error(`Failed to emit the event ${name}`);
+ });
+ }
+}
+
+module.exports = Emit;
diff --git a/lib/plugins/emit/index.test.js b/lib/plugins/emit/index.test.js
new file mode 100644
index 000000000..dd859cde3
--- /dev/null
+++ b/lib/plugins/emit/index.test.js
@@ -0,0 +1,240 @@
+'use strict';
+
+const chai = require('chai');
+const sinon = require('sinon');
+const proxyquire = require('proxyquire');
+const path = require('path');
+const os = require('os');
+const Serverless = require('../../Serverless');
+const testUtils = require('../../../tests/utils');
+const CLI = require('../../classes/CLI');
+
+chai.use(require('chai-as-promised'));
+
+const expect = chai.expect;
+
+describe('Emit', () => {
+ describe('#constructor()', () => {
+ let emit;
+ let serverless;
+ let emitEventStub;
+
+ beforeEach(() => {
+ serverless = new Serverless();
+ serverless.cli = new CLI(serverless);
+ emitEventStub = sinon.stub().resolves();
+ const Emit = proxyquire('./index', {
+ '@serverless/fdk': {
+ eventGateway: () => ({
+ emit: emitEventStub,
+ }),
+ },
+ });
+ emit = new Emit(serverless);
+ });
+
+ it('should have commands', () => expect(emit.commands).to.be.not.empty);
+ it('should have hooks', () => expect(emit.hooks).to.be.not.empty);
+
+ it('should run promise chain in order', () => {
+ const retrieveDataStub = sinon.stub(emit, 'retrieveData').resolves();
+ emitEventStub = sinon.stub(emit, 'emitEvent').resolves();
+
+ return emit.hooks['emit:emit']().then(() => {
+ expect(retrieveDataStub.calledOnce).to.be.equal(true);
+ expect(emitEventStub.calledAfter(retrieveDataStub)).to.be.equal(true);
+
+ emit.retrieveData.restore();
+ emit.emitEvent.restore();
+ });
+ });
+ });
+
+ describe('#retrieveData()', () => {
+ let emit;
+ let serverless;
+ let emitEventStub;
+
+ beforeEach(() => {
+ serverless = new Serverless();
+ serverless.cli = new CLI(serverless);
+ emitEventStub = sinon.stub().resolves();
+ const Emit = proxyquire('./index', {
+ '@serverless/fdk': {
+ eventGateway: () => ({
+ emit: emitEventStub,
+ }),
+ },
+ });
+ emit = new Emit(serverless);
+ });
+
+ it('should use the data args if provided over path', () => {
+ emit.options.path = '/some/path';
+ emit.options.data = '{"key": "value"}';
+ return emit.retrieveData().then(() => {
+ expect(emit.data).to.deep.equal({ key: 'value' });
+ });
+ });
+
+ it('should use and prase the data args if provided', () => {
+ emit.options.data = '{"key": "value"}';
+ return emit.retrieveData().then(() => {
+ expect(emit.data).to.deep.equal({ key: 'value' });
+ });
+ });
+
+ it('should use and not parse the data args if a datatype is provided', () => {
+ emit.options.data = 'Hello World';
+ emit.options.datatype = 'text/plain';
+ return emit.retrieveData().then(() => {
+ expect(emit.data).to.deep.equal('Hello World');
+ });
+ });
+
+ it('it should parse the file if a relative file path is provided', () => {
+ serverless.config.servicePath = testUtils.getTmpDirPath();
+ const data = { testProp: 'testValue' };
+ serverless.utils.writeFileSync(
+ path.join(serverless.config.servicePath, 'data.json'),
+ JSON.stringify(data)
+ );
+ emit.options.path = 'data.json';
+
+ return emit.retrieveData().then(() => {
+ expect(emit.data).to.deep.equal(data);
+ });
+ });
+
+ it('it should parse the file if an absolute file path is provided', () => {
+ serverless.config.servicePath = testUtils.getTmpDirPath();
+ const data = { testProp: 'testValue' };
+ const dataFile = path.join(serverless.config.servicePath, 'data.json');
+ serverless.utils.writeFileSync(dataFile, JSON.stringify(data));
+ emit.options.path = dataFile;
+
+ return emit.retrieveData().then(() => {
+ expect(emit.data).to.deep.equal(data);
+ });
+ });
+
+ it('it should parse a yaml file if a file path is provided', () => {
+ serverless.config.servicePath = testUtils.getTmpDirPath();
+ const yamlContent = 'testProp: testValue';
+
+ serverless.utils.writeFileSync(
+ path.join(serverless.config.servicePath, 'data.yml'),
+ yamlContent
+ );
+ emit.options.path = 'data.yml';
+
+ return emit.retrieveData().then(() => {
+ expect(emit.data).to.deep.equal({
+ testProp: 'testValue',
+ });
+ });
+ });
+
+ it('it should throw error if the file path does not exist', () => {
+ serverless.config.servicePath = testUtils.getTmpDirPath();
+ emit.options.path = 'some/path';
+
+ return emit.retrieveData().catch(err => {
+ expect(err).to.be.an.instanceOf(Error);
+ expect(err.message).to.equal('The file you provided does not exist.');
+ });
+ });
+ });
+
+ describe('#emitEvent() - logged in', () => {
+ let emit;
+ let serverless;
+ let emitEventStub;
+ let logStub;
+
+ beforeEach(() => {
+ serverless = new Serverless();
+ serverless.cli = new CLI(serverless);
+ emitEventStub = sinon.stub().resolves();
+ const Emit = proxyquire('./index', {
+ '@serverless/fdk': {
+ eventGateway: () => ({
+ emit: emitEventStub,
+ }),
+ },
+ '../../utils/getAuthToken': () => 'abc123',
+ });
+ emit = new Emit(serverless);
+ logStub = sinon.stub(emit.serverless.cli, 'consoleLog');
+ });
+ it('should emit an event using the name args', () => {
+ emit.options.name = 'userCreated';
+ emit.data = { key: 'value' };
+ return emit.emitEvent().then(() => {
+ expect(emitEventStub.calledOnce).to.equal(true);
+ expect(
+ emitEventStub.calledWithMatch({
+ event: emit.options.name,
+ data: emit.data,
+ })
+ ).to.equal(true);
+ expect(logStub.getCall(0).args[0]).to.equal([
+ ' Serverless Emitted the event userCreated as datatype application/json:',
+ ' {\n "key": "value"\n }',
+ ].join(os.EOL));
+ });
+ });
+
+ it('should emit an event with a custom datatype', () => {
+ emit.options.name = 'userCreated';
+ emit.options.datatype = 'text/plain';
+ emit.data = 'This is a message';
+ return emit.emitEvent().then(() => {
+ expect(emitEventStub.calledOnce).to.equal(true);
+ expect(
+ emitEventStub.calledWithMatch({
+ event: emit.options.name,
+ data: emit.data,
+ dataType: 'text/plain',
+ })
+ ).to.equal(true);
+ expect(logStub.getCall(0).args[0]).to.equal([
+ ' Serverless Emitted the event userCreated as datatype text/plain:',
+ ' "This is a message"',
+ ].join(os.EOL));
+ });
+ });
+ });
+
+ describe('#emitEvent() - logged out', () => {
+ let emit;
+ let serverless;
+ let emitEventStub;
+
+ beforeEach(() => {
+ serverless = new Serverless();
+ serverless.cli = new CLI(serverless);
+ emitEventStub = sinon.stub().resolves();
+ const Emit = proxyquire('./index', {
+ '@serverless/fdk': {
+ eventGateway: () => ({
+ emit: emitEventStub,
+ }),
+ },
+ '../../utils/getAuthToken': () => null,
+ });
+ emit = new Emit(serverless);
+ });
+
+ it('should throw an Error of not logged in', () => {
+ emit.options.name = 'userCreated';
+ emit.data = { key: 'value' };
+ return emit.emitEvent().catch(err => {
+ expect(err).to.be.an.instanceOf(Error);
+ expect(err.message).to.equal(
+ 'Must be logged in to use this command. Please run "serverless login".'
+ );
+ });
+ });
+ });
+});
diff --git a/lib/plugins/invoke/invoke.js b/lib/plugins/invoke/invoke.js
index f513fef23..18f715735 100644
--- a/lib/plugins/invoke/invoke.js
+++ b/lib/plugins/invoke/invoke.js
@@ -41,9 +41,13 @@ class Invoke {
shortcut: 'l',
},
data: {
- usage: 'input data',
+ usage: 'Input data',
shortcut: 'd',
},
+ raw: {
+ usage: 'Flag to pass input data as a raw string',
+ },
+
},
commands: {
local: {
@@ -66,6 +70,17 @@ class Invoke {
usage: 'input data',
shortcut: 'd',
},
+ raw: {
+ usage: 'Flag to pass input data as a raw string',
+ },
+ context: {
+ usage: 'Context of the service',
+ shortcut: 'c',
+ },
+ contextPath: {
+ usage: 'Path to JSON or YAML file holding context data',
+ shortcut: 'x',
+ },
},
},
},
diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js
index 56476c955..a3f23f144 100644
--- a/lib/plugins/login/login.js
+++ b/lib/plugins/login/login.js
@@ -36,6 +36,7 @@ class Login {
lifecycleEvents: [
'login',
],
+ platform: true,
},
};
diff --git a/lib/plugins/logout/logout.js b/lib/plugins/logout/logout.js
index c362275bb..380668694 100644
--- a/lib/plugins/logout/logout.js
+++ b/lib/plugins/logout/logout.js
@@ -3,7 +3,7 @@
const userStats = require('../../utils/userStats');
const configUtils = require('../../utils/config');
-class Login {
+class Logout {
constructor(serverless, options) {
this.serverless = serverless;
this.options = options;
@@ -12,6 +12,7 @@ class Login {
logout: {
usage: 'Logout from the Serverless Platform',
lifecycleEvents: ['logout'],
+ platform: true,
},
};
@@ -50,4 +51,4 @@ class Login {
}
}
-module.exports = Login;
+module.exports = Logout;
diff --git a/lib/plugins/package/lib/packageService.js b/lib/plugins/package/lib/packageService.js
index 9ba26bffb..0c43ff0b4 100644
--- a/lib/plugins/package/lib/packageService.js
+++ b/lib/plugins/package/lib/packageService.js
@@ -2,6 +2,7 @@
const BbPromise = require('bluebird');
const path = require('path');
+const globby = require('globby');
const _ = require('lodash');
module.exports = {
@@ -60,19 +61,19 @@ module.exports = {
},
packageAll() {
- const exclude = this.getExcludes();
- const include = this.getIncludes();
const zipFileName = `${this.serverless.service.service}.zip`;
- return this.zipService(exclude, include, zipFileName).then(filePath => {
- // only set the default artifact for backward-compatibility
- // when no explicit artifact is defined
- if (!this.serverless.service.package.artifact) {
- this.serverless.service.package.artifact = filePath;
- this.serverless.service.artifact = filePath;
- }
- return filePath;
- });
+ return this.resolveFilePathsAll().then(filePaths =>
+ this.zipFiles(filePaths, zipFileName).then(filePath => {
+ // only set the default artifact for backward-compatibility
+ // when no explicit artifact is defined
+ if (!this.serverless.service.package.artifact) {
+ this.serverless.service.package.artifact = filePath;
+ this.serverless.service.artifact = filePath;
+ }
+ return filePath;
+ })
+ );
},
packageFunction(functionName) {
@@ -94,15 +95,62 @@ module.exports = {
return BbPromise.resolve(filePath);
}
- const exclude = this.getExcludes(funcPackageConfig.exclude);
- const include = this.getIncludes(funcPackageConfig.include);
const zipFileName = `${functionName}.zip`;
- return this.zipService(exclude, include, zipFileName).then(artifactPath => {
- functionObject.package = {
- artifact: artifactPath,
- };
- return artifactPath;
+ return this.resolveFilePathsFunction(functionName).then(filePaths =>
+ this.zipFiles(filePaths, zipFileName).then(artifactPath => {
+ functionObject.package = {
+ artifact: artifactPath,
+ };
+ return artifactPath;
+ })
+ );
+ },
+
+ resolveFilePathsAll() {
+ const params = { exclude: this.getExcludes(), include: this.getIncludes() };
+ return this.excludeDevDependencies(params).then(() =>
+ this.resolveFilePathsFromPatterns(params));
+ },
+
+ resolveFilePathsFunction(functionName) {
+ const functionObject = this.serverless.service.getFunction(functionName);
+ const funcPackageConfig = functionObject.package || {};
+
+ const params = {
+ exclude: this.getExcludes(funcPackageConfig.exclude),
+ include: this.getIncludes(funcPackageConfig.include),
+ };
+ return this.excludeDevDependencies(params).then(() =>
+ this.resolveFilePathsFromPatterns(params));
+ },
+
+ resolveFilePathsFromPatterns(params) {
+ const patterns = ['**'];
+
+ params.exclude.forEach((pattern) => {
+ if (pattern.charAt(0) !== '!') {
+ patterns.push(`!${pattern}`);
+ } else {
+ patterns.push(pattern.substring(1));
+ }
+ });
+
+ // push the include globs to the end of the array
+ // (files and folders will be re-added again even if they were excluded beforehand)
+ params.include.forEach((pattern) => {
+ patterns.push(pattern);
+ });
+
+ return globby(patterns, {
+ cwd: this.serverless.config.servicePath,
+ dot: true,
+ silent: true,
+ follow: true,
+ nodir: true,
+ }).then(filePaths => {
+ if (filePaths.length !== 0) return filePaths;
+ throw new this.serverless.classes.Error('No file matches include / exclude patterns');
});
},
};
diff --git a/lib/plugins/package/lib/packageService.test.js b/lib/plugins/package/lib/packageService.test.js
index 0507b7979..6a1c1d5f9 100644
--- a/lib/plugins/package/lib/packageService.test.js
+++ b/lib/plugins/package/lib/packageService.test.js
@@ -1,6 +1,7 @@
'use strict';
const BbPromise = require('bluebird');
+const path = require('path');
const chai = require('chai');
const sinon = require('sinon');
const Package = require('../package');
@@ -225,24 +226,29 @@ describe('#packageService()', () => {
describe('#packageAll()', () => {
const exclude = ['test-exclude'];
const include = ['test-include'];
+ const files = [];
const artifactFilePath = '/some/fake/path/test-artifact.zip';
let getExcludesStub;
let getIncludesStub;
- let zipServiceStub;
+ let resolveFilePathsFromPatternsStub;
+ let zipFilesStub;
beforeEach(() => {
getExcludesStub = sinon
.stub(packagePlugin, 'getExcludes').returns(exclude);
getIncludesStub = sinon
.stub(packagePlugin, 'getIncludes').returns(include);
- zipServiceStub = sinon
- .stub(packagePlugin, 'zipService').resolves(artifactFilePath);
+ resolveFilePathsFromPatternsStub = sinon
+ .stub(packagePlugin, 'resolveFilePathsFromPatterns').returns(files);
+ zipFilesStub = sinon
+ .stub(packagePlugin, 'zipFiles').resolves(artifactFilePath);
});
afterEach(() => {
packagePlugin.getExcludes.restore();
packagePlugin.getIncludes.restore();
- packagePlugin.zipService.restore();
+ packagePlugin.resolveFilePathsFromPatterns.restore();
+ packagePlugin.zipFiles.restore();
});
it('should call zipService with settings', () => {
@@ -255,10 +261,10 @@ describe('#packageService()', () => {
.then(() => BbPromise.all([
expect(getExcludesStub).to.be.calledOnce,
expect(getIncludesStub).to.be.calledOnce,
- expect(zipServiceStub).to.be.calledOnce,
- expect(zipServiceStub).to.have.been.calledWithExactly(
- exclude,
- include,
+ expect(resolveFilePathsFromPatternsStub).to.be.calledOnce,
+ expect(zipFilesStub).to.be.calledOnce,
+ expect(zipFilesStub).to.have.been.calledWithExactly(
+ files,
zipFileName
),
]));
@@ -268,24 +274,29 @@ describe('#packageService()', () => {
describe('#packageFunction()', () => {
const exclude = ['test-exclude'];
const include = ['test-include'];
+ const files = [];
const artifactFilePath = '/some/fake/path/test-artifact.zip';
let getExcludesStub;
let getIncludesStub;
- let zipServiceStub;
+ let resolveFilePathsFromPatternsStub;
+ let zipFilesStub;
beforeEach(() => {
getExcludesStub = sinon
.stub(packagePlugin, 'getExcludes').returns(exclude);
getIncludesStub = sinon
.stub(packagePlugin, 'getIncludes').returns(include);
- zipServiceStub = sinon
- .stub(packagePlugin, 'zipService').resolves(artifactFilePath);
+ resolveFilePathsFromPatternsStub = sinon
+ .stub(packagePlugin, 'resolveFilePathsFromPatterns').returns(files);
+ zipFilesStub = sinon
+ .stub(packagePlugin, 'zipFiles').resolves(artifactFilePath);
});
afterEach(() => {
packagePlugin.getExcludes.restore();
packagePlugin.getIncludes.restore();
- packagePlugin.zipService.restore();
+ packagePlugin.resolveFilePathsFromPatterns.restore();
+ packagePlugin.zipFiles.restore();
});
it('should call zipService with settings', () => {
@@ -302,11 +313,11 @@ describe('#packageService()', () => {
.then(() => BbPromise.all([
expect(getExcludesStub).to.be.calledOnce,
expect(getIncludesStub).to.be.calledOnce,
+ expect(resolveFilePathsFromPatternsStub).to.be.calledOnce,
- expect(zipServiceStub).to.be.calledOnce,
- expect(zipServiceStub).to.have.been.calledWithExactly(
- exclude,
- include,
+ expect(zipFilesStub).to.be.calledOnce,
+ expect(zipFilesStub).to.have.been.calledWithExactly(
+ files,
zipFileName
),
]));
@@ -326,11 +337,11 @@ describe('#packageService()', () => {
};
return expect(packagePlugin.packageFunction(funcName)).to.eventually
- .equal('test/artifact.zip')
+ .equal(path.join('test/artifact.zip'))
.then(() => BbPromise.all([
expect(getExcludesStub).to.not.have.been.called,
expect(getIncludesStub).to.not.have.been.called,
- expect(zipServiceStub).to.not.have.been.called,
+ expect(zipFilesStub).to.not.have.been.called,
]));
});
@@ -348,11 +359,11 @@ describe('#packageService()', () => {
};
return expect(packagePlugin.packageFunction(funcName)).to.eventually
- .equal('test/artifact.zip')
+ .equal(path.join('test/artifact.zip'))
.then(() => BbPromise.all([
expect(getExcludesStub).to.not.have.been.called,
expect(getIncludesStub).to.not.have.been.called,
- expect(zipServiceStub).to.not.have.been.called,
+ expect(zipFilesStub).to.not.have.been.called,
]));
});
});
diff --git a/lib/plugins/package/lib/zipService.js b/lib/plugins/package/lib/zipService.js
index 582f683cc..a1354f16f 100644
--- a/lib/plugins/package/lib/zipService.js
+++ b/lib/plugins/package/lib/zipService.js
@@ -7,7 +7,7 @@ const archiver = require('archiver');
const os = require('os');
const path = require('path');
const crypto = require('crypto');
-const fs = BbPromise.promisifyAll(require('fs'));
+const fs = BbPromise.promisifyAll(require('graceful-fs'));
const childProcess = BbPromise.promisifyAll(require('child_process'));
const globby = require('globby');
const _ = require('lodash');
@@ -51,73 +51,58 @@ module.exports = {
},
zip(params) {
- const patterns = ['**'];
+ return this.resolveFilePathsFromPatterns(params).then(filePaths =>
+ this.zipFiles(filePaths, params.zipFileName));
+ },
- params.exclude.forEach((pattern) => {
- if (pattern.charAt(0) !== '!') {
- patterns.push(`!${pattern}`);
- } else {
- patterns.push(pattern.substring(1));
- }
- });
-
- // push the include globs to the end of the array
- // (files and folders will be re-added again even if they were excluded beforehand)
- params.include.forEach((pattern) => {
- patterns.push(pattern);
- });
+ zipFiles(files, zipFileName) {
+ if (files.length === 0) {
+ const error = new this.serverless.classes.Error('No files to package');
+ return BbPromise.reject(error);
+ }
const zip = archiver.create('zip');
// Create artifact in temp path and move it to the package path (if any) later
const artifactFilePath = path.join(this.serverless.config.servicePath,
'.serverless',
- params.zipFileName
+ zipFileName
);
this.serverless.utils.writeFileDir(artifactFilePath);
const output = fs.createWriteStream(artifactFilePath);
- const files = globby.sync(patterns, {
- cwd: this.serverless.config.servicePath,
- dot: true,
- silent: true,
- follow: true,
- });
-
- if (files.length === 0) {
- const error = new this.serverless
- .classes.Error('No file matches include / exclude patterns');
- return BbPromise.reject(error);
- }
-
- output.on('open', () => {
- zip.pipe(output);
-
- files.forEach((filePath) => {
- const fullPath = path.resolve(
- this.serverless.config.servicePath,
- filePath
- );
-
- const stats = fs.statSync(fullPath);
-
- if (!stats.isDirectory(fullPath)) {
- zip.append(fs.readFileSync(fullPath), {
- name: filePath,
- mode: stats.mode,
- date: new Date(0), // necessary to get the same hash when zipping the same content
- });
- }
- });
-
- zip.finalize();
- });
-
return new BbPromise((resolve, reject) => {
output.on('close', () => resolve(artifactFilePath));
+ output.on('error', (err) => reject(err));
zip.on('error', (err) => reject(err));
+
+
+ output.on('open', () => {
+ zip.pipe(output);
+
+ BbPromise.all(files.map((filePath) => {
+ const fullPath = path.resolve(
+ this.serverless.config.servicePath,
+ filePath
+ );
+
+ return fs.statAsync(fullPath).then(stats =>
+ this.getFileContent(fullPath).then(fileContent =>
+ zip.append(fileContent, {
+ name: filePath,
+ mode: stats.mode,
+ date: new Date(0), // necessary to get the same hash when zipping the same content
+ })
+ )
+ );
+ })).then(() => zip.finalize()).catch(reject);
+ });
});
},
+
+ getFileContent(fullPath) {
+ return fs.readFileAsync(fullPath, 'utf8');
+ },
};
// eslint-disable-next-line
@@ -166,7 +151,7 @@ function excludeNodeDevDependencies(servicePath) {
return BbPromise.map(['dev', 'prod'], (env) => {
const depFile = env === 'dev' ? nodeDevDepFile : nodeProdDepFile;
return childProcess.execAsync(
- `npm ls --${env}=true --parseable=true --silent >> ${depFile}`,
+ `npm ls --${env}=true --parseable=true --long=false --silent >> ${depFile}`,
{ cwd: dirWithPackageJson }
).catch(() => BbPromise.resolve());
});
diff --git a/lib/plugins/package/lib/zipService.test.js b/lib/plugins/package/lib/zipService.test.js
index 8727ad496..2473cca0a 100644
--- a/lib/plugins/package/lib/zipService.test.js
+++ b/lib/plugins/package/lib/zipService.test.js
@@ -9,7 +9,7 @@ const JsZip = require('jszip');
const globby = require('globby');
const _ = require('lodash');
const BbPromise = require('bluebird');
-const fs = BbPromise.promisifyAll(require('fs'));
+const fs = BbPromise.promisifyAll(require('graceful-fs'));
const childProcess = BbPromise.promisifyAll(require('child_process'));
const sinon = require('sinon');
const Package = require('../package');
@@ -147,11 +147,11 @@ describe('zipService', () => {
nosort: true,
});
expect(execAsyncStub.args[0][0]).to
- .match(/npm ls --dev=true --parseable=true --silent >> .+/);
+ .match(/npm ls --dev=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[0][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[1][0]).to
- .match(/npm ls --prod=true --parseable=true --silent >> .+/);
+ .match(/npm ls --prod=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[1][1].cwd).to
.match(/.+/);
expect(updatedParams.exclude).to.deep.equal([
@@ -249,10 +249,10 @@ describe('zipService', () => {
execAsyncStub.onCall(4).resolves();
execAsyncStub.onCall(5).resolves();
const depPaths = [
- `${servicePath}/node_modules/module-1`,
- `${servicePath}/node_modules/module-2`,
- `${servicePath}/1st/2nd/node_modules/module-1`,
- `${servicePath}/1st/2nd/node_modules/module-2`,
+ path.join(`${servicePath}`, 'node_modules/module-1'),
+ path.join(`${servicePath}`, 'node_modules/module-2'),
+ path.join(`${servicePath}`, '1st/2nd/node_modules/module-1'),
+ path.join(`${servicePath}`, '1st/2nd/node_modules/module-2'),
].join('\n');
readFileAsyncStub.withArgs(sinon.match(/dev$/)).resolves(depPaths);
readFileAsyncStub.withArgs(sinon.match(/prod$/)).resolves([]);
@@ -271,35 +271,35 @@ describe('zipService', () => {
nosort: true,
});
expect(execAsyncStub.args[0][0]).to
- .match(/npm ls --dev=true --parseable=true --silent >> .+/);
+ .match(/npm ls --dev=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[0][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[1][0]).to
- .match(/npm ls --prod=true --parseable=true --silent >> .+/);
+ .match(/npm ls --prod=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[1][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[2][0]).to
- .match(/npm ls --dev=true --parseable=true --silent >> .+/);
+ .match(/npm ls --dev=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[2][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[3][0]).to
- .match(/npm ls --prod=true --parseable=true --silent >> .+/);
+ .match(/npm ls --prod=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[3][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[4][0]).to
- .match(/npm ls --dev=true --parseable=true --silent >> .+/);
+ .match(/npm ls --dev=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[4][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[5][0]).to
- .match(/npm ls --prod=true --parseable=true --silent >> .+/);
+ .match(/npm ls --prod=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[5][1].cwd).to
.match(/.+/);
expect(updatedParams.exclude).to.deep.equal([
'user-defined-exclude-me',
- 'node_modules/module-1/**',
- 'node_modules/module-2/**',
- '1st/2nd/node_modules/module-1/**',
- '1st/2nd/node_modules/module-2/**',
+ `${path.join('node_modules/module-1')}/**`,
+ `${path.join('node_modules/module-2')}/**`,
+ `${path.join('1st/2nd/node_modules/module-1')}/**`,
+ `${path.join('1st/2nd/node_modules/module-2')}/**`,
]);
expect(updatedParams.include).to
.deep.equal([
@@ -315,8 +315,8 @@ describe('zipService', () => {
globbySyncStub.returns(filePaths);
execAsyncStub.resolves();
const depPaths = [
- `${servicePath}/node_modules/module-1`,
- `${servicePath}/node_modules/module-2`,
+ path.join(`${servicePath}`, 'node_modules/module-1'),
+ path.join(`${servicePath}`, 'node_modules/module-2'),
].join('\n');
readFileAsyncStub.withArgs(sinon.match(/dev$/)).resolves(depPaths);
readFileAsyncStub.withArgs(sinon.match(/prod$/)).resolves([]);
@@ -335,17 +335,17 @@ describe('zipService', () => {
nosort: true,
});
expect(execAsyncStub.args[0][0]).to
- .match(/npm ls --dev=true --parseable=true --silent >> .+/);
+ .match(/npm ls --dev=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[0][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[1][0]).to
- .match(/npm ls --prod=true --parseable=true --silent >> .+/);
+ .match(/npm ls --prod=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[1][1].cwd).to
.match(/.+/);
expect(updatedParams.exclude).to.deep.equal([
'user-defined-exclude-me',
- 'node_modules/module-1/**',
- 'node_modules/module-2/**',
+ `${path.join('node_modules/module-1')}/**`,
+ `${path.join('node_modules/module-2')}/**`,
]);
expect(updatedParams.include).to.deep.equal([
'user-defined-include-me',
@@ -369,12 +369,12 @@ describe('zipService', () => {
globbySyncStub.returns(filePaths);
execAsyncStub.resolves();
const depPaths = [
- `${servicePath}/node_modules/module-1`,
- `${servicePath}/node_modules/module-2`,
- `${servicePath}/1st/node_modules/module-1`,
- `${servicePath}/1st/node_modules/module-2`,
- `${servicePath}/1st/2nd/node_modules/module-1`,
- `${servicePath}/1st/2nd/node_modules/module-2`,
+ path.join(`${servicePath}`, 'node_modules/module-1'),
+ path.join(`${servicePath}`, 'node_modules/module-2'),
+ path.join(`${servicePath}`, '1st/node_modules/module-1'),
+ path.join(`${servicePath}`, '1st/node_modules/module-2'),
+ path.join(`${servicePath}`, '1st/2nd/node_modules/module-1'),
+ path.join(`${servicePath}`, '1st/2nd/node_modules/module-2'),
].join('\n');
readFileAsyncStub.resolves(depPaths);
readFileAsyncStub.withArgs(sinon.match(/dev$/)).resolves(depPaths);
@@ -394,37 +394,37 @@ describe('zipService', () => {
nosort: true,
});
expect(execAsyncStub.args[0][0]).to
- .match(/npm ls --dev=true --parseable=true --silent >> .+/);
+ .match(/npm ls --dev=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[0][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[1][0]).to
- .match(/npm ls --prod=true --parseable=true --silent >> .+/);
+ .match(/npm ls --prod=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[1][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[2][0]).to
- .match(/npm ls --dev=true --parseable=true --silent >> .+/);
+ .match(/npm ls --dev=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[2][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[3][0]).to
- .match(/npm ls --prod=true --parseable=true --silent >> .+/);
+ .match(/npm ls --prod=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[3][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[4][0]).to
- .match(/npm ls --dev=true --parseable=true --silent >> .+/);
+ .match(/npm ls --dev=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[4][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[5][0]).to
- .match(/npm ls --prod=true --parseable=true --silent >> .+/);
+ .match(/npm ls --prod=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[5][1].cwd).to
.match(/.+/);
expect(updatedParams.exclude).to.deep.equal([
'user-defined-exclude-me',
- 'node_modules/module-1/**',
- 'node_modules/module-2/**',
- '1st/node_modules/module-1/**',
- '1st/node_modules/module-2/**',
- '1st/2nd/node_modules/module-1/**',
- '1st/2nd/node_modules/module-2/**',
+ `${path.join('node_modules/module-1')}/**`,
+ `${path.join('node_modules/module-2')}/**`,
+ `${path.join('1st/node_modules/module-1')}/**`,
+ `${path.join('1st/node_modules/module-2')}/**`,
+ `${path.join('1st/2nd/node_modules/module-1')}/**`,
+ `${path.join('1st/2nd/node_modules/module-2')}/**`,
]);
expect(updatedParams.include).to.deep.equal([
'user-defined-include-me',
@@ -440,13 +440,13 @@ describe('zipService', () => {
execAsyncStub.resolves();
const devDepPaths = [
- `${servicePath}/node_modules/module-1`,
- `${servicePath}/node_modules/module-2`,
+ path.join(`${servicePath}`, 'node_modules/module-1'),
+ path.join(`${servicePath}`, 'node_modules/module-2'),
].join('\n');
readFileAsyncStub.withArgs(sinon.match(/dev$/)).resolves(devDepPaths);
const prodDepPaths = [
- `${servicePath}/node_modules/module-2`,
+ path.join(`${servicePath}`, 'node_modules/module-2'),
];
readFileAsyncStub.withArgs(sinon.match(/prod$/)).resolves(prodDepPaths);
@@ -464,16 +464,16 @@ describe('zipService', () => {
nosort: true,
});
expect(execAsyncStub.args[0][0]).to
- .match(/npm ls --dev=true --parseable=true --silent >> .+/);
+ .match(/npm ls --dev=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[0][1].cwd).to
.match(/.+/);
expect(execAsyncStub.args[1][0]).to
- .match(/npm ls --prod=true --parseable=true --silent >> .+/);
+ .match(/npm ls --prod=true --parseable=true --long=false --silent >> .+/);
expect(execAsyncStub.args[1][1].cwd).to
.match(/.+/);
expect(updatedParams.exclude).to.deep.equal([
'user-defined-exclude-me',
- 'node_modules/module-1/**',
+ `${path.join('node_modules/module-1')}/**`,
]);
expect(updatedParams.include).to.deep.equal([
'user-defined-include-me',
@@ -567,7 +567,7 @@ describe('zipService', () => {
expect(Object.keys(unzippedFileData)
.filter(file => !unzippedFileData[file].dir))
- .to.be.lengthOf(13);
+ .to.be.lengthOf(12);
// root directory
expect(unzippedFileData['event.json'].name)
@@ -648,7 +648,7 @@ describe('zipService', () => {
expect(Object.keys(unzippedFileData)
.filter(file => !unzippedFileData[file].dir))
- .to.be.lengthOf(8);
+ .to.be.lengthOf(7);
// root directory
expect(unzippedFileData['handler.js'].name)
@@ -693,7 +693,7 @@ describe('zipService', () => {
expect(Object.keys(unzippedFileData)
.filter(file => !unzippedFileData[file].dir))
- .to.be.lengthOf(11);
+ .to.be.lengthOf(10);
// root directory
expect(unzippedFileData['event.json'].name)
@@ -747,7 +747,7 @@ describe('zipService', () => {
expect(Object.keys(unzippedFileData)
.filter(file => !unzippedFileData[file].dir))
- .to.be.lengthOf(11);
+ .to.be.lengthOf(10);
// root directory
expect(unzippedFileData['event.json'].name)
@@ -788,4 +788,11 @@ describe('zipService', () => {
.rejectedWith(Error, 'file matches include / exclude');
});
});
+
+ describe('#zipFiles()', () => {
+ it('should throw an error if no files are provided', () =>
+ expect(packagePlugin.zipFiles([], path.resolve(__dirname, 'tmp.zip'))).to.be
+ .rejectedWith(Error, 'No files to package')
+ );
+ });
});
diff --git a/lib/plugins/platform/platform.js b/lib/plugins/platform/platform.js
index acb6573f3..1af4d4f31 100644
--- a/lib/plugins/platform/platform.js
+++ b/lib/plugins/platform/platform.js
@@ -10,9 +10,9 @@ const BbPromise = require('bluebird');
const fsExtra = require('../../utils/fs/fse');
const fetch = require('node-fetch');
const chalk = require('chalk');
-const configUtils = require('../../utils/config');
const functionInfoUtils = require('../../utils/functionInfoUtils');
const createApolloClient = require('../../utils/createApolloClient');
+const getAuthToken = require('../../utils/getAuthToken');
const selectServicePublish = require('../../utils/selectors/selectServicePublish');
// NOTE Needed for apollo to work
@@ -91,17 +91,7 @@ class Platform {
}
getAuthToken() {
- if (process.env.SERVERLESS_TOKEN) {
- return process.env.SERVERLESS_TOKEN;
- }
-
- const userConfig = configUtils.getConfig();
- const currentId = userConfig.userId;
- const globalConfig = configUtils.getGlobalConfig();
- if (globalConfig.users && globalConfig.users[currentId] && globalConfig.users[currentId].auth) {
- return globalConfig.users[currentId].auth.id_token;
- }
- return null;
+ return getAuthToken();
}
publishService() {
diff --git a/lib/plugins/run/index.js b/lib/plugins/run/index.js
new file mode 100644
index 000000000..b6fad0a2b
--- /dev/null
+++ b/lib/plugins/run/index.js
@@ -0,0 +1,156 @@
+'use strict';
+
+const BbPromise = require('bluebird');
+
+const logServerless = require('./utils/logServerless');
+const getLocalRootUrl = require('./utils/getLocalRootUrl');
+
+const localEmulatorRunning = require('./utils/localEmulatorRunning');
+const eventGatewayRunning = require('./utils/eventGatewayRunning');
+
+const localEmulatorInstalled = require('./utils/localEmulatorInstalled');
+const eventGatewayInstalled = require('./utils/eventGatewayInstalled');
+
+const installLocalEmulator = require('./utils/installLocalEmulator');
+const installEventGateway = require('./utils/installEventGateway');
+
+const deployFunctionsToLocalEmulator = require('./utils/deployFunctionsToLocalEmulator');
+const registerFunctionsToEventGateway = require('./utils/registerFunctionsToEventGateway');
+
+const manageLocalEmulator = require('./utils/manageLocalEmulator');
+const manageEventGateway = require('./utils/manageEventGateway');
+
+const getAuthToken = require('../../utils/getAuthToken');
+
+class Run {
+ constructor(serverless, options) {
+ this.serverless = serverless;
+ this.options = options;
+ this.commands = {
+ run: {
+ usage: 'Runs the Event Gateway and the Emulator',
+ lifecycleEvents: [
+ 'run',
+ ],
+ options: {
+ eport: {
+ usage: 'The Event Gateway API port',
+ shortcut: 'e',
+ default: '4000',
+ },
+ cport: {
+ usage: 'The Event Gateway configuration port',
+ shortcut: 'c',
+ default: '4001',
+ },
+ lport: {
+ usage: 'The Emulator port',
+ shortcut: 'l',
+ default: '4002',
+ },
+ debug: {
+ usage: 'Start the debugger',
+ shortcut: 'd',
+ },
+ },
+ platform: true,
+ },
+ };
+
+ this.hooks = {
+ 'run:run': () => BbPromise.bind(this)
+ .then(this.run),
+ };
+ }
+
+ run() {
+ const EVENT_GATEWAY_VERSION = '0.5.15';
+ const LOCAL_EMULATOR_VERSION = '0.1.18';
+
+ const authToken = getAuthToken();
+ if (!authToken) {
+ throw new this.serverless.classes
+ .Error('Must be logged in to use this command. Please run "serverless login".');
+ }
+
+ let functionsDeployed = false;
+ let functionsRegistered = false;
+ if (!this.serverless.config.servicePath) {
+ throw new this.serverless.classes
+ .Error('This command can only run inside a service');
+ }
+
+ return localEmulatorRunning(getLocalRootUrl(this.options.lport))
+ .then(localEmulatorAlreadyRunning => {
+ if (localEmulatorAlreadyRunning) {
+ // logServerless('Emulator already running');
+ functionsDeployed = true;
+ return deployFunctionsToLocalEmulator(
+ this.serverless.service,
+ this.serverless.config.servicePath,
+ getLocalRootUrl(this.options.lport)
+ ).then(noFunctions => {
+ if (noFunctions) {
+ // eslint-disable-next-line max-len
+ logServerless('Service does not contain any functions to be loaded in your current "serverless run" session.');
+ return BbPromise.resolve();
+ }
+ // eslint-disable-next-line max-len
+ logServerless('Functions loaded successfully in your current "serverless run" session.');
+ return BbPromise.resolve();
+ });
+ }
+ return BbPromise.resolve();
+ })
+ .then(() => eventGatewayRunning(getLocalRootUrl(this.options.cport)))
+ .then(eventGatewayAlreadyRunning => {
+ if (eventGatewayAlreadyRunning) {
+ functionsRegistered = true;
+ // logServerless('Event Gateway already running');
+ return registerFunctionsToEventGateway(
+ this.serverless.service,
+ getLocalRootUrl(this.options.eport),
+ getLocalRootUrl(this.options.cport),
+ getLocalRootUrl(this.options.lport)
+ ).then(() => {
+ // eslint-disable-next-line max-len
+ // logServerless('Functions and subscriptions registered. For details please review the terminal running the Event Gateway.');
+ });
+ }
+ return BbPromise.resolve();
+ })
+ .then(() => {
+ if (!functionsDeployed && !localEmulatorInstalled(LOCAL_EMULATOR_VERSION)) {
+ logServerless('Installing Emulator');
+ installLocalEmulator(LOCAL_EMULATOR_VERSION);
+ }
+ return BbPromise.resolve();
+ })
+ .then(() => {
+ if (!eventGatewayInstalled(EVENT_GATEWAY_VERSION)) {
+ logServerless('Installing Event Gateway');
+ return installEventGateway(EVENT_GATEWAY_VERSION);
+ }
+ return BbPromise.resolve();
+ })
+ .then(() => {
+ if (!functionsDeployed) {
+ return manageLocalEmulator(this.serverless.service,
+ this.serverless.config.servicePath,
+ { port: this.options.lport, debug: this.options.debug });
+ }
+ return BbPromise.resolve();
+ })
+ .then(() => {
+ if (!functionsRegistered) {
+ return manageEventGateway(this.serverless.service,
+ this.options.eport,
+ this.options.cport,
+ this.options.lport);
+ }
+ return BbPromise.resolve();
+ });
+ }
+}
+
+module.exports = Run;
diff --git a/lib/plugins/run/utils/deployFunctionToLocalEmulator.js b/lib/plugins/run/utils/deployFunctionToLocalEmulator.js
new file mode 100644
index 000000000..f25961326
--- /dev/null
+++ b/lib/plugins/run/utils/deployFunctionToLocalEmulator.js
@@ -0,0 +1,21 @@
+'use strict';
+
+const fetch = require('node-fetch');
+
+function deployFunctionToLocalEmulator(functionId, functionConfig, emulatorUrl) {
+ const localEmulatorDeployEndpoint = `${emulatorUrl}/v0/emulator/api/functions/deploy`;
+
+ return fetch(localEmulatorDeployEndpoint, {
+ headers: {
+ 'content-type': 'application/json',
+ },
+ method: 'POST',
+ timeout: 0, // NOTE using 0 so that deployments of large functions won't timeout
+ body: JSON.stringify({
+ functionId,
+ functionConfig,
+ }),
+ });
+}
+
+module.exports = deployFunctionToLocalEmulator;
diff --git a/lib/plugins/run/utils/deployFunctionsToLocalEmulator.js b/lib/plugins/run/utils/deployFunctionsToLocalEmulator.js
new file mode 100644
index 000000000..1d7654e0a
--- /dev/null
+++ b/lib/plugins/run/utils/deployFunctionsToLocalEmulator.js
@@ -0,0 +1,37 @@
+'use strict';
+
+const _ = require('lodash');
+const BbPromise = require('bluebird');
+const getLocalEmulatorFunctionConfig = require('./getLocalEmulatorFunctionConfig');
+const deployFunctionToLocalEmulator = require('./deployFunctionToLocalEmulator');
+const logLocalEmulator = require('./logLocalEmulator');
+
+function deployFunctionsToLocalEmulator(service, servicePath, localEmulatorRootUrl) {
+ const functionDeploymentPromises = [];
+ let noFunctions = false;
+
+ _.each(service.functions, (functionConfig, functionName) => {
+ const localEmulatorFunctionConfig = getLocalEmulatorFunctionConfig(
+ functionConfig,
+ service.provider,
+ servicePath);
+
+ const deployFunctionToLocalEmulatorPromise = deployFunctionToLocalEmulator(
+ `${service.service}-${functionName}`,
+ localEmulatorFunctionConfig, localEmulatorRootUrl);
+ functionDeploymentPromises.push(deployFunctionToLocalEmulatorPromise);
+ });
+
+ if (functionDeploymentPromises.length === 0) {
+ noFunctions = true;
+ return BbPromise.resolve(noFunctions);
+ }
+
+ // NOTE important for UX since it takes a while to upload large functions
+ logLocalEmulator('Functions loading...');
+
+ return BbPromise.all(functionDeploymentPromises)
+ .then(() => noFunctions);
+}
+
+module.exports = deployFunctionsToLocalEmulator;
diff --git a/lib/plugins/run/utils/eventGatewayInstalled.js b/lib/plugins/run/utils/eventGatewayInstalled.js
new file mode 100644
index 000000000..52d851b26
--- /dev/null
+++ b/lib/plugins/run/utils/eventGatewayInstalled.js
@@ -0,0 +1,26 @@
+'use strict';
+
+const path = require('path');
+const os = require('os');
+const BbPromise = require('bluebird');
+const childProcess = BbPromise.promisifyAll(require('child_process'));
+const fileExistsSync = require('../../../utils/fs/fileExistsSync');
+
+function eventGatewayInstalled(eventGatewayVersion) {
+ const eventGatewayBinaryFilePath = path
+ .join(os.homedir(), '.serverless', 'event-gateway', 'event-gateway');
+
+ if (!fileExistsSync(eventGatewayBinaryFilePath)) {
+ return false;
+ }
+
+ const cp = childProcess.spawnSync(eventGatewayBinaryFilePath, ['--version'],
+ { encoding: 'utf8' });
+ const currentVersion = cp.stdout.replace('Event Gateway version: ', '').trim();
+ if (currentVersion !== eventGatewayVersion) {
+ return false;
+ }
+ return true;
+}
+
+module.exports = eventGatewayInstalled;
diff --git a/lib/plugins/run/utils/eventGatewayRunning.js b/lib/plugins/run/utils/eventGatewayRunning.js
new file mode 100644
index 000000000..75d4dcbfa
--- /dev/null
+++ b/lib/plugins/run/utils/eventGatewayRunning.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const fetch = require('node-fetch');
+const BbPromise = require('bluebird');
+
+function eventGatewayRunning(eventGatewayRootUrl) {
+ const eventGatewayStatusEndpoint = `${eventGatewayRootUrl}/v1/status`;
+
+ return fetch(eventGatewayStatusEndpoint, {
+ method: 'GET',
+ timeout: 1000,
+ }).then(res => res.ok)
+ .catch(() => BbPromise.resolve(false));
+}
+
+module.exports = eventGatewayRunning;
diff --git a/lib/plugins/run/utils/getConfigureConfig.js b/lib/plugins/run/utils/getConfigureConfig.js
new file mode 100644
index 000000000..560cb2e82
--- /dev/null
+++ b/lib/plugins/run/utils/getConfigureConfig.js
@@ -0,0 +1,40 @@
+'use strict';
+
+const _ = require('lodash');
+const getFunctionToRegister = require('./getFunctionToRegister');
+
+function getConfigureConfig(serviceObject, localEmulatorRootUrl) {
+ const config = {
+ functions: [],
+ subscriptions: [],
+ };
+ _.each(serviceObject.functions, (functionConfig, functionName) => {
+ let functionSubscriptions = [];
+ const functionToRegister = getFunctionToRegister(serviceObject.service,
+ functionName, localEmulatorRootUrl);
+
+ if (functionConfig.events && functionConfig.events.length > 0) {
+ functionSubscriptions = _.map(functionConfig.events, (event) => {
+ const functionSubscription = {
+ functionId: functionToRegister.functionId,
+ };
+
+ if (typeof event === 'string') {
+ functionSubscription.event = event;
+ } else if (typeof event === 'object' && event.http) {
+ functionSubscription.event = 'http';
+ functionSubscription.method = event.http.method;
+ functionSubscription.path = event.http.path;
+ }
+
+ return functionSubscription;
+ });
+ }
+
+ config.functions.push(functionToRegister);
+ config.subscriptions = config.subscriptions.concat(functionSubscriptions);
+ });
+ return config;
+}
+
+module.exports = getConfigureConfig;
diff --git a/lib/plugins/run/utils/getFunctionToRegister.js b/lib/plugins/run/utils/getFunctionToRegister.js
new file mode 100644
index 000000000..5ad586134
--- /dev/null
+++ b/lib/plugins/run/utils/getFunctionToRegister.js
@@ -0,0 +1,19 @@
+'use strict';
+
+
+function getFunctionToRegister(serviceName, functionName, emulatorUrl) {
+ const functionId = `${serviceName}-${functionName}`;
+
+ const functionObject = {
+ functionId,
+ provider: {
+ type: 'emulator',
+ emulatorUrl,
+ apiVersion: 'v0',
+ },
+ };
+
+ return functionObject;
+}
+
+module.exports = getFunctionToRegister;
diff --git a/lib/plugins/run/utils/getLocalEmulatorFunctionConfig.js b/lib/plugins/run/utils/getLocalEmulatorFunctionConfig.js
new file mode 100644
index 000000000..3f0dca055
--- /dev/null
+++ b/lib/plugins/run/utils/getLocalEmulatorFunctionConfig.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const _ = require('lodash');
+
+function getLocalEmulatorFunctionConfig(functionConfig, providerConfig, servicePath) {
+ const provider = functionConfig.provider || providerConfig.name;
+ const envVars = _.merge(providerConfig.environment, functionConfig.environment);
+
+ const localEmulatorFunctionConfig = {
+ provider,
+ handler: functionConfig.handler,
+ servicePath,
+ runtime: functionConfig.runtime || providerConfig.runtime,
+ };
+
+ if (provider === 'aws') {
+ localEmulatorFunctionConfig.functionName = functionConfig.name;
+ localEmulatorFunctionConfig.memorySize = Number(functionConfig.memorySize)
+ || Number(providerConfig.memorySize)
+ || 1024;
+ localEmulatorFunctionConfig.region = providerConfig.region;
+ localEmulatorFunctionConfig.envVars = envVars;
+ } else if (provider === 'google') {
+ const memorySize = Number(functionConfig.memorySize)
+ || Number(providerConfig.memorySize)
+ || 1024;
+ localEmulatorFunctionConfig.functionName = functionConfig.name;
+ // TODO localEmulatorFunctionConfig.eventType = ?
+ localEmulatorFunctionConfig.project = providerConfig.project;
+ localEmulatorFunctionConfig.memorySize = memorySize;
+ localEmulatorFunctionConfig.env = {
+ REGION: providerConfig.region,
+ FUNCTION_NAME: functionConfig.name,
+ MEMORY_SIZE: memorySize,
+ };
+
+ localEmulatorFunctionConfig.env = _.merge(localEmulatorFunctionConfig.env,
+ providerConfig.environment, functionConfig.environment);
+ }
+
+ return localEmulatorFunctionConfig;
+}
+
+module.exports = getLocalEmulatorFunctionConfig;
diff --git a/lib/plugins/run/utils/getLocalRootUrl.js b/lib/plugins/run/utils/getLocalRootUrl.js
new file mode 100644
index 000000000..d830691d7
--- /dev/null
+++ b/lib/plugins/run/utils/getLocalRootUrl.js
@@ -0,0 +1,7 @@
+'use strict';
+
+function getLocalRootUrl(port) {
+ return `http://localhost:${port}`;
+}
+
+module.exports = getLocalRootUrl;
diff --git a/lib/plugins/run/utils/getTmpDirPath.js b/lib/plugins/run/utils/getTmpDirPath.js
new file mode 100644
index 000000000..b0651529a
--- /dev/null
+++ b/lib/plugins/run/utils/getTmpDirPath.js
@@ -0,0 +1,10 @@
+'use strict';
+
+const path = require('path');
+const os = require('os');
+const crypto = require('crypto');
+
+const getTmpDirPath = () => path.join(os.tmpdir(),
+ 'tmpdirs-serverless', 'serverless', crypto.randomBytes(8).toString('hex'));
+
+module.exports = getTmpDirPath;
diff --git a/lib/plugins/run/utils/installEventGateway.js b/lib/plugins/run/utils/installEventGateway.js
new file mode 100644
index 000000000..c5d7d1525
--- /dev/null
+++ b/lib/plugins/run/utils/installEventGateway.js
@@ -0,0 +1,29 @@
+'use strict';
+
+const download = require('download');
+const os = require('os');
+const path = require('path');
+
+function installEventGateway(eventGatewayVersion) {
+ let arch = '386';
+ if (process.arch === 'x64') {
+ arch = 'amd64';
+ }
+
+ let eventGatewayDownloadUrl = `https://github.com/serverless/event-gateway/releases/download/${eventGatewayVersion}/event-gateway_${eventGatewayVersion}_darwin_${arch}.tar.gz`;
+
+ if (os.platform() === 'linux') {
+ eventGatewayDownloadUrl = `https://github.com/serverless/event-gateway/releases/download/${eventGatewayVersion}/event-gateway_${eventGatewayVersion}_linux_${arch}.tar.gz`;
+ } else if (os.platform() === 'win32') {
+ eventGatewayDownloadUrl = `https://github.com/serverless/event-gateway/releases/download/${eventGatewayVersion}/event-gateway_${eventGatewayVersion}_windows_${arch}.tar.gz`;
+ }
+ const eventGatewayDownloadPath = path.join(os.homedir(), '.serverless', 'event-gateway');
+
+ return download(
+ eventGatewayDownloadUrl,
+ eventGatewayDownloadPath,
+ { timeout: 30000, extract: true, strip: 1, mode: '755' }
+ );
+}
+
+module.exports = installEventGateway;
diff --git a/lib/plugins/run/utils/installLocalEmulator.js b/lib/plugins/run/utils/installLocalEmulator.js
new file mode 100644
index 000000000..4a9f288a0
--- /dev/null
+++ b/lib/plugins/run/utils/installLocalEmulator.js
@@ -0,0 +1,10 @@
+'use strict';
+
+const BbPromise = require('bluebird');
+const childProcess = BbPromise.promisifyAll(require('child_process'));
+
+function installLocalEmulator(localEmulatorVersion) {
+ childProcess.execSync(`npm install -g @serverless/emulator@${localEmulatorVersion}`);
+}
+
+module.exports = installLocalEmulator;
diff --git a/lib/plugins/run/utils/localEmulatorInstalled.js b/lib/plugins/run/utils/localEmulatorInstalled.js
new file mode 100644
index 000000000..3106504c5
--- /dev/null
+++ b/lib/plugins/run/utils/localEmulatorInstalled.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const BbPromise = require('bluebird');
+const childProcess = BbPromise.promisifyAll(require('child_process'));
+
+function localEmulatorInstalled(localEmulatorVersion) {
+ try {
+ const cp = childProcess.spawnSync('sle', ['ping'], { encoding: 'utf8' });
+ const currentVersion = cp.stdout.trim();
+ if (currentVersion === 'pong' || (currentVersion !== localEmulatorVersion)) {
+ return false;
+ }
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
+module.exports = localEmulatorInstalled;
diff --git a/lib/plugins/run/utils/localEmulatorRunning.js b/lib/plugins/run/utils/localEmulatorRunning.js
new file mode 100644
index 000000000..77e581e1b
--- /dev/null
+++ b/lib/plugins/run/utils/localEmulatorRunning.js
@@ -0,0 +1,29 @@
+'use strict';
+
+const fetch = require('node-fetch');
+const BbPromise = require('bluebird');
+
+function localEmulatorRunning(localEmulatorRootUrl) {
+ const localEmulatorHeartbeatEndpoint = `${localEmulatorRootUrl}/v0/emulator/api/utils/heartbeat`;
+ const timestamp = (+new Date());
+ const payload = {
+ ping: timestamp,
+ };
+
+ return fetch(localEmulatorHeartbeatEndpoint, {
+ headers: {
+ 'content-type': 'application/json',
+ },
+ method: 'POST',
+ timeout: 1000,
+ body: JSON.stringify(payload),
+ }).then(res => res.json())
+ .then(json => {
+ if (json.pong === timestamp) {
+ return BbPromise.resolve(true);
+ }
+ return BbPromise.resolve(false);
+ }).catch(() => BbPromise.resolve(false));
+}
+
+module.exports = localEmulatorRunning;
diff --git a/lib/plugins/run/utils/log.js b/lib/plugins/run/utils/log.js
new file mode 100644
index 000000000..0f4dc6d07
--- /dev/null
+++ b/lib/plugins/run/utils/log.js
@@ -0,0 +1 @@
+module.exports = msg => process.stdout.write(msg);
diff --git a/lib/plugins/run/utils/logEventGateway.js b/lib/plugins/run/utils/logEventGateway.js
new file mode 100644
index 000000000..7b72224d8
--- /dev/null
+++ b/lib/plugins/run/utils/logEventGateway.js
@@ -0,0 +1,74 @@
+'use strict';
+
+/* eslint-disable max-len */
+
+const chalk = require('chalk');
+const log = require('./log');
+const os = require('os');
+
+const colorPrefix = chalk.hex('#D86121');
+const colorDim = chalk.hex('#777777');
+const spaceSmall = ' ';
+const prefix = colorPrefix(` Event Gateway${spaceSmall}`);
+const serverlessColorPrefix = chalk.hex('#bdb018');
+const serverlessPrefix = serverlessColorPrefix(` Serverless${spaceSmall}`);
+
+const prettifyValue = value => {
+ const prettified = JSON.stringify(value, null, 2).replace(
+ new RegExp('\\n', 'g'),
+ `${os.EOL}${spaceSmall}`
+ );
+ return `${spaceSmall}${prettified}`;
+};
+
+const processMessage = msg => {
+ let parsedMsg;
+ try {
+ parsedMsg = JSON.parse(msg);
+ } catch (err) {
+ return false;
+ }
+
+ if (parsedMsg.msg === 'Function registered.') {
+ return `${prefix}Function '${parsedMsg.functionId}' registered`;
+ } else if (parsedMsg.msg === 'Subscription created.') {
+ return `${prefix}Subscription created for event '${parsedMsg.event}' and function '${parsedMsg.functionId}'`;
+ } else if (parsedMsg.msg === 'Subscription deleted.') {
+ return `${prefix}Subscription removed: event:${parsedMsg.event} >>> function:${parsedMsg.functionId}`;
+ } else if (parsedMsg.msg === 'Event received.') {
+ const event = JSON.parse(parsedMsg.event);
+ const text = `${prefix}Event '${event.event}' received:${os.EOL}${os.EOL}`;
+ return `${text}${colorDim(prettifyValue(event))}${os.EOL}`;
+ } else if (parsedMsg.msg === 'Function triggered.') {
+ const event = JSON.parse(parsedMsg.event);
+ const text = `Function '${parsedMsg.functionId}' triggered by event '${event.event}'${os.EOL}`;
+ return `${serverlessPrefix} ${text}`;
+ } else if (parsedMsg.msg.startsWith('Running in development mode with embedded etcd')) {
+ const partOne = 'Running in development mode with embedded etcd. Event API listening on ';
+ const re = new RegExp(`${partOne}(.*). Config API listening on (.*).`);
+ const found = parsedMsg.msg.match(re);
+ if (found) {
+ const apiText = `Event API listening on: ${found[1]}`;
+ return `${prefix}${apiText}${os.EOL}${prefix}Config API listening on: ${found[2]}`;
+ }
+ } else if (parsedMsg.msg === 'Function finished.') {
+ const response = prettifyValue(JSON.parse(parsedMsg.response));
+ const text = `Function '${parsedMsg.functionId}' finished:${os.EOL}${os.EOL}${colorDim(response)}${os.EOL}`;
+ return `${serverlessPrefix} ${text}`;
+ }
+
+ return false;
+};
+
+module.exports = msg => {
+ try {
+ const processedMsg = processMessage(msg);
+ if (processedMsg) {
+ log(`${processedMsg}${os.EOL}`);
+ }
+ } catch (err) {
+ // NOTE keep this here - it's a worse UX to skip messages
+ // rather than having an unformated message logged
+ log(`${prefix}raw output: ${colorDim(msg)}${os.EOL}`);
+ }
+};
diff --git a/lib/plugins/run/utils/logEventGateway.test.js b/lib/plugins/run/utils/logEventGateway.test.js
new file mode 100644
index 000000000..619c20e37
--- /dev/null
+++ b/lib/plugins/run/utils/logEventGateway.test.js
@@ -0,0 +1,88 @@
+'use strict';
+
+const chai = require('chai');
+const sinon = require('sinon');
+const proxyquire = require('proxyquire');
+const os = require('os');
+
+chai.use(require('chai-as-promised'));
+
+const expect = chai.expect;
+
+describe('logEventGateway', () => {
+ let logStub;
+ let logEventGateway;
+
+ beforeEach(() => {
+ logStub = sinon.stub();
+ logEventGateway = proxyquire('./logEventGateway', {
+ './log': logStub,
+ });
+ });
+
+ it('format and log function added', () => {
+ logEventGateway(
+ JSON.stringify({
+ level: 'DEBUG',
+ msg: 'Function registered.',
+ functionId: 's1-f1',
+ type: 'http',
+ })
+ );
+ expect(logStub.calledOnce).to.be.equal(true);
+ const expected = ` Event Gateway Function 's1-f1' registered${os.EOL}`;
+ expect(logStub.getCall(0).args[0]).to.be.equal(expected);
+ });
+
+ it('format and log event received', () => {
+ logEventGateway(
+ JSON.stringify({
+ level: 'debug',
+ ts: 1502464166.8101041,
+ msg: 'Event received.',
+ event:
+ '{"headers":{"Accept":["image/webp,image/apng,image/*,*/*;q=0.8"],"Accept-Encoding":["gzip, deflate, br"],"Accept-Language":["en-US,en;q=0.8"],"Cache-Control":["no-cache"],"Connection":["keep-alive"],"Pragma":["no-cache"],"Referer":["http://localhost:4000/"],"User-Agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"]},"query":{},"body":""}',
+ path: '/favicon.ico',
+ method: 'GET',
+ })
+ );
+ expect(logStub.calledOnce).to.be.equal(true);
+ const expected = [
+ ' Event Gateway Event \'undefined\' received:',
+ '',
+ ' {',
+ ' "headers": {',
+ ' "Accept": [',
+ ' "image/webp,image/apng,image/*,*/*;q=0.8"',
+ ' ],',
+ ' "Accept-Encoding": [',
+ ' "gzip, deflate, br"',
+ ' ],',
+ ' "Accept-Language": [',
+ ' "en-US,en;q=0.8"',
+ ' ],',
+ ' "Cache-Control": [',
+ ' "no-cache"',
+ ' ],',
+ ' "Connection": [',
+ ' "keep-alive"',
+ ' ],',
+ ' "Pragma": [',
+ ' "no-cache"',
+ ' ],',
+ ' "Referer": [',
+ ' "http://localhost:4000/"',
+ ' ],',
+ ' "User-Agent": [', // eslint-disable-next-line max-len
+ ' "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"',
+ ' ]',
+ ' },',
+ ' "query": {},',
+ ' "body": ""',
+ ' }',
+ '',
+ '',
+ ].join(os.EOL);
+ expect(logStub.getCall(0).args[0]).to.be.equal(expected);
+ });
+});
diff --git a/lib/plugins/run/utils/logLocalEmulator.js b/lib/plugins/run/utils/logLocalEmulator.js
new file mode 100644
index 000000000..c9e0a5b4a
--- /dev/null
+++ b/lib/plugins/run/utils/logLocalEmulator.js
@@ -0,0 +1,36 @@
+'use strict';
+
+const os = require('os');
+const chalk = require('chalk');
+
+const colorPrefix = chalk.hex('#bdb018');
+const colorDim = chalk.hex('#777777');
+const colorError = chalk.hex('#e22836');
+const spaceSmall = ' ';
+const prefix = colorPrefix(` Serverless${spaceSmall}`);
+
+const processMessage = rawMessage => {
+ let msg = rawMessage;
+ if (msg.trim().length < 0) {
+ return false;
+ } else if (typeof msg === 'string') {
+ msg = msg.trim();
+
+ if (msg.startsWith('Error:')) {
+ msg = `${colorError('Function failed due to an error:')}${os.EOL}${os.EOL}${colorDim(
+ msg
+ )}${os.EOL}`;
+ }
+ }
+
+ return msg;
+};
+
+function logLocalEmulator(rawMessage) {
+ const message = processMessage(rawMessage);
+ if (message) {
+ process.stdout.write(`${prefix}${message}${os.EOL}`);
+ }
+}
+
+module.exports = logLocalEmulator;
diff --git a/lib/plugins/run/utils/logServerless.js b/lib/plugins/run/utils/logServerless.js
new file mode 100644
index 000000000..3103dfef9
--- /dev/null
+++ b/lib/plugins/run/utils/logServerless.js
@@ -0,0 +1,13 @@
+'use strict';
+
+const chalk = require('chalk');
+
+const colorPrefix = chalk.hex('#bdb018');
+const spaceSmall = ' ';
+const prefix = colorPrefix(` Serverless${spaceSmall}`);
+
+function logServerless(message) {
+ process.stdout.write(`${prefix}${message}\n`);
+}
+
+module.exports = logServerless;
diff --git a/lib/plugins/run/utils/manageEventGateway.js b/lib/plugins/run/utils/manageEventGateway.js
new file mode 100644
index 000000000..6624ef7f9
--- /dev/null
+++ b/lib/plugins/run/utils/manageEventGateway.js
@@ -0,0 +1,71 @@
+'use strict';
+
+const BbPromise = require('bluebird');
+const childProcess = BbPromise.promisifyAll(require('child_process'));
+const path = require('path');
+const os = require('os');
+const _ = require('lodash');
+
+const logServerless = require('./logServerless');
+const logEventGateway = require('./logEventGateway');
+const getTmpDirPath = require('./getTmpDirPath');
+const getLocalRootUrl = require('./getLocalRootUrl');
+const registerFunctionsToEventGateway = require('./registerFunctionsToEventGateway');
+
+const splitLinesAndLog = data => {
+ const str = data.toString('utf8');
+ // TODO makes sure this doesn't affect escaped newlines inside event content
+ const lines = str.split(/\r?\n/g);
+ _.forEach(lines, line => {
+ if (line !== '') {
+ logEventGateway(line);
+ }
+ });
+};
+
+function manageEventGateway(service, eventsPort, configurationPort, localEmulatorPort) {
+ let initialized = false;
+ const binaryFilePath = path.join(os.homedir(), '.serverless', 'event-gateway', 'event-gateway');
+ logServerless('Event Gateway initializing...');
+
+ const args = [
+ `-embed-data-dir=${getTmpDirPath()}`,
+ '-dev',
+ '-log-level=debug',
+ '-log-format=json',
+ `-config-port=${configurationPort}`,
+ `-events-port=${eventsPort}`,
+ ];
+
+ const cp = childProcess.spawn(binaryFilePath, args);
+
+ cp.stdout.on('data', stdout => {
+ splitLinesAndLog(stdout);
+ });
+
+ cp.stderr.on('data', stderr => {
+ splitLinesAndLog(stderr);
+
+ if (!initialized) {
+ initialized = true;
+ logServerless('Event Gateway initialized');
+ setTimeout(
+ () =>
+ registerFunctionsToEventGateway(
+ service,
+ getLocalRootUrl(eventsPort),
+ getLocalRootUrl(configurationPort),
+ getLocalRootUrl(localEmulatorPort)
+ ),
+ 2000
+ );
+ }
+ });
+
+ cp.on('close', () => BbPromise.resolve());
+ cp.on('error', error => BbPromise.reject(error));
+
+ process.on('exit', () => cp.kill());
+}
+
+module.exports = manageEventGateway;
diff --git a/lib/plugins/run/utils/manageLocalEmulator.js b/lib/plugins/run/utils/manageLocalEmulator.js
new file mode 100644
index 000000000..d17afb19f
--- /dev/null
+++ b/lib/plugins/run/utils/manageLocalEmulator.js
@@ -0,0 +1,46 @@
+'use strict';
+
+const BbPromise = require('bluebird');
+const childProcess = BbPromise.promisifyAll(require('child_process'));
+
+const getLocalRootUrl = require('./getLocalRootUrl');
+const deployFunctionsToLocalEmulator = require('./deployFunctionsToLocalEmulator');
+const logServerless = require('./logServerless');
+const logLocalEmulator = require('./logLocalEmulator');
+
+function manageLocalEmulator(service, servicePath, options) {
+ let initialized = false;
+ const port = options.port;
+ const debug = options.debug;
+ let params = ['--port', port];
+ if (debug) {
+ params = params.concat(['--debug']);
+ logServerless('Emulator initializing in debug mode...');
+ } else {
+ logServerless('Emulator initializing...');
+ }
+ const cp = childProcess.spawn('sle', params);
+
+ return new BbPromise((resolve, reject) => {
+ cp.stdout.on('data', stdout => {
+ logLocalEmulator(stdout.toString('utf8'));
+ if (!initialized) {
+ initialized = true;
+ return deployFunctionsToLocalEmulator(service, servicePath,
+ getLocalRootUrl(port)).then(() => resolve());
+ }
+ return resolve();
+ });
+
+ cp.stderr.on('data', stderr => {
+ logLocalEmulator(stderr.toString('utf8'));
+ });
+
+ cp.on('close', () => resolve());
+ cp.on('error', error => reject(error));
+
+ process.on('exit', () => cp.kill());
+ });
+}
+
+module.exports = manageLocalEmulator;
diff --git a/lib/plugins/run/utils/registerFunctionsToEventGateway.js b/lib/plugins/run/utils/registerFunctionsToEventGateway.js
new file mode 100644
index 000000000..3fe352d87
--- /dev/null
+++ b/lib/plugins/run/utils/registerFunctionsToEventGateway.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const fdk = require('@serverless/fdk');
+const getConfigureConfig = require('./getConfigureConfig');
+
+function registerFunctionsToEventGateway(service,
+ eventsRootUrl,
+ configurationRootUrl,
+ localEmulatorRootUrl) {
+ const gateway = fdk.eventGateway({
+ url: eventsRootUrl,
+ configurationUrl: configurationRootUrl,
+ });
+
+ const configureConfig = getConfigureConfig(service, localEmulatorRootUrl);
+ return gateway.configure(configureConfig);
+}
+
+module.exports = registerFunctionsToEventGateway;
diff --git a/lib/utils/getAuthToken.js b/lib/utils/getAuthToken.js
new file mode 100644
index 000000000..71081335f
--- /dev/null
+++ b/lib/utils/getAuthToken.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const configUtils = require('./config');
+
+function getAuthToken() {
+ if (process.env.SERVERLESS_TOKEN) {
+ return process.env.SERVERLESS_TOKEN;
+ }
+
+ const userConfig = configUtils.getConfig();
+ const currentId = userConfig.userId;
+ const globalConfig = configUtils.getGlobalConfig();
+ if (globalConfig.users && globalConfig.users[currentId] && globalConfig.users[currentId].auth) {
+ return globalConfig.users[currentId].auth.id_token;
+ }
+ return null;
+}
+
+module.exports = getAuthToken;
diff --git a/lib/utils/isDockerContainer.js b/lib/utils/isDockerContainer.js
deleted file mode 100644
index 57e89b282..000000000
--- a/lib/utils/isDockerContainer.js
+++ /dev/null
@@ -1,20 +0,0 @@
-'use strict';
-
-const path = require('path');
-const readFileSync = require('./fs/readFileSync');
-const fileExistsSync = require('./fs/fileExistsSync');
-
-/* Check if is inside docker container */
-module.exports = function isDockerContainer() {
- // wrap in try catch to make sure that missing permissions won't break anything
- try {
- const cgroupFilePath = path.join('/', 'proc', '1', 'cgroup');
- if (fileExistsSync(cgroupFilePath)) {
- const cgroupFileContent = readFileSync(cgroupFilePath).toString();
- return !!cgroupFileContent.match(/docker/);
- }
- } catch (exception) {
- // do nothing
- }
- return false;
-};
diff --git a/lib/utils/openBrowser.js b/lib/utils/openBrowser.js
index bc419d194..965e18893 100644
--- a/lib/utils/openBrowser.js
+++ b/lib/utils/openBrowser.js
@@ -4,7 +4,7 @@
const opn = require('opn');
const chalk = require('chalk');
-const isDockerContainer = require('./isDockerContainer');
+const isDockerContainer = require('is-docker');
function displayManualOpenMessage(url) {
// https://github.com/sindresorhus/log-symbols
diff --git a/lib/utils/userStats.js b/lib/utils/userStats.js
index f25ecc7aa..718fbc4a5 100644
--- a/lib/utils/userStats.js
+++ b/lib/utils/userStats.js
@@ -48,15 +48,13 @@ function track(eventName, payload) {
return BbPromise.resolve();
}
+ const config = configUtils.getConfig();
+ const frameworkId = config.frameworkId;
// getConfig for values if not provided from .track call
if (!userId || !userEmail) {
- const config = configUtils.getConfig();
userId = config.userId;
if (config.users && config.users[userId] && config.users[userId].email) {
userEmail = config.users[userId].email;
- } else {
- debug('exit early if no user data or email found');
- return BbPromise.resolve();
}
}
@@ -73,6 +71,7 @@ function track(eventName, payload) {
const defaultData = {
event: eventName,
id: userId,
+ frameworkId,
email: userEmail,
data: {
id: userId,
diff --git a/package-lock.json b/package-lock.json
index c0efece23..317d290a2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,25 +1,17 @@
{
"name": "serverless",
- "version": "1.19.0",
+ "version": "1.20.2",
"lockfileVersion": 1,
- "requires": true,
"dependencies": {
- "@types/async": {
- "version": "2.0.40",
- "resolved": "https://registry.npmjs.org/@types/async/-/async-2.0.40.tgz",
- "integrity": "sha1-rALeaOZsAEpht8sW34sds6JUzKk=",
- "optional": true
+ "@serverless/fdk": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@serverless/fdk/-/fdk-0.3.5.tgz",
+ "integrity": "sha512-0xbTEX4u6AjLmOFZ5XODEIDRmjrPW1EzcdZPkrbiWY37LLwpjEHw7qgtToK56PgN1P99qHT1fKhuhTulKVxGWA=="
},
"@types/graphql": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.9.1.tgz",
- "integrity": "sha1-sE6+hLyZfMYNvqLtTQ1DQsc3+Z0=",
- "optional": true
- },
- "@types/isomorphic-fetch": {
- "version": "0.0.34",
- "resolved": "https://registry.npmjs.org/@types/isomorphic-fetch/-/isomorphic-fetch-0.0.34.tgz",
- "integrity": "sha1-PDSD5gbAQTeEOOlRRk8A5OYHBtY=",
+ "version": "0.10.2",
+ "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.10.2.tgz",
+ "integrity": "sha512-Ayw0w+kr8vYd8DToiMXjcHxXv1ljWbqX2mnLwXDxkBgog3vywGriC0JZ+npsuohKs3+E88M8OOtobo4g0X3SIA==",
"optional": true
},
"abab": {
@@ -45,9 +37,6 @@
"resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz",
"integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=",
"dev": true,
- "requires": {
- "acorn": "4.0.13"
- },
"dependencies": {
"acorn": {
"version": "4.0.13",
@@ -62,9 +51,6 @@
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
"integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
"dev": true,
- "requires": {
- "acorn": "3.3.0"
- },
"dependencies": {
"acorn": {
"version": "3.3.0",
@@ -78,10 +64,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz",
"integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=",
- "requires": {
- "extend": "3.0.1",
- "semver": "5.0.3"
- },
"dependencies": {
"semver": {
"version": "5.0.3",
@@ -94,11 +76,7 @@
"version": "4.11.8",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
"integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
- "dev": true,
- "requires": {
- "co": "4.6.0",
- "json-stable-stringify": "1.0.1"
- }
+ "dev": true
},
"ajv-keywords": {
"version": "1.5.1",
@@ -110,12 +88,7 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
"integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
- "dev": true,
- "requires": {
- "kind-of": "3.2.2",
- "longest": "1.0.1",
- "repeat-string": "1.6.1"
- }
+ "dev": true
},
"amdefine": {
"version": "1.0.1",
@@ -137,10 +110,7 @@
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz",
"integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=",
- "dev": true,
- "requires": {
- "ansi-wrap": "0.1.0"
- }
+ "dev": true
},
"ansi-regex": {
"version": "2.1.1",
@@ -148,9 +118,9 @@
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug=="
},
"ansi-wrap": {
"version": "0.1.0",
@@ -165,94 +135,53 @@
"dev": true
},
"apollo-client": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-1.4.2.tgz",
- "integrity": "sha1-PUnRmu+guvkO3uVAGjWOQzpuYk8=",
- "requires": {
- "@types/async": "2.0.40",
- "@types/graphql": "0.9.1",
- "@types/isomorphic-fetch": "0.0.34",
- "graphql": "0.10.1",
- "graphql-anywhere": "3.1.0",
- "graphql-tag": "2.4.0",
- "redux": "3.7.0",
- "symbol-observable": "1.0.4",
- "whatwg-fetch": "2.0.3"
- }
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-1.9.1.tgz",
+ "integrity": "sha512-30e5851mju1mhJzfONvPg3fjYz7rUwjxNAuEIyhFrjWyUYWSBBOEC7+loGPCrj4I0nuTWcKe54rxqtjH8v5vcA=="
+ },
+ "apollo-link-core": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/apollo-link-core/-/apollo-link-core-0.5.0.tgz",
+ "integrity": "sha1-3IfaGqpjsCkyGucJONwmJX9auMY="
},
"append-transform": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz",
"integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=",
- "dev": true,
- "requires": {
- "default-require-extensions": "1.0.0"
- }
+ "dev": true
},
"archiver": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/archiver/-/archiver-1.3.0.tgz",
"integrity": "sha1-TyGU1tj5nfP1MeaIHxTxXVX6ryI=",
- "requires": {
- "archiver-utils": "1.3.0",
- "async": "2.4.1",
- "buffer-crc32": "0.2.13",
- "glob": "7.1.2",
- "lodash": "4.17.4",
- "readable-stream": "2.2.11",
- "tar-stream": "1.5.4",
- "walkdir": "0.0.11",
- "zip-stream": "1.1.1"
- },
"dependencies": {
"async": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz",
- "integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=",
- "requires": {
- "lodash": "4.17.4"
- }
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz",
+ "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw=="
}
}
},
"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.1.2",
- "graceful-fs": "4.1.11",
- "lazystream": "1.0.0",
- "lodash": "4.17.4",
- "normalize-path": "2.1.1",
- "readable-stream": "2.2.11"
- }
+ "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ="
},
"are-we-there-yet": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
- "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
- "requires": {
- "delegates": "1.0.0",
- "readable-stream": "2.2.11"
- }
+ "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0="
},
"argparse": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
- "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
- "requires": {
- "sprintf-js": "1.0.3"
- }
+ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY="
},
"arr-diff": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
"integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
- "dev": true,
- "requires": {
- "arr-flatten": "1.1.0"
- }
+ "dev": true
},
"arr-flatten": {
"version": "1.1.0",
@@ -269,10 +198,7 @@
"array-union": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
- "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
- "requires": {
- "array-uniq": "1.0.3"
- }
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk="
},
"array-uniq": {
"version": "1.0.3",
@@ -289,11 +215,7 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz",
"integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=",
- "dev": true,
- "requires": {
- "define-properties": "1.1.2",
- "es-abstract": "1.7.0"
- }
+ "dev": true
},
"arrify": {
"version": "1.0.1",
@@ -302,9 +224,9 @@
"dev": true
},
"asap": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz",
- "integrity": "sha1-UidltQw1EEkOUtfc/ghe+bqWlY8=",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
"dev": true
},
"asn1": {
@@ -342,21 +264,15 @@
"dev": true
},
"aws-sdk": {
- "version": "2.67.0",
- "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.67.0.tgz",
- "integrity": "sha1-wPw6Q0PPxjEmXZ3WvFC6cJQB+Fc=",
- "requires": {
- "buffer": "5.0.6",
- "crypto-browserify": "1.0.9",
- "jmespath": "0.15.0",
- "querystring": "0.2.0",
- "sax": "1.2.1",
- "url": "0.10.3",
- "uuid": "3.0.1",
- "xml2js": "0.4.17",
- "xmlbuilder": "4.2.1"
- },
+ "version": "2.102.0",
+ "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.102.0.tgz",
+ "integrity": "sha1-cOUqjv9j3kxo4dCMXDfbVWEyQ0A=",
"dependencies": {
+ "url": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
+ "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ="
+ },
"uuid": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz",
@@ -377,71 +293,55 @@
"dev": true
},
"babel-code-frame": {
- "version": "6.22.0",
- "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz",
- "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=",
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
"dev": true,
- "requires": {
- "chalk": "1.1.3",
- "esutils": "2.0.2",
- "js-tokens": "3.0.1"
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
}
},
"babel-core": {
- "version": "6.25.0",
- "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.25.0.tgz",
- "integrity": "sha1-fdQrBGPHQunVKW3rPsZ6kyLa1yk=",
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz",
+ "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=",
"dev": true,
- "requires": {
- "babel-code-frame": "6.22.0",
- "babel-generator": "6.25.0",
- "babel-helpers": "6.24.1",
- "babel-messages": "6.23.0",
- "babel-register": "6.24.1",
- "babel-runtime": "6.23.0",
- "babel-template": "6.25.0",
- "babel-traverse": "6.25.0",
- "babel-types": "6.25.0",
- "babylon": "6.17.4",
- "convert-source-map": "1.5.0",
- "debug": "2.6.8",
- "json5": "0.5.1",
- "lodash": "4.17.4",
- "minimatch": "3.0.4",
- "path-is-absolute": "1.0.1",
- "private": "0.1.7",
- "slash": "1.0.0",
- "source-map": "0.5.6"
- },
"dependencies": {
"source-map": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
- "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
}
}
},
"babel-generator": {
- "version": "6.25.0",
- "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.25.0.tgz",
- "integrity": "sha1-M6GvcNXyiQrrRlpKd5PB32qeqfw=",
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz",
+ "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=",
"dev": true,
- "requires": {
- "babel-messages": "6.23.0",
- "babel-runtime": "6.23.0",
- "babel-types": "6.25.0",
- "detect-indent": "4.0.0",
- "jsesc": "1.3.0",
- "lodash": "4.17.4",
- "source-map": "0.5.6",
- "trim-right": "1.0.1"
- },
"dependencies": {
"source-map": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
- "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
}
}
@@ -450,43 +350,25 @@
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
"integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.23.0",
- "babel-template": "6.25.0"
- }
+ "dev": true
},
"babel-jest": {
"version": "18.0.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-18.0.0.tgz",
"integrity": "sha1-F+u6jLMoXJBthZ6HB+Tnl5X7ZeM=",
- "dev": true,
- "requires": {
- "babel-core": "6.25.0",
- "babel-plugin-istanbul": "3.1.2",
- "babel-preset-jest": "18.0.0"
- }
+ "dev": true
},
"babel-messages": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
"integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.23.0"
- }
+ "dev": true
},
"babel-plugin-istanbul": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-3.1.2.tgz",
"integrity": "sha1-EdWr3hhCXsJLXWSMfgtdJc01SiI=",
- "dev": true,
- "requires": {
- "find-up": "1.1.2",
- "istanbul-lib-instrument": "1.7.3",
- "object-assign": "4.1.1",
- "test-exclude": "3.3.0"
- }
+ "dev": true
},
"babel-plugin-jest-hoist": {
"version": "18.0.0",
@@ -498,111 +380,65 @@
"version": "18.0.0",
"resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-18.0.0.tgz",
"integrity": "sha1-hPr4yj7GWrp9Xj9Zu67ZNaskBJ4=",
- "dev": true,
- "requires": {
- "babel-plugin-jest-hoist": "18.0.0"
- }
+ "dev": true
},
"babel-register": {
- "version": "6.24.1",
- "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz",
- "integrity": "sha1-fhDhOi9xBlvfrVoXh7pFvKbe118=",
- "dev": true,
- "requires": {
- "babel-core": "6.25.0",
- "babel-runtime": "6.23.0",
- "core-js": "2.4.1",
- "home-or-tmp": "2.0.0",
- "lodash": "4.17.4",
- "mkdirp": "0.5.1",
- "source-map-support": "0.4.15"
- }
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
+ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=",
+ "dev": true
},
"babel-runtime": {
- "version": "6.23.0",
- "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz",
- "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=",
- "dev": true,
- "requires": {
- "core-js": "2.4.1",
- "regenerator-runtime": "0.10.5"
- }
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "dev": true
},
"babel-template": {
- "version": "6.25.0",
- "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.25.0.tgz",
- "integrity": "sha1-ZlJBFmt8KqTGGdceGSlpVSsQwHE=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.23.0",
- "babel-traverse": "6.25.0",
- "babel-types": "6.25.0",
- "babylon": "6.17.4",
- "lodash": "4.17.4"
- }
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
+ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
+ "dev": true
},
"babel-traverse": {
- "version": "6.25.0",
- "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.25.0.tgz",
- "integrity": "sha1-IldJfi/NGbie3BPEyROB+VEklvE=",
- "dev": true,
- "requires": {
- "babel-code-frame": "6.22.0",
- "babel-messages": "6.23.0",
- "babel-runtime": "6.23.0",
- "babel-types": "6.25.0",
- "babylon": "6.17.4",
- "debug": "2.6.8",
- "globals": "9.18.0",
- "invariant": "2.2.2",
- "lodash": "4.17.4"
- }
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+ "dev": true
},
"babel-types": {
- "version": "6.25.0",
- "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.25.0.tgz",
- "integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4=",
- "dev": true,
- "requires": {
- "babel-runtime": "6.23.0",
- "esutils": "2.0.2",
- "lodash": "4.17.4",
- "to-fast-properties": "1.0.3"
- }
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+ "dev": true
},
"babylon": {
- "version": "6.17.4",
- "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.4.tgz",
- "integrity": "sha512-kChlV+0SXkjE0vUn9OZ7pBMWRFd8uq3mZe8x1K6jhuNcAFAtEnjchFAqB+dYEXKyd+JpT6eppRR78QAr5gTsUw==",
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
"dev": true
},
"balanced-match": {
- "version": "0.4.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
- "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"base64-js": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz",
- "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE="
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
+ "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw=="
},
"bcrypt-pbkdf": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
"dev": true,
- "optional": true,
- "requires": {
- "tweetnacl": "0.14.5"
- }
+ "optional": true
},
"bl": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz",
- "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=",
- "requires": {
- "readable-stream": "2.2.11"
- }
+ "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4="
},
"bluebird": {
"version": "3.5.0",
@@ -613,39 +449,24 @@
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
- "dev": true,
- "requires": {
- "hoek": "2.16.3"
- }
+ "dev": true
},
"brace-expansion": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz",
- "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=",
- "requires": {
- "balanced-match": "0.4.2",
- "concat-map": "0.0.1"
- }
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI="
},
"braces": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
"integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
- "dev": true,
- "requires": {
- "expand-range": "1.8.2",
- "preserve": "0.2.0",
- "repeat-element": "1.1.2"
- }
+ "dev": true
},
"browser-resolve": {
"version": "1.11.2",
"resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz",
"integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=",
"dev": true,
- "requires": {
- "resolve": "1.1.7"
- },
"dependencies": {
"resolve": {
"version": "1.1.7",
@@ -665,19 +486,12 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bser/-/bser-1.0.2.tgz",
"integrity": "sha1-OBEWlwsqbe6lZG3RXdcnhES1YWk=",
- "dev": true,
- "requires": {
- "node-int64": "0.4.0"
- }
+ "dev": true
},
"buffer": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.6.tgz",
- "integrity": "sha1-LqZp9+7Atu2gWwj4tf9mGyhXNYg=",
- "requires": {
- "base64-js": "1.2.0",
- "ieee754": "1.1.8"
- }
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg="
},
"buffer-crc32": {
"version": "0.2.13",
@@ -694,19 +508,13 @@
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/caller-id/-/caller-id-0.1.0.tgz",
"integrity": "sha1-Wb2sCJPRLDhxQIJ5Ix+XRYNk8Hs=",
- "dev": true,
- "requires": {
- "stack-trace": "0.0.9"
- }
+ "dev": true
},
"caller-path": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
"integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
- "dev": true,
- "requires": {
- "callsites": "0.2.0"
- }
+ "dev": true
},
"callsites": {
"version": "0.2.0",
@@ -730,11 +538,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/cardinal/-/cardinal-1.0.0.tgz",
"integrity": "sha1-UOIcGwqjdyn5N33vGWtanOyTLuk=",
- "dev": true,
- "requires": {
- "ansicolors": "0.2.1",
- "redeyed": "1.0.1"
- }
+ "dev": true
},
"caseless": {
"version": "0.11.0",
@@ -743,56 +547,33 @@
"dev": true
},
"caw": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.0.tgz",
- "integrity": "sha1-Efi93C+AFGmVLV4yJbqYSVovoP8=",
- "requires": {
- "get-proxy": "1.1.0",
- "tunnel-agent": "0.4.3"
- }
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz",
+ "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA=="
},
"center-align": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
"integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
"dev": true,
- "optional": true,
- "requires": {
- "align-text": "0.1.4",
- "lazy-cache": "1.0.4"
- }
+ "optional": true
},
"chai": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz",
"integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=",
- "dev": true,
- "requires": {
- "assertion-error": "1.0.2",
- "deep-eql": "0.1.3",
- "type-detect": "1.0.0"
- }
+ "dev": true
},
"chai-as-promised": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-6.0.0.tgz",
"integrity": "sha1-GgKkM6byTa+sY7nJb6FoTbGqjaY=",
- "dev": true,
- "requires": {
- "check-error": "1.0.2"
- }
+ "dev": true
},
"chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
- "requires": {
- "ansi-styles": "2.2.1",
- "escape-string-regexp": "1.0.5",
- "has-ansi": "2.0.0",
- "strip-ansi": "3.0.1",
- "supports-color": "2.0.0"
- }
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
+ "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ=="
},
"check-error": {
"version": "1.0.2",
@@ -806,42 +587,32 @@
"integrity": "sha1-3FKF8rTiUYIWg2gcOBwziPRuxTQ="
},
"circular-json": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz",
- "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=",
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+ "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
"dev": true
},
"cli-cursor": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
- "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
- "requires": {
- "restore-cursor": "1.0.1"
- }
+ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc="
},
"cli-table": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz",
"integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=",
- "dev": true,
- "requires": {
- "colors": "1.0.3"
- }
+ "dev": true
},
"cli-usage": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/cli-usage/-/cli-usage-0.1.4.tgz",
"integrity": "sha1-fAHg3HBsI0s5yTODjI4gshdXduI=",
- "dev": true,
- "requires": {
- "marked": "0.3.6",
- "marked-terminal": "1.7.0"
- }
+ "dev": true
},
"cli-width": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz",
- "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao="
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
},
"cliui": {
"version": "2.1.0",
@@ -849,11 +620,6 @@
"integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
"dev": true,
"optional": true,
- "requires": {
- "center-align": "0.1.3",
- "right-align": "0.1.3",
- "wordwrap": "0.0.2"
- },
"dependencies": {
"wordwrap": {
"version": "0.0.2",
@@ -876,11 +642,21 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"coffee-script": {
- "version": "1.12.6",
- "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.6.tgz",
- "integrity": "sha1-KFo/cRVokGUGTWv570Vy22ZpXL8=",
+ "version": "1.12.7",
+ "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz",
+ "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==",
"dev": true
},
+ "color-convert": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz",
+ "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o="
+ },
+ "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.0.3",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
@@ -890,18 +666,12 @@
"combined-stream": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
- "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
- "requires": {
- "delayed-stream": "1.0.0"
- }
+ "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk="
},
"commander": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
- "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
- "requires": {
- "graceful-readlink": "1.0.1"
- }
+ "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ="
},
"component-emitter": {
"version": "1.2.1",
@@ -911,13 +681,7 @@
"compress-commons": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.0.tgz",
- "integrity": "sha1-WFhwku8g03y1i68AARLJJ4/3O58=",
- "requires": {
- "buffer-crc32": "0.2.13",
- "crc32-stream": "2.0.0",
- "normalize-path": "2.1.1",
- "readable-stream": "2.2.11"
- }
+ "integrity": "sha1-WFhwku8g03y1i68AARLJJ4/3O58="
},
"concat-map": {
"version": "0.0.1",
@@ -927,12 +691,12 @@
"concat-stream": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
- "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=",
- "requires": {
- "inherits": "2.0.3",
- "readable-stream": "2.2.11",
- "typedarray": "0.0.6"
- }
+ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc="
+ },
+ "config-chain": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz",
+ "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI="
},
"contains-path": {
"version": "0.1.0",
@@ -963,9 +727,9 @@
"integrity": "sha1-Qa1XsbVVlR7BcUEqgZQrHoIA00o="
},
"core-js": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
- "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=",
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz",
+ "integrity": "sha1-VpwFCRi+ZIazg3VSAorgRmtxcIY=",
"dev": true
},
"core-util-is": {
@@ -978,12 +742,19 @@
"resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.1.tgz",
"integrity": "sha1-1wu5rMGDXsTwY/+drFQjwXsR8Xg=",
"dev": true,
- "requires": {
- "js-yaml": "3.8.4",
- "lcov-parse": "0.0.10",
- "log-driver": "1.2.5",
- "minimist": "1.2.0",
- "request": "2.79.0"
+ "dependencies": {
+ "esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz",
+ "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=",
+ "dev": true
+ }
}
},
"crc": {
@@ -994,28 +765,18 @@
"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.2.11"
- }
+ "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ="
},
"create-error-class": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
- "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
- "requires": {
- "capture-stack-trace": "1.0.0"
- }
+ "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y="
},
"cryptiles": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
"integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
- "dev": true,
- "requires": {
- "boom": "2.10.1"
- }
+ "dev": true
},
"crypto-browserify": {
"version": "1.0.9",
@@ -1032,19 +793,13 @@
"version": "0.2.37",
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz",
"integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=",
- "dev": true,
- "requires": {
- "cssom": "0.3.2"
- }
+ "dev": true
},
"d": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
"integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
- "dev": true,
- "requires": {
- "es5-ext": "0.10.23"
- }
+ "dev": true
},
"damerau-levenshtein": {
"version": "1.0.4",
@@ -1057,9 +812,6 @@
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"dev": true,
- "requires": {
- "assert-plus": "1.0.0"
- },
"dependencies": {
"assert-plus": {
"version": "1.0.0",
@@ -1072,10 +824,7 @@
"debug": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
- "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
- "requires": {
- "ms": "2.0.0"
- }
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw="
},
"decamelize": {
"version": "1.2.0",
@@ -1086,77 +835,44 @@
"decompress": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz",
- "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=",
- "requires": {
- "decompress-tar": "4.1.0",
- "decompress-tarbz2": "4.1.0",
- "decompress-targz": "4.1.0",
- "decompress-unzip": "4.0.1",
- "graceful-fs": "4.1.11",
- "make-dir": "1.0.0",
- "pify": "2.3.0",
- "strip-dirs": "2.0.0"
- }
+ "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50="
},
"decompress-tar": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.0.tgz",
- "integrity": "sha1-HwkqtphEBVjHL8eOd9JG0+y0U7A=",
- "requires": {
- "file-type": "3.9.0",
- "is-stream": "1.1.0",
- "tar-stream": "1.5.4"
- }
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz",
+ "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ=="
},
"decompress-tarbz2": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.0.tgz",
- "integrity": "sha1-+6tY1d5z8/0hPKw68cGDNPUcuJE=",
- "requires": {
- "decompress-tar": "4.1.0",
- "file-type": "3.9.0",
- "is-stream": "1.1.0",
- "pify": "2.3.0",
- "seek-bzip": "1.0.5",
- "unbzip2-stream": "1.2.4"
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz",
+ "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==",
+ "dependencies": {
+ "file-type": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.1.0.tgz",
+ "integrity": "sha1-Wn26mBOPoKvsevxD5amgsqrHKfE="
+ }
}
},
"decompress-targz": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.0.tgz",
- "integrity": "sha1-R1ucQGvmIa6DYnSALZsl+ZE+rVk=",
- "requires": {
- "decompress-tar": "4.1.0",
- "file-type": "4.4.0",
- "is-stream": "1.1.0"
- },
- "dependencies": {
- "file-type": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz",
- "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU="
- }
- }
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz",
+ "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w=="
},
"decompress-unzip": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz",
"integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=",
- "requires": {
- "file-type": "3.9.0",
- "get-stream": "2.3.1",
- "pify": "2.3.0",
- "yauzl": "2.8.0"
- },
"dependencies": {
+ "file-type": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
+ "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek="
+ },
"get-stream": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
- "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=",
- "requires": {
- "object-assign": "4.1.1",
- "pinkie-promise": "2.0.1"
- }
+ "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4="
}
}
},
@@ -1165,9 +881,6 @@
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz",
"integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=",
"dev": true,
- "requires": {
- "type-detect": "0.1.1"
- },
"dependencies": {
"type-detect": {
"version": "0.1.1",
@@ -1189,9 +902,9 @@
"dev": true
},
"deepmerge": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.0.tgz",
- "integrity": "sha512-Hm4+NyDQGgH3oYhKqR0gd99veBBZpnEUNoEfFl+3PRkQL+LKGJEBgqimeofAWzUn6aBzcaYPJrRigto/WfDzTg==",
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.1.tgz",
+ "integrity": "sha512-Ndl8eeOHB9dQkmT1HWCgY3t0odl4bmWKFzjQZBYAxVTNs2B3nn5b6orimRYHKZ4FI8psvZkA1INRCW6l7vc9lQ==",
"dev": true
},
"default-require-extensions": {
@@ -1199,18 +912,12 @@
"resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz",
"integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=",
"dev": true,
- "requires": {
- "strip-bom": "2.0.0"
- },
"dependencies": {
"strip-bom": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
- "dev": true,
- "requires": {
- "is-utf8": "0.2.1"
- }
+ "dev": true
}
}
},
@@ -1218,25 +925,20 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
"integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
- "dev": true,
- "requires": {
- "foreach": "2.0.5",
- "object-keys": "1.0.11"
- }
+ "dev": true
},
"del": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
"integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
"dev": true,
- "requires": {
- "globby": "6.1.0",
- "is-path-cwd": "1.0.0",
- "is-path-in-cwd": "1.0.0",
- "object-assign": "4.1.1",
- "pify": "2.3.0",
- "pinkie-promise": "2.0.1",
- "rimraf": "2.6.1"
+ "dependencies": {
+ "globby": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+ "dev": true
+ }
}
},
"delayed-stream": {
@@ -1253,10 +955,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
"integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
- "dev": true,
- "requires": {
- "repeating": "2.0.1"
- }
+ "dev": true
},
"diacritics-map": {
"version": "0.1.0",
@@ -1274,25 +973,12 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz",
"integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=",
- "dev": true,
- "requires": {
- "esutils": "2.0.2",
- "isarray": "1.0.0"
- }
+ "dev": true
},
"download": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/download/-/download-5.0.3.tgz",
- "integrity": "sha1-Y1N/l3+ZJmow64oqL70fILgAD3o=",
- "requires": {
- "caw": "2.0.0",
- "decompress": "4.2.0",
- "filenamify": "2.0.0",
- "get-stream": "3.0.0",
- "got": "6.7.1",
- "mkdirp": "0.5.1",
- "pify": "2.3.0"
- }
+ "integrity": "sha1-Y1N/l3+ZJmow64oqL70fILgAD3o="
},
"duplexer3": {
"version": "0.1.4",
@@ -1304,102 +990,59 @@
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
"dev": true,
- "optional": true,
- "requires": {
- "jsbn": "0.1.1"
- }
+ "optional": true
},
"encoding": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
- "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
- "requires": {
- "iconv-lite": "0.4.17"
- }
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s="
},
"end-of-stream": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz",
- "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=",
- "requires": {
- "once": "1.4.0"
- }
+ "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY="
},
"errno": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz",
"integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=",
- "dev": true,
- "requires": {
- "prr": "0.0.0"
- }
+ "dev": true
},
"error-ex": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
"integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
- "dev": true,
- "requires": {
- "is-arrayish": "0.2.1"
- }
+ "dev": true
},
"es-abstract": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz",
- "integrity": "sha1-363ndOAb/Nl/lhgCmMRJyGI/uUw=",
- "dev": true,
- "requires": {
- "es-to-primitive": "1.1.1",
- "function-bind": "1.1.0",
- "is-callable": "1.1.3",
- "is-regex": "1.0.4"
- }
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.8.0.tgz",
+ "integrity": "sha512-Cf9/h5MrXtExM20gSS55YFrGKCyPrRBjIVBtVyy8vmlsDfe0NPKMWj65tPLgzyfPuapWxh5whpXCtW4+AW5mRg==",
+ "dev": true
},
"es-to-primitive": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
"integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
- "dev": true,
- "requires": {
- "is-callable": "1.1.3",
- "is-date-object": "1.0.1",
- "is-symbol": "1.0.1"
- }
+ "dev": true
},
"es5-ext": {
- "version": "0.10.23",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.23.tgz",
- "integrity": "sha1-dXi1G+l0IHpUh4IbVlOMIk5Oezg=",
- "dev": true,
- "requires": {
- "es6-iterator": "2.0.1",
- "es6-symbol": "3.1.1"
- }
+ "version": "0.10.29",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.29.tgz",
+ "integrity": "sha512-KXla9NXo5sdaEkGSmbFPYgjH6m75kxsthL6GDRSug/Y2OiMoYm0I9giL39j4cgmaFmAbkIFJ6gG+SGKnLSmOvA==",
+ "dev": true
},
"es6-iterator": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz",
"integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=",
- "dev": true,
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.23",
- "es6-symbol": "3.1.1"
- }
+ "dev": true
},
"es6-map": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
"integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
- "dev": true,
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.23",
- "es6-iterator": "2.0.1",
- "es6-set": "0.1.5",
- "es6-symbol": "3.1.1",
- "event-emitter": "0.3.5"
- }
+ "dev": true
},
"es6-promise": {
"version": "3.0.2",
@@ -1411,36 +1054,19 @@
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
"integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
- "dev": true,
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.23",
- "es6-iterator": "2.0.1",
- "es6-symbol": "3.1.1",
- "event-emitter": "0.3.5"
- }
+ "dev": true
},
"es6-symbol": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
"integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
- "dev": true,
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.23"
- }
+ "dev": true
},
"es6-weak-map": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz",
"integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=",
- "dev": true,
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.23",
- "es6-iterator": "2.0.1",
- "es6-symbol": "3.1.1"
- }
+ "dev": true
},
"escape-string-regexp": {
"version": "1.0.5",
@@ -1452,14 +1078,13 @@
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
"integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=",
"dev": true,
- "requires": {
- "esprima": "3.1.3",
- "estraverse": "1.9.3",
- "esutils": "2.0.2",
- "optionator": "0.8.2",
- "source-map": "0.2.0"
- },
"dependencies": {
+ "esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+ "dev": true
+ },
"estraverse": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
@@ -1472,65 +1097,57 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
"integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=",
- "dev": true,
- "requires": {
- "es6-map": "0.1.5",
- "es6-weak-map": "2.0.2",
- "esrecurse": "4.2.0",
- "estraverse": "4.2.0"
- }
+ "dev": true
},
"eslint": {
"version": "3.19.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz",
"integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=",
"dev": true,
- "requires": {
- "babel-code-frame": "6.22.0",
- "chalk": "1.1.3",
- "concat-stream": "1.6.0",
- "debug": "2.6.8",
- "doctrine": "2.0.0",
- "escope": "3.6.0",
- "espree": "3.4.3",
- "esquery": "1.0.0",
- "estraverse": "4.2.0",
- "esutils": "2.0.2",
- "file-entry-cache": "2.0.0",
- "glob": "7.1.2",
- "globals": "9.18.0",
- "ignore": "3.3.3",
- "imurmurhash": "0.1.4",
- "inquirer": "1.2.3",
- "is-my-json-valid": "2.16.0",
- "is-resolvable": "1.0.0",
- "js-yaml": "3.8.4",
- "json-stable-stringify": "1.0.1",
- "levn": "0.3.0",
- "lodash": "4.17.4",
- "mkdirp": "0.5.1",
- "natural-compare": "1.4.0",
- "optionator": "0.8.2",
- "path-is-inside": "1.0.2",
- "pluralize": "1.2.1",
- "progress": "1.1.8",
- "require-uncached": "1.0.3",
- "shelljs": "0.6.1",
- "strip-bom": "3.0.0",
- "strip-json-comments": "2.0.1",
- "table": "3.8.3",
- "text-table": "0.2.0",
- "user-home": "2.0.0"
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "inquirer": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
+ "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=",
+ "dev": true
+ },
+ "run-async": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz",
+ "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=",
+ "dev": true
+ },
+ "shelljs": {
+ "version": "0.7.8",
+ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz",
+ "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
}
},
"eslint-config-airbnb": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-10.0.1.tgz",
"integrity": "sha1-pHAQhkbWxF4fY5oD8R1QShqkrtw=",
- "dev": true,
- "requires": {
- "eslint-config-airbnb-base": "5.0.3"
- }
+ "dev": true
},
"eslint-config-airbnb-base": {
"version": "5.0.3",
@@ -1542,46 +1159,19 @@
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz",
"integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=",
- "dev": true,
- "requires": {
- "debug": "2.6.8",
- "object-assign": "4.1.1",
- "resolve": "1.3.3"
- }
+ "dev": true
},
"eslint-plugin-import": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-1.16.0.tgz",
"integrity": "sha1-svoH68xTUE0PKkR3WC7Iv/GHG58=",
"dev": true,
- "requires": {
- "builtin-modules": "1.1.1",
- "contains-path": "0.1.0",
- "debug": "2.6.8",
- "doctrine": "1.3.0",
- "es6-map": "0.1.5",
- "es6-set": "0.1.5",
- "eslint-import-resolver-node": "0.2.3",
- "has": "1.0.1",
- "lodash.cond": "4.5.2",
- "lodash.endswith": "4.2.1",
- "lodash.find": "4.6.0",
- "lodash.findindex": "4.6.0",
- "minimatch": "3.0.4",
- "object-assign": "4.1.1",
- "pkg-dir": "1.0.0",
- "pkg-up": "1.0.0"
- },
"dependencies": {
"doctrine": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.3.0.tgz",
"integrity": "sha1-E+dWgrVVGEJCdvfBc3g0Vu+RPSY=",
- "dev": true,
- "requires": {
- "esutils": "2.0.2",
- "isarray": "1.0.0"
- }
+ "dev": true
}
}
},
@@ -1589,71 +1179,44 @@
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-2.2.3.tgz",
"integrity": "sha1-TjXLcbin23AqxBXIBuuOjZ6mxl0=",
- "dev": true,
- "requires": {
- "damerau-levenshtein": "1.0.4",
- "jsx-ast-utils": "1.4.1",
- "object-assign": "4.1.1"
- }
+ "dev": true
},
"eslint-plugin-react": {
"version": "6.10.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz",
"integrity": "sha1-xUNb6wZ3ThLH2y9qut3L+QDNP3g=",
"dev": true,
- "requires": {
- "array.prototype.find": "2.0.4",
- "doctrine": "1.5.0",
- "has": "1.0.1",
- "jsx-ast-utils": "1.4.1",
- "object.assign": "4.0.4"
- },
"dependencies": {
"doctrine": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
"integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
- "dev": true,
- "requires": {
- "esutils": "2.0.2",
- "isarray": "1.0.0"
- }
+ "dev": true
}
}
},
"espree": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz",
- "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=",
- "dev": true,
- "requires": {
- "acorn": "5.1.1",
- "acorn-jsx": "3.0.1"
- }
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.0.tgz",
+ "integrity": "sha1-mDWGJb3QVYYeon4oZ+pyn69GPY0=",
+ "dev": true
},
"esprima": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
- "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw=="
},
"esquery": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz",
"integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=",
- "dev": true,
- "requires": {
- "estraverse": "4.2.0"
- }
+ "dev": true
},
"esrecurse": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz",
"integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=",
- "dev": true,
- "requires": {
- "estraverse": "4.2.0",
- "object-assign": "4.1.1"
- }
+ "dev": true
},
"estraverse": {
"version": "4.2.0",
@@ -1671,20 +1234,18 @@
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
"integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
- "dev": true,
- "requires": {
- "d": "1.0.0",
- "es5-ext": "0.10.23"
- }
+ "dev": true
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
},
"exec-sh": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.0.tgz",
"integrity": "sha1-FPdd4/INKG75MwmbLOUKkDWc7xA=",
- "dev": true,
- "requires": {
- "merge": "1.2.0"
- }
+ "dev": true
},
"exit-hook": {
"version": "1.1.1",
@@ -1695,19 +1256,13 @@
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
"integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
- "dev": true,
- "requires": {
- "is-posix-bracket": "0.1.1"
- }
+ "dev": true
},
"expand-range": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
"integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
- "dev": true,
- "requires": {
- "fill-range": "2.2.3"
- }
+ "dev": true
},
"extend": {
"version": "3.0.1",
@@ -1718,34 +1273,23 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "0.1.1"
- }
+ "dev": true
},
"external-editor": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-1.1.1.tgz",
- "integrity": "sha1-Etew24UPf/fnCBuvQAVwAGDEYAs=",
- "requires": {
- "extend": "3.0.1",
- "spawn-sync": "1.0.15",
- "tmp": "0.0.29"
- }
+ "integrity": "sha1-Etew24UPf/fnCBuvQAVwAGDEYAs="
},
"extglob": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
"integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
- "dev": true,
- "requires": {
- "is-extglob": "1.0.0"
- }
+ "dev": true
},
"extsprintf": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz",
- "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
"dev": true
},
"fast-levenshtein": {
@@ -1758,42 +1302,28 @@
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-1.9.2.tgz",
"integrity": "sha1-okz0eCf4LTj7Waaa1wt247auc4M=",
- "dev": true,
- "requires": {
- "bser": "1.0.2"
- }
+ "dev": true
},
"fd-slicer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
- "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
- "requires": {
- "pend": "1.2.0"
- }
+ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU="
},
"figures": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
- "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
- "requires": {
- "escape-string-regexp": "1.0.5",
- "object-assign": "4.1.1"
- }
+ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4="
},
"file-entry-cache": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
"integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
- "dev": true,
- "requires": {
- "flat-cache": "1.2.2",
- "object-assign": "4.1.1"
- }
+ "dev": true
},
"file-type": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
- "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek="
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
+ "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY="
},
"filename-regex": {
"version": "2.0.1",
@@ -1809,22 +1339,13 @@
"filenamify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.0.0.tgz",
- "integrity": "sha1-vRYiYsC26Uv7zc8Zo7uzdk94VpU=",
- "requires": {
- "filename-reserved-regex": "2.0.0",
- "strip-outer": "1.0.0",
- "trim-repeated": "1.0.0"
- }
+ "integrity": "sha1-vRYiYsC26Uv7zc8Zo7uzdk94VpU="
},
"fileset": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
"integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=",
- "dev": true,
- "requires": {
- "glob": "7.1.2",
- "minimatch": "3.0.4"
- }
+ "dev": true
},
"filesize": {
"version": "3.5.10",
@@ -1835,46 +1356,25 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz",
"integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=",
- "dev": true,
- "requires": {
- "is-object": "1.0.1",
- "merge-descriptors": "1.0.1"
- }
+ "dev": true
},
"fill-range": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
"integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
- "dev": true,
- "requires": {
- "is-number": "2.1.0",
- "isobject": "2.1.0",
- "randomatic": "1.1.7",
- "repeat-element": "1.1.2",
- "repeat-string": "1.6.1"
- }
+ "dev": true
},
"find-up": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
- "dev": true,
- "requires": {
- "path-exists": "2.1.0",
- "pinkie-promise": "2.0.1"
- }
+ "dev": true
},
"flat-cache": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz",
"integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=",
- "dev": true,
- "requires": {
- "circular-json": "0.3.1",
- "del": "2.2.2",
- "graceful-fs": "4.1.11",
- "write": "0.2.1"
- }
+ "dev": true
},
"for-in": {
"version": "1.0.2",
@@ -1886,10 +1386,7 @@
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
"integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
- "dev": true,
- "requires": {
- "for-in": "1.0.2"
- }
+ "dev": true
},
"foreach": {
"version": "2.0.5",
@@ -1904,23 +1401,15 @@
"dev": true
},
"form-data": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
- "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
- "requires": {
- "asynckit": "0.4.0",
- "combined-stream": "1.0.5",
- "mime-types": "2.1.15"
- }
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.2.0.tgz",
+ "integrity": "sha1-ml47kpX5gLJiPPZPojixTOvKcHs="
},
"formatio": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz",
"integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=",
- "dev": true,
- "requires": {
- "samsam": "1.1.2"
- }
+ "dev": true
},
"formidable": {
"version": "1.1.1",
@@ -1930,14 +1419,7 @@
"fs-extra": {
"version": "0.26.7",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
- "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
- "requires": {
- "graceful-fs": "4.1.11",
- "jsonfile": "2.4.0",
- "klaw": "1.3.1",
- "path-is-absolute": "1.0.1",
- "rimraf": "2.6.1"
- }
+ "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k="
},
"fs.realpath": {
"version": "1.0.0",
@@ -1953,14 +1435,7 @@
"gauge": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz",
- "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=",
- "requires": {
- "ansi": "0.3.1",
- "has-unicode": "2.0.1",
- "lodash.pad": "4.5.1",
- "lodash.padend": "4.6.1",
- "lodash.padstart": "4.6.1"
- }
+ "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM="
},
"generate-function": {
"version": "2.0.0",
@@ -1972,10 +1447,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
"integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
- "dev": true,
- "requires": {
- "is-property": "1.0.2"
- }
+ "dev": true
},
"get-caller-file": {
"version": "1.0.2",
@@ -1984,12 +1456,9 @@
"dev": true
},
"get-proxy": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-1.1.0.tgz",
- "integrity": "sha1-iUhUSRvFkbDxR9euVw9cZ4tyVus=",
- "requires": {
- "rc": "1.2.1"
- }
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz",
+ "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw=="
},
"get-stdin": {
"version": "5.0.1",
@@ -2006,9 +1475,6 @@
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"dev": true,
- "requires": {
- "assert-plus": "1.0.0"
- },
"dependencies": {
"assert-plus": {
"version": "1.0.0",
@@ -2021,34 +1487,19 @@
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
- "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
- "requires": {
- "fs.realpath": "1.0.0",
- "inflight": "1.0.6",
- "inherits": "2.0.3",
- "minimatch": "3.0.4",
- "once": "1.4.0",
- "path-is-absolute": "1.0.1"
- }
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ=="
},
"glob-base": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
"integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
- "dev": true,
- "requires": {
- "glob-parent": "2.0.0",
- "is-glob": "2.0.1"
- }
+ "dev": true
},
"glob-parent": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
"integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
- "dev": true,
- "requires": {
- "is-glob": "2.0.1"
- }
+ "dev": true
},
"globals": {
"version": "9.18.0",
@@ -2059,32 +1510,12 @@
"globby": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
- "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
- "requires": {
- "array-union": "1.0.2",
- "glob": "7.1.2",
- "object-assign": "4.1.1",
- "pify": "2.3.0",
- "pinkie-promise": "2.0.1"
- }
+ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw="
},
"got": {
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
- "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
- "requires": {
- "create-error-class": "3.0.2",
- "duplexer3": "0.1.4",
- "get-stream": "3.0.0",
- "is-redirect": "1.0.0",
- "is-retry-allowed": "1.1.0",
- "is-stream": "1.1.0",
- "lowercase-keys": "1.0.0",
- "safe-buffer": "5.0.1",
- "timed-out": "4.0.1",
- "unzip-response": "2.0.1",
- "url-parse-lax": "1.0.0"
- }
+ "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA="
},
"graceful-fs": {
"version": "4.1.11",
@@ -2099,18 +1530,12 @@
"graphlib": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.1.tgz",
- "integrity": "sha1-QjUsUrovTQNctWbrkfc5X3bryVE=",
- "requires": {
- "lodash": "4.17.4"
- }
+ "integrity": "sha1-QjUsUrovTQNctWbrkfc5X3bryVE="
},
"graphql": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.10.1.tgz",
- "integrity": "sha1-dck8LOc661uuLu+1Vajp45w2An0=",
- "requires": {
- "iterall": "1.1.1"
- }
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.10.5.tgz",
+ "integrity": "sha512-Q7cx22DiLhwHsEfUnUip1Ww/Vfx7FS0w6+iHItNuN61+XpegHSa3k5U0+6M5BcpavQImBwFiy0z3uYwY7cXMLQ=="
},
"graphql-anywhere": {
"version": "3.1.0",
@@ -2118,22 +1543,15 @@
"integrity": "sha1-PqDY6GRrXO5oA1AWqadVfBXCHpY="
},
"graphql-tag": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.4.0.tgz",
- "integrity": "sha1-D+E3NI1Nsu+vKbUrpMHL+ErBOMs="
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.4.2.tgz",
+ "integrity": "sha1-amMpfYUi0DorctJvGyOaqzQ4QM0="
},
"gray-matter": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-2.1.1.tgz",
"integrity": "sha1-MELZrewqHe1qdwep7SOA+KF6Qw4=",
- "dev": true,
- "requires": {
- "ansi-red": "0.1.1",
- "coffee-script": "1.12.6",
- "extend-shallow": "2.0.1",
- "js-yaml": "3.8.4",
- "toml": "2.3.2"
- }
+ "dev": true
},
"growl": {
"version": "1.9.2",
@@ -2152,21 +1570,12 @@
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz",
"integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=",
"dev": true,
- "requires": {
- "async": "1.5.2",
- "optimist": "0.6.1",
- "source-map": "0.4.4",
- "uglify-js": "2.8.29"
- },
"dependencies": {
"source-map": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
- "dev": true,
- "requires": {
- "amdefine": "1.0.1"
- }
+ "dev": true
}
}
},
@@ -2175,29 +1584,58 @@
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
"integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
"dev": true,
- "requires": {
- "chalk": "1.1.3",
- "commander": "2.8.1",
- "is-my-json-valid": "2.16.0",
- "pinkie-promise": "2.0.1"
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "commander": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
+ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
}
},
"has": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
"integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
- "dev": true,
- "requires": {
- "function-bind": "1.1.0"
- }
+ "dev": true
},
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
- "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
- "requires": {
- "ansi-regex": "2.1.1"
- }
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE="
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "has-symbol-support-x": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.0.tgz",
+ "integrity": "sha512-F1NtLDtW9NyUrS3faUcI1yVFHCTXyzPb1jfrZBQi5NHxFPlXxZnFLFGzfA2DsdmgCxv2MZ0+bfcgC4EZTmk4SQ=="
+ },
+ "has-to-string-tag-x": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.0.tgz",
+ "integrity": "sha512-R3OdOP9j6AH5hS1yXeu9wAS+iKSZQx/CC6aMdN6WiaqPlBoA2S+47MtoMsZgKr2m0eAJ+73WWGX0RaFFE5XWKA=="
},
"has-unicode": {
"version": "2.0.1",
@@ -2208,13 +1646,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
"integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
- "dev": true,
- "requires": {
- "boom": "2.10.1",
- "cryptiles": "2.0.5",
- "hoek": "2.16.3",
- "sntp": "1.0.9"
- }
+ "dev": true
},
"hoek": {
"version": "2.16.3",
@@ -2226,11 +1658,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
"integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=",
- "dev": true,
- "requires": {
- "os-homedir": "1.0.2",
- "os-tmpdir": "1.0.2"
- }
+ "dev": true
},
"hosted-git-info": {
"version": "2.5.0",
@@ -2242,21 +1670,13 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz",
"integrity": "sha1-eb96eF6klf5mFl5zQVPzY/9UN9o=",
- "dev": true,
- "requires": {
- "whatwg-encoding": "1.0.1"
- }
+ "dev": true
},
"http-basic": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/http-basic/-/http-basic-2.5.1.tgz",
"integrity": "sha1-jORHvbW2xXf4pj4/p4BW7Eu02/s=",
- "dev": true,
- "requires": {
- "caseless": "0.11.0",
- "concat-stream": "1.6.0",
- "http-response-object": "1.1.0"
- }
+ "dev": true
},
"http-response-object": {
"version": "1.1.0",
@@ -2268,27 +1688,17 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
"integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
- "dev": true,
- "requires": {
- "assert-plus": "0.2.0",
- "jsprim": "1.4.0",
- "sshpk": "1.13.1"
- }
+ "dev": true
},
"https-proxy-agent": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz",
- "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=",
- "requires": {
- "agent-base": "2.1.1",
- "debug": "2.6.8",
- "extend": "3.0.1"
- }
+ "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY="
},
"iconv-lite": {
- "version": "0.4.17",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.17.tgz",
- "integrity": "sha1-T9qjs4rLwsAxsEXQ7c3+HsqxjI0="
+ "version": "0.4.18",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
+ "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA=="
},
"ieee754": {
"version": "1.1.8",
@@ -2315,11 +1725,7 @@
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
- "requires": {
- "once": "1.4.0",
- "wrappy": "1.0.2"
- }
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk="
},
"inherits": {
"version": "2.0.3",
@@ -2335,31 +1741,35 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-1.2.3.tgz",
"integrity": "sha1-TexvMvN+97sLLtPx0aXD9UUHSRg=",
- "requires": {
- "ansi-escapes": "1.4.0",
- "chalk": "1.1.3",
- "cli-cursor": "1.0.2",
- "cli-width": "2.1.0",
- "external-editor": "1.1.1",
- "figures": "1.7.0",
- "lodash": "4.17.4",
- "mute-stream": "0.0.6",
- "pinkie-promise": "2.0.1",
- "run-async": "2.3.0",
- "rx": "4.1.0",
- "string-width": "1.0.2",
- "strip-ansi": "3.0.1",
- "through": "2.3.8"
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg="
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+ }
}
},
+ "interpret": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz",
+ "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=",
+ "dev": true
+ },
"invariant": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz",
"integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=",
- "dev": true,
- "requires": {
- "loose-envify": "1.3.1"
- }
+ "dev": true
},
"invert-kv": {
"version": "1.0.0",
@@ -2383,10 +1793,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
- "dev": true,
- "requires": {
- "builtin-modules": "1.1.1"
- }
+ "dev": true
},
"is-callable": {
"version": "1.1.3",
@@ -2398,10 +1805,7 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz",
"integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=",
- "dev": true,
- "requires": {
- "ci-info": "1.0.0"
- }
+ "dev": true
},
"is-date-object": {
"version": "1.0.1",
@@ -2409,6 +1813,11 @@
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
"dev": true
},
+ "is-docker": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-1.1.0.tgz",
+ "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE="
+ },
"is-dotfile": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
@@ -2419,10 +1828,7 @@
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
"integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
- "dev": true,
- "requires": {
- "is-primitive": "2.0.0"
- }
+ "dev": true
},
"is-extendable": {
"version": "0.1.1",
@@ -2440,27 +1846,18 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
"integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
- "dev": true,
- "requires": {
- "number-is-nan": "1.0.1"
- }
+ "dev": true
},
"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.1"
- }
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs="
},
"is-glob": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
- "dev": true,
- "requires": {
- "is-extglob": "1.0.0"
- }
+ "dev": true
},
"is-local-path": {
"version": "0.1.6",
@@ -2469,16 +1866,10 @@
"dev": true
},
"is-my-json-valid": {
- "version": "2.16.0",
- "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz",
- "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=",
- "dev": true,
- "requires": {
- "generate-function": "2.0.0",
- "generate-object-property": "1.2.0",
- "jsonpointer": "4.0.1",
- "xtend": "4.0.1"
- }
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz",
+ "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==",
+ "dev": true
},
"is-natural-number": {
"version": "4.0.1",
@@ -2489,16 +1880,12 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
"integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
- "dev": true,
- "requires": {
- "kind-of": "3.2.2"
- }
+ "dev": true
},
"is-object": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz",
- "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
- "dev": true
+ "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA="
},
"is-path-cwd": {
"version": "1.0.0",
@@ -2510,19 +1897,13 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz",
"integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=",
- "dev": true,
- "requires": {
- "is-path-inside": "1.0.0"
- }
+ "dev": true
},
"is-path-inside": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz",
"integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=",
- "dev": true,
- "requires": {
- "path-is-inside": "1.0.2"
- }
+ "dev": true
},
"is-posix-bracket": {
"version": "0.1.1",
@@ -2556,19 +1937,13 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
- "dev": true,
- "requires": {
- "has": "1.0.1"
- }
+ "dev": true
},
"is-resolvable": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz",
"integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=",
- "dev": true,
- "requires": {
- "tryit": "1.0.3"
- }
+ "dev": true
},
"is-retry-allowed": {
"version": "1.1.0",
@@ -2618,10 +1993,12 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
"integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
- "dev": true,
- "requires": {
- "isarray": "1.0.0"
- }
+ "dev": true
+ },
+ "isomorphic-fetch": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+ "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk="
},
"isstream": {
"version": "0.1.2",
@@ -2634,48 +2011,51 @@
"resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz",
"integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=",
"dev": true,
- "requires": {
- "abbrev": "1.0.9",
- "async": "1.5.2",
- "escodegen": "1.8.1",
- "esprima": "3.1.3",
- "glob": "7.1.2",
- "handlebars": "4.0.10",
- "js-yaml": "3.8.4",
- "mkdirp": "0.5.1",
- "nopt": "3.0.6",
- "once": "1.4.0",
- "resolve": "1.1.7",
- "supports-color": "2.0.0",
- "which": "1.2.14",
- "wordwrap": "1.0.0"
- },
"dependencies": {
+ "esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+ "dev": true
+ },
+ "glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ },
"resolve": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
"integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
"dev": true
+ },
+ "supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "dev": true
}
}
},
"istanbul-api": {
- "version": "1.1.10",
- "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.1.10.tgz",
- "integrity": "sha1-8n5ecSXI3hP2qAZhr3j1EuVDmys=",
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.1.12.tgz",
+ "integrity": "sha1-ktZ+nY+eqHNJpkpw3fWnqM35fyE=",
"dev": true,
- "requires": {
- "async": "1.5.2",
- "fileset": "2.0.3",
- "istanbul-lib-coverage": "1.1.1",
- "istanbul-lib-hook": "1.0.7",
- "istanbul-lib-instrument": "1.7.3",
- "istanbul-lib-report": "1.1.1",
- "istanbul-lib-source-maps": "1.2.1",
- "istanbul-reports": "1.1.1",
- "js-yaml": "3.8.4",
- "mkdirp": "0.5.1",
- "once": "1.4.0"
+ "dependencies": {
+ "async": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz",
+ "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==",
+ "dev": true
+ }
}
},
"istanbul-lib-coverage": {
@@ -2688,36 +2068,32 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz",
"integrity": "sha512-3U2HB9y1ZV9UmFlE12Fx+nPtFqIymzrqCksrXujm3NVbAZIJg/RfYgO1XiIa0mbmxTjWpVEVlkIZJ25xVIAfkQ==",
- "dev": true,
- "requires": {
- "append-transform": "0.4.0"
- }
+ "dev": true
},
"istanbul-lib-instrument": {
- "version": "1.7.3",
- "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.3.tgz",
- "integrity": "sha1-klsjkWPqvdaMxASPUsL6T4mez6c=",
- "dev": true,
- "requires": {
- "babel-generator": "6.25.0",
- "babel-template": "6.25.0",
- "babel-traverse": "6.25.0",
- "babel-types": "6.25.0",
- "babylon": "6.17.4",
- "istanbul-lib-coverage": "1.1.1",
- "semver": "5.3.0"
- }
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.5.tgz",
+ "integrity": "sha1-rbWW+PDLi5XnOSBjUaOKWGryGx4=",
+ "dev": true
},
"istanbul-lib-report": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz",
"integrity": "sha512-tvF+YmCmH4thnez6JFX06ujIA19WPa9YUiwjc1uALF2cv5dmE3It8b5I8Ob7FHJ70H9Y5yF+TDkVa/mcADuw1Q==",
"dev": true,
- "requires": {
- "istanbul-lib-coverage": "1.1.1",
- "mkdirp": "0.5.1",
- "path-parse": "1.0.5",
- "supports-color": "2.0.0"
+ "dependencies": {
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "dev": true
+ }
}
},
"istanbul-lib-source-maps": {
@@ -2725,18 +2101,11 @@
"resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz",
"integrity": "sha512-mukVvSXCn9JQvdJl8wP/iPhqig0MRtuWuD4ZNKo6vB2Ik//AmhAKe3QnPN02dmkRe3lTudFk3rzoHhwU4hb94w==",
"dev": true,
- "requires": {
- "debug": "2.6.8",
- "istanbul-lib-coverage": "1.1.1",
- "mkdirp": "0.5.1",
- "rimraf": "2.6.1",
- "source-map": "0.5.6"
- },
"dependencies": {
"source-map": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
- "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
}
}
@@ -2745,10 +2114,12 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.1.tgz",
"integrity": "sha512-P8G873A0kW24XRlxHVGhMJBhQ8gWAec+dae7ZxOBzxT4w+a9ATSPvRVK3LB1RAJ9S8bg2tOyWHAGW40Zd2dKfw==",
- "dev": true,
- "requires": {
- "handlebars": "4.0.10"
- }
+ "dev": true
+ },
+ "isurl": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
+ "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w=="
},
"iterall": {
"version": "1.1.1",
@@ -2766,37 +2137,13 @@
"resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-18.1.0.tgz",
"integrity": "sha1-Xq027K1CCBfCybqiqnV09jJXs9Y=",
"dev": true,
- "requires": {
- "ansi-escapes": "1.4.0",
- "callsites": "2.0.0",
- "chalk": "1.1.3",
- "graceful-fs": "4.1.11",
- "is-ci": "1.0.10",
- "istanbul-api": "1.1.10",
- "istanbul-lib-coverage": "1.1.1",
- "istanbul-lib-instrument": "1.7.3",
- "jest-changed-files": "17.0.2",
- "jest-config": "18.1.0",
- "jest-environment-jsdom": "18.1.0",
- "jest-file-exists": "17.0.0",
- "jest-haste-map": "18.1.0",
- "jest-jasmine2": "18.1.0",
- "jest-mock": "18.0.0",
- "jest-resolve": "18.1.0",
- "jest-resolve-dependencies": "18.1.0",
- "jest-runtime": "18.1.0",
- "jest-snapshot": "18.1.0",
- "jest-util": "18.1.0",
- "json-stable-stringify": "1.0.1",
- "node-notifier": "4.6.1",
- "sane": "1.4.1",
- "strip-ansi": "3.0.1",
- "throat": "3.2.0",
- "which": "1.2.14",
- "worker-farm": "1.4.1",
- "yargs": "6.6.0"
- },
"dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
"callsites": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
@@ -2809,37 +2156,29 @@
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
"dev": true
},
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
"cliui": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
- "dev": true,
- "requires": {
- "string-width": "1.0.2",
- "strip-ansi": "3.0.1",
- "wrap-ansi": "2.1.0"
- }
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
},
"yargs": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz",
"integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=",
- "dev": true,
- "requires": {
- "camelcase": "3.0.0",
- "cliui": "3.2.0",
- "decamelize": "1.2.0",
- "get-caller-file": "1.0.2",
- "os-locale": "1.4.0",
- "read-pkg-up": "1.0.1",
- "require-directory": "2.1.1",
- "require-main-filename": "1.0.1",
- "set-blocking": "2.0.0",
- "string-width": "1.0.2",
- "which-module": "1.0.0",
- "y18n": "3.2.1",
- "yargs-parser": "4.2.1"
- }
+ "dev": true
}
}
},
@@ -2848,15 +2187,25 @@
"resolved": "https://registry.npmjs.org/jest-config/-/jest-config-18.1.0.tgz",
"integrity": "sha1-YRF0Cm1Iqrhv9anmqwuYvZk7b/Q=",
"dev": true,
- "requires": {
- "chalk": "1.1.3",
- "jest-environment-jsdom": "18.1.0",
- "jest-environment-node": "18.1.0",
- "jest-jasmine2": "18.1.0",
- "jest-mock": "18.0.0",
- "jest-resolve": "18.1.0",
- "jest-util": "18.1.0",
- "json-stable-stringify": "1.0.1"
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
}
},
"jest-diff": {
@@ -2864,33 +2213,38 @@
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-18.1.0.tgz",
"integrity": "sha1-T/eedN2YjBORlbNl3GXYf2BvSAM=",
"dev": true,
- "requires": {
- "chalk": "1.1.3",
- "diff": "3.3.0",
- "jest-matcher-utils": "18.1.0",
- "pretty-format": "18.1.0"
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
}
},
"jest-environment-jsdom": {
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-18.1.0.tgz",
"integrity": "sha1-GLQvDE6iuunzbKs2ObHo+MOE4k4=",
- "dev": true,
- "requires": {
- "jest-mock": "18.0.0",
- "jest-util": "18.1.0",
- "jsdom": "9.12.0"
- }
+ "dev": true
},
"jest-environment-node": {
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-18.1.0.tgz",
"integrity": "sha1-TWeXVyyN2pms9frmlutilFVHx3k=",
- "dev": true,
- "requires": {
- "jest-mock": "18.0.0",
- "jest-util": "18.1.0"
- }
+ "dev": true
},
"jest-file-exists": {
"version": "17.0.0",
@@ -2902,49 +2256,45 @@
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-18.1.0.tgz",
"integrity": "sha1-BoOcdLdwpAwaEGlohR340oHAg3U=",
- "dev": true,
- "requires": {
- "fb-watchman": "1.9.2",
- "graceful-fs": "4.1.11",
- "micromatch": "2.3.11",
- "sane": "1.4.1",
- "worker-farm": "1.4.1"
- }
+ "dev": true
},
"jest-jasmine2": {
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-18.1.0.tgz",
"integrity": "sha1-CU4QTCwYlwh2bHcmO7Kuy1hgqAs=",
- "dev": true,
- "requires": {
- "graceful-fs": "4.1.11",
- "jest-matcher-utils": "18.1.0",
- "jest-matchers": "18.1.0",
- "jest-snapshot": "18.1.0",
- "jest-util": "18.1.0"
- }
+ "dev": true
},
"jest-matcher-utils": {
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-18.1.0.tgz",
"integrity": "sha1-GsRlGVXuKmDO8ef8yYzf13PA+TI=",
"dev": true,
- "requires": {
- "chalk": "1.1.3",
- "pretty-format": "18.1.0"
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
}
},
"jest-matchers": {
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/jest-matchers/-/jest-matchers-18.1.0.tgz",
"integrity": "sha1-A0FIS/h6H9C6wKTSyJnit3o/Hq0=",
- "dev": true,
- "requires": {
- "jest-diff": "18.1.0",
- "jest-matcher-utils": "18.1.0",
- "jest-util": "18.1.0",
- "pretty-format": "18.1.0"
- }
+ "dev": true
},
"jest-mock": {
"version": "18.0.0",
@@ -2956,84 +2306,55 @@
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-18.1.0.tgz",
"integrity": "sha1-aACsy1NmWMkGzV4p3kErGrmsJJs=",
- "dev": true,
- "requires": {
- "browser-resolve": "1.11.2",
- "jest-file-exists": "17.0.0",
- "jest-haste-map": "18.1.0",
- "resolve": "1.3.3"
- }
+ "dev": true
},
"jest-resolve-dependencies": {
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-18.1.0.tgz",
"integrity": "sha1-gTT7XK9Zye2EL+AVKrAcUnEfG7s=",
- "dev": true,
- "requires": {
- "jest-file-exists": "17.0.0",
- "jest-resolve": "18.1.0"
- }
+ "dev": true
},
"jest-runtime": {
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-18.1.0.tgz",
"integrity": "sha1-Or/WhxdbIfw7haK4BkOZ6ZeFmSI=",
"dev": true,
- "requires": {
- "babel-core": "6.25.0",
- "babel-jest": "18.0.0",
- "babel-plugin-istanbul": "3.1.2",
- "chalk": "1.1.3",
- "graceful-fs": "4.1.11",
- "jest-config": "18.1.0",
- "jest-file-exists": "17.0.0",
- "jest-haste-map": "18.1.0",
- "jest-mock": "18.0.0",
- "jest-resolve": "18.1.0",
- "jest-snapshot": "18.1.0",
- "jest-util": "18.1.0",
- "json-stable-stringify": "1.0.1",
- "micromatch": "2.3.11",
- "yargs": "6.6.0"
- },
"dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
"camelcase": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
"dev": true
},
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
"cliui": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
- "dev": true,
- "requires": {
- "string-width": "1.0.2",
- "strip-ansi": "3.0.1",
- "wrap-ansi": "2.1.0"
- }
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
},
"yargs": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz",
"integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=",
- "dev": true,
- "requires": {
- "camelcase": "3.0.0",
- "cliui": "3.2.0",
- "decamelize": "1.2.0",
- "get-caller-file": "1.0.2",
- "os-locale": "1.4.0",
- "read-pkg-up": "1.0.1",
- "require-directory": "2.1.1",
- "require-main-filename": "1.0.1",
- "set-blocking": "2.0.0",
- "string-width": "1.0.2",
- "which-module": "1.0.0",
- "y18n": "3.2.1",
- "yargs-parser": "4.2.1"
- }
+ "dev": true
}
}
},
@@ -3041,28 +2362,32 @@
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-18.1.0.tgz",
"integrity": "sha1-VbltLuY5ybznb4fyo/1Atxx6WRY=",
- "dev": true,
- "requires": {
- "jest-diff": "18.1.0",
- "jest-file-exists": "17.0.0",
- "jest-matcher-utils": "18.1.0",
- "jest-util": "18.1.0",
- "natural-compare": "1.4.0",
- "pretty-format": "18.1.0"
- }
+ "dev": true
},
"jest-util": {
"version": "18.1.0",
"resolved": "https://registry.npmjs.org/jest-util/-/jest-util-18.1.0.tgz",
"integrity": "sha1-OpnDIRSrF/hL4JQ4JScAbm1L/Go=",
"dev": true,
- "requires": {
- "chalk": "1.1.3",
- "diff": "3.3.0",
- "graceful-fs": "4.1.11",
- "jest-file-exists": "17.0.0",
- "jest-mock": "18.0.0",
- "mkdirp": "0.5.1"
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
}
},
"jmespath": {
@@ -3071,18 +2396,14 @@
"integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc="
},
"js-tokens": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz",
- "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc="
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
},
"js-yaml": {
- "version": "3.8.4",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz",
- "integrity": "sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=",
- "requires": {
- "argparse": "1.0.9",
- "esprima": "3.1.3"
- }
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz",
+ "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww=="
},
"jsbn": {
"version": "0.1.1",
@@ -3096,27 +2417,6 @@
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-9.12.0.tgz",
"integrity": "sha1-6MVG//ywbADUgzyoRBD+1/igl9Q=",
"dev": true,
- "requires": {
- "abab": "1.0.3",
- "acorn": "4.0.13",
- "acorn-globals": "3.1.0",
- "array-equal": "1.0.0",
- "content-type-parser": "1.0.1",
- "cssom": "0.3.2",
- "cssstyle": "0.2.37",
- "escodegen": "1.8.1",
- "html-encoding-sniffer": "1.0.1",
- "nwmatcher": "1.4.1",
- "parse5": "1.5.1",
- "request": "2.79.0",
- "sax": "1.2.1",
- "symbol-tree": "3.2.2",
- "tough-cookie": "2.3.2",
- "webidl-conversions": "4.0.1",
- "whatwg-encoding": "1.0.1",
- "whatwg-url": "4.8.0",
- "xml-name-validator": "2.0.1"
- },
"dependencies": {
"acorn": {
"version": "4.0.13",
@@ -3136,23 +2436,11 @@
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/json-refs/-/json-refs-2.1.7.tgz",
"integrity": "sha1-uesB/in16j6Sh48VrqEK04taz4k=",
- "requires": {
- "commander": "2.9.0",
- "graphlib": "2.1.1",
- "js-yaml": "3.8.4",
- "native-promise-only": "0.8.1",
- "path-loader": "1.0.2",
- "slash": "1.0.0",
- "uri-js": "3.0.2"
- },
"dependencies": {
"commander": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
- "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
- "requires": {
- "graceful-readlink": "1.0.1"
- }
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
+ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ=="
}
}
},
@@ -3166,10 +2454,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
"integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
- "dev": true,
- "requires": {
- "jsonify": "0.0.0"
- }
+ "dev": true
},
"json-stringify-safe": {
"version": "5.0.1",
@@ -3191,10 +2476,7 @@
"jsonfile": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
- "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
- "requires": {
- "graceful-fs": "4.1.11"
- }
+ "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug="
},
"jsonify": {
"version": "0.0.0",
@@ -3209,16 +2491,10 @@
"dev": true
},
"jsprim": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz",
- "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=",
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"dev": true,
- "requires": {
- "assert-plus": "1.0.0",
- "extsprintf": "1.0.2",
- "json-schema": "0.2.3",
- "verror": "1.3.6"
- },
"dependencies": {
"assert-plus": {
"version": "1.0.0",
@@ -3239,19 +2515,24 @@
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.3.tgz",
"integrity": "sha1-ipIEA7KxZRwPwSa+kBktkICVfDc=",
"dev": true,
- "requires": {
- "core-js": "2.3.0",
- "es6-promise": "3.0.2",
- "lie": "3.1.1",
- "pako": "1.0.5",
- "readable-stream": "2.2.11"
- },
"dependencies": {
"core-js": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz",
"integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=",
"dev": true
+ },
+ "readable-stream": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
}
}
},
@@ -3264,18 +2545,12 @@
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "1.1.5"
- }
+ "dev": true
},
"klaw": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
- "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
- "requires": {
- "graceful-fs": "4.1.11"
- }
+ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk="
},
"lazy-cache": {
"version": "1.0.4",
@@ -3287,19 +2562,13 @@
"lazystream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
- "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
- "requires": {
- "readable-stream": "2.2.11"
- }
+ "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ="
},
"lcid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
"integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
- "dev": true,
- "requires": {
- "invert-kv": "1.0.0"
- }
+ "dev": true
},
"lcov-parse": {
"version": "0.0.10",
@@ -3311,54 +2580,31 @@
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
"integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
- "dev": true,
- "requires": {
- "prelude-ls": "1.1.2",
- "type-check": "0.3.2"
- }
+ "dev": true
},
"lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
- "dev": true,
- "requires": {
- "immediate": "3.0.6"
- }
+ "dev": true
},
"list-item": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz",
"integrity": "sha1-DGXQDih8tmPMs8s4Sad+iewmilY=",
- "dev": true,
- "requires": {
- "expand-range": "1.8.2",
- "extend-shallow": "2.0.1",
- "is-number": "2.1.0",
- "repeat-string": "1.6.1"
- }
+ "dev": true
},
"load-json-file": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"dev": true,
- "requires": {
- "graceful-fs": "4.1.11",
- "parse-json": "2.2.0",
- "pify": "2.3.0",
- "pinkie-promise": "2.0.1",
- "strip-bom": "2.0.0"
- },
"dependencies": {
"strip-bom": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
- "dev": true,
- "requires": {
- "is-utf8": "0.2.1"
- }
+ "dev": true
}
}
},
@@ -3367,10 +2613,6 @@
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
"dev": true,
- "requires": {
- "p-locate": "2.0.0",
- "path-exists": "3.0.0"
- },
"dependencies": {
"path-exists": {
"version": "3.0.0",
@@ -3406,25 +2648,13 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
"integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=",
- "dev": true,
- "requires": {
- "lodash._basecopy": "3.0.1",
- "lodash.keys": "3.1.2"
- }
+ "dev": true
},
"lodash._baseclone": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz",
"integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=",
- "dev": true,
- "requires": {
- "lodash._arraycopy": "3.0.0",
- "lodash._arrayeach": "3.0.0",
- "lodash._baseassign": "3.2.0",
- "lodash._basefor": "3.0.3",
- "lodash.isarray": "3.0.4",
- "lodash.keys": "3.1.2"
- }
+ "dev": true
},
"lodash._basecopy": {
"version": "3.0.1",
@@ -3472,11 +2702,7 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-3.0.2.tgz",
"integrity": "sha1-oKHkDYKl6on/WxR7hETtY9koJ9s=",
- "dev": true,
- "requires": {
- "lodash._baseclone": "3.3.0",
- "lodash._bindcallback": "3.0.1"
- }
+ "dev": true
},
"lodash.cond": {
"version": "4.5.2",
@@ -3488,12 +2714,7 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz",
"integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=",
- "dev": true,
- "requires": {
- "lodash._baseassign": "3.2.0",
- "lodash._basecreate": "3.0.3",
- "lodash._isiterateecall": "3.0.9"
- }
+ "dev": true
},
"lodash.difference": {
"version": "4.5.0",
@@ -3534,12 +2755,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
"integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
- "dev": true,
- "requires": {
- "lodash._getnative": "3.9.1",
- "lodash.isarguments": "3.1.0",
- "lodash.isarray": "3.0.4"
- }
+ "dev": true
},
"lodash.pad": {
"version": "4.5.1",
@@ -3556,6 +2772,12 @@
"resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz",
"integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs="
},
+ "lodash.toarray": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
+ "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=",
+ "dev": true
+ },
"lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@@ -3582,10 +2804,7 @@
"loose-envify": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
- "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
- "requires": {
- "js-tokens": "3.0.1"
- }
+ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg="
},
"lowercase-keys": {
"version": "1.0.0",
@@ -3600,19 +2819,13 @@
"make-dir": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz",
- "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=",
- "requires": {
- "pify": "2.3.0"
- }
+ "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg="
},
"makeerror": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz",
"integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=",
- "dev": true,
- "requires": {
- "tmpl": "1.0.4"
- }
+ "dev": true
},
"markdown-link": {
"version": "0.1.1",
@@ -3625,25 +2838,24 @@
"resolved": "https://registry.npmjs.org/markdown-magic/-/markdown-magic-0.1.17.tgz",
"integrity": "sha1-lj/jsNvoIF5ycJRJpErS9NsR/24=",
"dev": true,
- "requires": {
- "commander": "2.8.1",
- "deepmerge": "1.5.0",
- "find-up": "2.1.0",
- "fs-extra": "0.26.7",
- "globby": "6.1.0",
- "is-local-path": "0.1.6",
- "markdown-toc": "1.1.0",
- "sync-request": "3.0.1"
- },
"dependencies": {
+ "commander": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
+ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
+ "dev": true
+ },
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
- "dev": true,
- "requires": {
- "locate-path": "2.0.0"
- }
+ "dev": true
+ },
+ "fs-extra": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz",
+ "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=",
+ "dev": true
}
}
},
@@ -3652,29 +2864,12 @@
"resolved": "https://registry.npmjs.org/markdown-toc/-/markdown-toc-1.1.0.tgz",
"integrity": "sha1-GORyN9iVSelEcSHmniyoU8otdSo=",
"dev": true,
- "requires": {
- "concat-stream": "1.6.0",
- "diacritics-map": "0.1.0",
- "gray-matter": "2.1.1",
- "lazy-cache": "2.0.2",
- "list-item": "1.1.1",
- "markdown-link": "0.1.1",
- "minimist": "1.2.0",
- "mixin-deep": "1.2.0",
- "object.pick": "1.2.0",
- "remarkable": "1.7.1",
- "repeat-string": "1.6.1",
- "strip-color": "0.1.0"
- },
"dependencies": {
"lazy-cache": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz",
"integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=",
- "dev": true,
- "requires": {
- "set-getter": "0.1.0"
- }
+ "dev": true
}
}
},
@@ -3689,12 +2884,25 @@
"resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-1.7.0.tgz",
"integrity": "sha1-yMRgiBx3LHYEtkNnAH7l938SWQQ=",
"dev": true,
- "requires": {
- "cardinal": "1.0.0",
- "chalk": "1.1.3",
- "cli-table": "0.3.1",
- "lodash.assign": "4.2.0",
- "node-emoji": "1.5.1"
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
}
},
"merge": {
@@ -3718,22 +2926,7 @@
"version": "2.3.11",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
"integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
- "dev": true,
- "requires": {
- "arr-diff": "2.0.0",
- "array-unique": "0.2.1",
- "braces": "1.8.5",
- "expand-brackets": "0.1.5",
- "extglob": "0.3.2",
- "filename-regex": "2.0.1",
- "is-extglob": "1.0.0",
- "is-glob": "2.0.1",
- "kind-of": "3.2.2",
- "normalize-path": "2.1.1",
- "object.omit": "2.0.1",
- "parse-glob": "3.0.4",
- "regex-cache": "0.4.3"
- }
+ "dev": true
},
"mime": {
"version": "1.3.6",
@@ -3741,25 +2934,19 @@
"integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA="
},
"mime-db": {
- "version": "1.27.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz",
- "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE="
+ "version": "1.29.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz",
+ "integrity": "sha1-SNJtI1WJZRcErFkWygYAGRQmaHg="
},
"mime-types": {
- "version": "2.1.15",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz",
- "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=",
- "requires": {
- "mime-db": "1.27.0"
- }
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz",
+ "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
- "requires": {
- "brace-expansion": "1.1.7"
- }
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA=="
},
"minimist": {
"version": "1.2.0",
@@ -3770,19 +2957,12 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.2.0.tgz",
"integrity": "sha1-0CuMb4ttS49ZgtP9AJxJGYUcP+I=",
- "dev": true,
- "requires": {
- "for-in": "1.0.2",
- "is-extendable": "0.1.1"
- }
+ "dev": true
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
- "requires": {
- "minimist": "0.0.8"
- },
"dependencies": {
"minimist": {
"version": "0.0.8",
@@ -3792,29 +2972,40 @@
}
},
"mocha": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.4.2.tgz",
- "integrity": "sha1-0O9NMyEm2/GNDWQMmzgt1IvpdZQ=",
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.0.tgz",
+ "integrity": "sha512-pIU2PJjrPYvYRqVpjXzj76qltO9uBYI7woYAMoxbSefsa+vqAfptjoeevd6bUgwD0mPIO+hv9f7ltvsNreL2PA==",
"dev": true,
- "requires": {
- "browser-stdout": "1.3.0",
- "commander": "2.8.1",
- "debug": "2.6.8",
- "diff": "3.2.0",
- "escape-string-regexp": "1.0.5",
- "glob": "7.1.2",
- "growl": "1.9.2",
- "json3": "3.3.2",
- "lodash.create": "3.1.1",
- "mkdirp": "0.5.1",
- "supports-color": "2.0.0"
- },
"dependencies": {
+ "commander": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
+ "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
+ "dev": true
+ },
"diff": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
"integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=",
"dev": true
+ },
+ "glob": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
+ "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
+ "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=",
+ "dev": true
}
}
},
@@ -3828,10 +3019,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/mock-require/-/mock-require-1.3.0.tgz",
"integrity": "sha1-gmFElS5QR2L45pJKqPY5Rl0deiQ=",
- "dev": true,
- "requires": {
- "caller-id": "0.1.0"
- }
+ "dev": true
},
"module-not-found-error": {
"version": "1.0.1",
@@ -3866,22 +3054,15 @@
"dev": true
},
"node-emoji": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.5.1.tgz",
- "integrity": "sha1-/ZGOQSdpv4xEgFEjgjOECyr/FqE=",
- "dev": true,
- "requires": {
- "string.prototype.codepointat": "0.2.0"
- }
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.8.1.tgz",
+ "integrity": "sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg==",
+ "dev": true
},
"node-fetch": {
- "version": "1.7.1",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.1.tgz",
- "integrity": "sha512-j8XsFGCLw79vWXkZtMSmmLaOk9z5SQ9bV/tkbZVCqvgwzrjAGq66igobLofHtF63NvMTp2WjytpsNTGKa+XRIQ==",
- "requires": {
- "encoding": "0.1.12",
- "is-stream": "1.1.0"
- }
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.2.tgz",
+ "integrity": "sha512-xZZUq2yDhKMIn/UgG5q//IZSNLJIwW2QxS14CNH5spuiXkITM2pUitjdq58yLSaU7m4M0wBNaM2Gh/ggY4YJig=="
},
"node-int64": {
"version": "0.4.0",
@@ -3893,55 +3074,41 @@
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-4.6.1.tgz",
"integrity": "sha1-BW0UJE89zBzq3+aK+c/wxUc6M/M=",
- "dev": true,
- "requires": {
- "cli-usage": "0.1.4",
- "growly": "1.3.0",
- "lodash.clonedeep": "3.0.2",
- "minimist": "1.2.0",
- "semver": "5.3.0",
- "shellwords": "0.1.0",
- "which": "1.2.14"
- }
+ "dev": true
},
"nopt": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
"integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
- "dev": true,
- "requires": {
- "abbrev": "1.0.9"
- }
+ "dev": true
},
"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==",
- "dev": true,
- "requires": {
- "hosted-git-info": "2.5.0",
- "is-builtin-module": "1.0.0",
- "semver": "5.3.0",
- "validate-npm-package-license": "3.0.1"
- }
+ "dev": true
},
"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.2"
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk="
+ },
+ "npm-conf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.2.tgz",
+ "integrity": "sha512-dotwbpwVzfNB/2EF3A2wjK5tEMLggKfuA/8TG6WvBB1Zrv+JsvF7E8ei9B/HGq211st/GwXFbREcNJvJ1eySUQ==",
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+ }
}
},
"npmlog": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz",
- "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=",
- "requires": {
- "ansi": "0.3.1",
- "are-we-there-yet": "1.1.4",
- "gauge": "1.2.7"
- }
+ "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI="
},
"number-is-nan": {
"version": "1.0.1",
@@ -3975,39 +3142,32 @@
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.0.4.tgz",
"integrity": "sha1-scnMBE7xuf5jYG/BQau7MuFHMMw=",
- "dev": true,
- "requires": {
- "define-properties": "1.1.2",
- "function-bind": "1.1.0",
- "object-keys": "1.0.11"
- }
+ "dev": true
},
"object.omit": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
"integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
- "dev": true,
- "requires": {
- "for-own": "0.1.5",
- "is-extendable": "0.1.1"
- }
+ "dev": true
},
"object.pick": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.2.0.tgz",
- "integrity": "sha1-tTkr7peC2m2ft9avr1OXefEjTCs=",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
"dev": true,
- "requires": {
- "isobject": "2.1.0"
+ "dependencies": {
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "requires": {
- "wrappy": "1.0.2"
- }
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E="
},
"onetime": {
"version": "1.1.0",
@@ -4017,21 +3177,20 @@
"opn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz",
- "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==",
- "requires": {
- "is-wsl": "1.1.0"
- }
+ "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg=="
},
"optimist": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
"dev": true,
- "requires": {
- "minimist": "1.2.0",
- "wordwrap": "0.0.3"
- },
"dependencies": {
+ "minimist": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+ "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
+ "dev": true
+ },
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
@@ -4044,15 +3203,7 @@
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
"integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
- "dev": true,
- "requires": {
- "deep-is": "0.1.3",
- "fast-levenshtein": "2.0.6",
- "levn": "0.3.0",
- "prelude-ls": "1.1.2",
- "type-check": "0.3.2",
- "wordwrap": "1.0.0"
- }
+ "dev": true
},
"os-homedir": {
"version": "1.0.2",
@@ -4064,10 +3215,7 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
- "dev": true,
- "requires": {
- "lcid": "1.0.0"
- }
+ "dev": true
},
"os-shim": {
"version": "0.1.3",
@@ -4089,10 +3237,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
- "dev": true,
- "requires": {
- "p-limit": "1.1.0"
- }
+ "dev": true
},
"pako": {
"version": "1.0.5",
@@ -4104,22 +3249,13 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
"integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
- "dev": true,
- "requires": {
- "glob-base": "0.3.0",
- "is-dotfile": "1.0.3",
- "is-extglob": "1.0.0",
- "is-glob": "2.0.1"
- }
+ "dev": true
},
"parse-json": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
- "dev": true,
- "requires": {
- "error-ex": "1.3.1"
- }
+ "dev": true
},
"parse5": {
"version": "1.5.1",
@@ -4131,10 +3267,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
- "dev": true,
- "requires": {
- "pinkie-promise": "2.0.1"
- }
+ "dev": true
},
"path-is-absolute": {
"version": "1.0.1",
@@ -4150,11 +3283,7 @@
"path-loader": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/path-loader/-/path-loader-1.0.2.tgz",
- "integrity": "sha1-zVxz5+OakQEb4UjWv92KhbuTHvk=",
- "requires": {
- "native-promise-only": "0.8.1",
- "superagent": "3.5.2"
- }
+ "integrity": "sha1-zVxz5+OakQEb4UjWv92KhbuTHvk="
},
"path-parse": {
"version": "1.0.5",
@@ -4166,12 +3295,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
"integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
- "dev": true,
- "requires": {
- "graceful-fs": "4.1.11",
- "pify": "2.3.0",
- "pinkie-promise": "2.0.1"
- }
+ "dev": true
},
"pend": {
"version": "1.2.0",
@@ -4191,28 +3315,19 @@
"pinkie-promise": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
- "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
- "requires": {
- "pinkie": "2.0.4"
- }
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o="
},
"pkg-dir": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz",
"integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=",
- "dev": true,
- "requires": {
- "find-up": "1.1.2"
- }
+ "dev": true
},
"pkg-up": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz",
"integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=",
- "dev": true,
- "requires": {
- "find-up": "1.1.2"
- }
+ "dev": true
},
"pluralize": {
"version": "1.2.1",
@@ -4242,8 +3357,13 @@
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-18.1.0.tgz",
"integrity": "sha1-+2Wob3p/kZSWPu6RhlwbzxA54oQ=",
"dev": true,
- "requires": {
- "ansi-styles": "2.2.1"
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ }
}
},
"private": {
@@ -4267,21 +3387,18 @@
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
- "dev": true,
- "requires": {
- "asap": "2.0.5"
- }
+ "dev": true
+ },
+ "proto-list": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+ "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk="
},
"proxyquire": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz",
"integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=",
"dev": true,
- "requires": {
- "fill-keys": "1.0.2",
- "module-not-found-error": "1.0.1",
- "resolve": "1.1.7"
- },
"dependencies": {
"resolve": {
"version": "1.1.7",
@@ -4303,42 +3420,37 @@
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
},
"qs": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
- "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM="
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz",
+ "integrity": "sha512-fjVFjW9yhqMhVGwRExCXLhJKrLlkYSaxNWdyc9rmHlrVZbk35YHH312dFd7191uQeXkI3mKLZTIbSvIeFwFemg=="
},
"querystring": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
},
+ "ramda": {
+ "version": "0.24.1",
+ "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz",
+ "integrity": "sha1-w7d1UZfzW43DUCIoJixMkd22uFc="
+ },
"randomatic": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
"integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
"dev": true,
- "requires": {
- "is-number": "3.0.0",
- "kind-of": "4.0.0"
- },
"dependencies": {
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"dev": true,
- "requires": {
- "kind-of": "3.2.2"
- },
"dependencies": {
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "1.1.5"
- }
+ "dev": true
}
}
},
@@ -4346,10 +3458,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
"integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
- "dev": true,
- "requires": {
- "is-buffer": "1.1.5"
- }
+ "dev": true
}
}
},
@@ -4357,13 +3466,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/raven/-/raven-1.2.1.tgz",
"integrity": "sha1-lJwTTbAooZC3u/j3kKrlQbfAIL0=",
- "requires": {
- "cookie": "0.3.1",
- "json-stringify-safe": "5.0.1",
- "lsmod": "1.0.0",
- "stack-trace": "0.0.9",
- "uuid": "3.0.0"
- },
"dependencies": {
"uuid": {
"version": "3.0.0",
@@ -4375,99 +3477,94 @@
"rc": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz",
- "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=",
- "requires": {
- "deep-extend": "0.4.2",
- "ini": "1.3.4",
- "minimist": "1.2.0",
- "strip-json-comments": "2.0.1"
- }
+ "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU="
},
"read-pkg": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
"integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
- "dev": true,
- "requires": {
- "load-json-file": "1.1.0",
- "normalize-package-data": "2.4.0",
- "path-type": "1.1.0"
- }
+ "dev": true
},
"read-pkg-up": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
- "dev": true,
- "requires": {
- "find-up": "1.1.2",
- "read-pkg": "1.1.0"
- }
+ "dev": true
},
"readable-stream": {
- "version": "2.2.11",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.11.tgz",
- "integrity": "sha512-h+8+r3MKEhkiVrwdKL8aWs1oc1VvBu33ueshOvS26RsZQ3Amhx/oO3TKe4lApSV9ueY6as8EAh7mtuFjdlhg9Q==",
- "requires": {
- "core-util-is": "1.0.2",
- "inherits": "2.0.3",
- "isarray": "1.0.0",
- "process-nextick-args": "1.0.7",
- "safe-buffer": "5.0.1",
- "string_decoder": "1.0.2",
- "util-deprecate": "1.0.2"
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ=="
+ },
+ "readline2": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz",
+ "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=",
+ "dev": true,
+ "dependencies": {
+ "mute-stream": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz",
+ "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=",
+ "dev": true
+ }
}
},
+ "rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
+ "dev": true
+ },
"redeyed": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/redeyed/-/redeyed-1.0.1.tgz",
"integrity": "sha1-6WwZO0DAgWsArshCaY5hGF5VSYo=",
"dev": true,
- "requires": {
- "esprima": "3.1.3"
+ "dependencies": {
+ "esprima": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz",
+ "integrity": "sha1-U88kes2ncxPlUcOqLnM0LT+099k=",
+ "dev": true
+ }
}
},
"redux": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.0.tgz",
- "integrity": "sha512-GHjaOkEQtQnnuLoYPFkRKHIqs1i1tdTlisu/xUHfk2juzCobSy4STxs4Lz5bPkc07Owb6BeGKx/r76c9IVTkOw==",
- "requires": {
- "lodash": "4.17.4",
- "lodash-es": "4.17.4",
- "loose-envify": "1.3.1",
- "symbol-observable": "1.0.4"
- }
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz",
+ "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A=="
},
"regenerator-runtime": {
- "version": "0.10.5",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
- "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz",
+ "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==",
"dev": true
},
"regex-cache": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz",
"integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=",
- "dev": true,
- "requires": {
- "is-equal-shallow": "0.1.3",
- "is-primitive": "2.0.0"
- }
+ "dev": true
},
"remarkable": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.1.tgz",
"integrity": "sha1-qspJchALZqZCpjoQIcpLrBvjv/Y=",
"dev": true,
- "requires": {
- "argparse": "1.0.9",
- "autolinker": "0.15.3"
+ "dependencies": {
+ "argparse": {
+ "version": "0.1.16",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz",
+ "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=",
+ "dev": true
+ }
}
},
"remove-trailing-separator": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz",
- "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE="
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
},
"repeat-element": {
"version": "1.1.2",
@@ -4485,10 +3582,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
"integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
- "dev": true,
- "requires": {
- "is-finite": "1.0.2"
- }
+ "dev": true
},
"replaceall": {
"version": "0.1.6",
@@ -4500,27 +3594,31 @@
"resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz",
"integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=",
"dev": true,
- "requires": {
- "aws-sign2": "0.6.0",
- "aws4": "1.6.0",
- "caseless": "0.11.0",
- "combined-stream": "1.0.5",
- "extend": "3.0.1",
- "forever-agent": "0.6.1",
- "form-data": "2.1.4",
- "har-validator": "2.0.6",
- "hawk": "3.1.3",
- "http-signature": "1.1.1",
- "is-typedarray": "1.0.0",
- "isstream": "0.1.2",
- "json-stringify-safe": "5.0.1",
- "mime-types": "2.1.15",
- "oauth-sign": "0.8.2",
- "qs": "6.4.0",
- "stringstream": "0.0.5",
- "tough-cookie": "2.3.2",
- "tunnel-agent": "0.4.3",
- "uuid": "2.0.3"
+ "dependencies": {
+ "form-data": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
+ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.3.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz",
+ "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=",
+ "dev": true
+ },
+ "tunnel-agent": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
+ "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=",
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
+ "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==",
+ "dev": true
+ }
}
},
"require-directory": {
@@ -4539,20 +3637,13 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
"integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
- "dev": true,
- "requires": {
- "caller-path": "0.1.0",
- "resolve-from": "1.0.1"
- }
+ "dev": true
},
"resolve": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz",
- "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=",
- "dev": true,
- "requires": {
- "path-parse": "1.0.5"
- }
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz",
+ "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==",
+ "dev": true
},
"resolve-from": {
"version": "1.0.1",
@@ -4563,47 +3654,40 @@
"restore-cursor": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
- "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
- "requires": {
- "exit-hook": "1.1.1",
- "onetime": "1.1.0"
- }
+ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE="
},
"right-align": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
"integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
"dev": true,
- "optional": true,
- "requires": {
- "align-text": "0.1.4"
- }
+ "optional": true
},
"rimraf": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
- "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
- "requires": {
- "glob": "7.1.2"
- }
+ "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0="
},
"run-async": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
- "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
- "requires": {
- "is-promise": "2.1.0"
- }
+ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA="
},
"rx": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz",
"integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I="
},
+ "rx-lite": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz",
+ "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=",
+ "dev": true
+ },
"safe-buffer": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz",
- "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c="
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
},
"samsam": {
"version": "1.1.2",
@@ -4615,15 +3699,7 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/sane/-/sane-1.4.1.tgz",
"integrity": "sha1-iPdj10BA9fDCVrYWPbOZvxEKxxU=",
- "dev": true,
- "requires": {
- "exec-sh": "0.2.0",
- "fb-watchman": "1.9.2",
- "minimatch": "3.0.4",
- "minimist": "1.2.0",
- "walker": "1.0.7",
- "watch": "0.10.0"
- }
+ "dev": true
},
"sax": {
"version": "1.2.1",
@@ -4633,15 +3709,12 @@
"seek-bzip": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz",
- "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=",
- "requires": {
- "commander": "2.8.1"
- }
+ "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w="
},
"semver": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
- "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
+ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg=="
},
"semver-regex": {
"version": "1.0.0",
@@ -4658,10 +3731,7 @@
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz",
"integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=",
- "dev": true,
- "requires": {
- "to-object-path": "0.3.0"
- }
+ "dev": true
},
"shelljs": {
"version": "0.6.1",
@@ -4669,22 +3739,21 @@
"integrity": "sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg="
},
"shellwords": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.0.tgz",
- "integrity": "sha1-Zq/Ue2oSky2Qccv9mKUueFzQuhQ=",
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
+ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
"dev": true
},
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+ },
"sinon": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz",
"integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=",
- "dev": true,
- "requires": {
- "formatio": "1.1.1",
- "lolex": "1.3.2",
- "samsam": "1.1.2",
- "util": "0.10.3"
- }
+ "dev": true
},
"sinon-bluebird": {
"version": "3.1.0",
@@ -4693,9 +3762,9 @@
"dev": true
},
"sinon-chai": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.11.0.tgz",
- "integrity": "sha512-3kbzpr2q8N+M4CWkcym349ifwkXorsbw2YyVpEIvB3AKC/ebrLHXj3DySt8epKGA49zJBSgn1OvWHZ+O+aR0dA==",
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.13.0.tgz",
+ "integrity": "sha512-hRNu/TlYEp4Rw5IbzO8ykGoZMSG489PGUx1rvePpHGrtl20cXivRBgtr/EWYxIwL9EOO9+on04nd9k3tW8tVww==",
"dev": true
},
"slash": {
@@ -4709,43 +3778,29 @@
"integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
"dev": true
},
- "slide": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
- "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc="
- },
"sntp": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
"integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
- "dev": true,
- "requires": {
- "hoek": "2.16.3"
- }
+ "dev": true
},
"source-map": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
"integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=",
"dev": true,
- "optional": true,
- "requires": {
- "amdefine": "1.0.1"
- }
+ "optional": true
},
"source-map-support": {
- "version": "0.4.15",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz",
- "integrity": "sha1-AyAt9lwG0r2MfsI2KhkwVv7407E=",
+ "version": "0.4.16",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.16.tgz",
+ "integrity": "sha512-A6vlydY7H/ljr4L2UOhDSajQdZQ6dMD7cLH0pzwcmwLyc9u8PNI4WGtnfDDzX7uzGL6c/T+ORL97Zlh+S4iOrg==",
"dev": true,
- "requires": {
- "source-map": "0.5.6"
- },
"dependencies": {
"source-map": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
- "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
}
}
@@ -4753,20 +3808,13 @@
"spawn-sync": {
"version": "1.0.15",
"resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz",
- "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=",
- "requires": {
- "concat-stream": "1.6.0",
- "os-shim": "0.1.3"
- }
+ "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY="
},
"spdx-correct": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
"integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=",
- "dev": true,
- "requires": {
- "spdx-license-ids": "1.2.2"
- }
+ "dev": true
},
"spdx-expression-parse": {
"version": "1.0.4",
@@ -4790,16 +3838,6 @@
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
"integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
"dev": true,
- "requires": {
- "asn1": "0.2.3",
- "assert-plus": "1.0.0",
- "bcrypt-pbkdf": "1.0.1",
- "dashdash": "1.14.1",
- "ecc-jsbn": "0.1.1",
- "getpass": "0.1.7",
- "jsbn": "0.1.1",
- "tweetnacl": "0.14.5"
- },
"dependencies": {
"assert-plus": {
"version": "1.0.0",
@@ -4815,28 +3853,14 @@
"integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU="
},
"string_decoder": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz",
- "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=",
- "requires": {
- "safe-buffer": "5.0.1"
- }
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ=="
},
"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.1.0",
- "is-fullwidth-code-point": "1.0.0",
- "strip-ansi": "3.0.1"
- }
- },
- "string.prototype.codepointat": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.0.tgz",
- "integrity": "sha1-aybpvTr8qnvjtCabUm3huCAArHg=",
- "dev": true
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M="
},
"stringstream": {
"version": "0.0.5",
@@ -4847,10 +3871,7 @@
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "requires": {
- "ansi-regex": "2.1.1"
- }
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="
},
"strip-bom": {
"version": "3.0.0",
@@ -4867,10 +3888,7 @@
"strip-dirs": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.0.0.tgz",
- "integrity": "sha1-YQzbKSggDaAAT0HcuQ/JXNkZoLY=",
- "requires": {
- "is-natural-number": "4.0.1"
- }
+ "integrity": "sha1-YQzbKSggDaAAT0HcuQ/JXNkZoLY="
},
"strip-json-comments": {
"version": "2.0.1",
@@ -4880,32 +3898,17 @@
"strip-outer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.0.tgz",
- "integrity": "sha1-qsC6YNLpDF1PJ1/Yhp/ZotMQ/7g=",
- "requires": {
- "escape-string-regexp": "1.0.5"
- }
+ "integrity": "sha1-qsC6YNLpDF1PJ1/Yhp/ZotMQ/7g="
},
"superagent": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.5.2.tgz",
- "integrity": "sha1-M2GjlxVnUEw1EGOr6q4PqiPb8/g=",
- "requires": {
- "component-emitter": "1.2.1",
- "cookiejar": "2.1.1",
- "debug": "2.6.8",
- "extend": "3.0.1",
- "form-data": "2.1.4",
- "formidable": "1.1.1",
- "methods": "1.1.2",
- "mime": "1.3.6",
- "qs": "6.4.0",
- "readable-stream": "2.2.11"
- }
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.6.0.tgz",
+ "integrity": "sha512-oWsu4mboo8sVxagp4bNwZIR1rUmypeAJDmNIwT9mF4k06hSu6P92aOjEWLaIj7vsX3fOUp+cRH/04tao+q5Q7A=="
},
"supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz",
+ "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA=="
},
"symbol-observable": {
"version": "1.0.4",
@@ -4922,65 +3925,75 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/sync-request/-/sync-request-3.0.1.tgz",
"integrity": "sha1-yqEjWq+Im6UBB2oYNMQ2gwqC+3M=",
- "dev": true,
- "requires": {
- "concat-stream": "1.6.0",
- "http-response-object": "1.1.0",
- "then-request": "2.2.0"
- }
+ "dev": true
},
"table": {
"version": "3.8.3",
"resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz",
"integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=",
"dev": true,
- "requires": {
- "ajv": "4.11.8",
- "ajv-keywords": "1.5.1",
- "chalk": "1.1.3",
- "lodash": "4.17.4",
- "slice-ansi": "0.0.4",
- "string-width": "1.0.2"
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "dependencies": {
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true
+ }
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
}
},
"tabtab": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/tabtab/-/tabtab-2.2.2.tgz",
- "integrity": "sha1-egR/FDsBC0y9MfhX6ClhUSy/ThQ=",
- "requires": {
- "debug": "2.6.8",
- "inquirer": "1.2.3",
- "lodash.difference": "4.5.0",
- "lodash.uniq": "4.5.0",
- "minimist": "1.2.0",
- "mkdirp": "0.5.1",
- "npmlog": "2.0.4",
- "object-assign": "4.1.1"
- }
+ "integrity": "sha1-egR/FDsBC0y9MfhX6ClhUSy/ThQ="
},
"tar-stream": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.4.tgz",
- "integrity": "sha1-NlSc8E7RrumyowwBQyUiONr5QBY=",
- "requires": {
- "bl": "1.2.1",
- "end-of-stream": "1.4.0",
- "readable-stream": "2.2.11",
- "xtend": "4.0.1"
- }
+ "integrity": "sha1-NlSc8E7RrumyowwBQyUiONr5QBY="
},
"test-exclude": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-3.3.0.tgz",
"integrity": "sha1-ehfKEjmYjJg2ewYhRW27fUvDiXc=",
- "dev": true,
- "requires": {
- "arrify": "1.0.1",
- "micromatch": "2.3.11",
- "object-assign": "4.1.1",
- "read-pkg-up": "1.0.1",
- "require-main-filename": "1.0.1"
- }
+ "dev": true
},
"text-table": {
"version": "0.2.0",
@@ -4992,15 +4005,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/then-request/-/then-request-2.2.0.tgz",
"integrity": "sha1-ZnizL6DKIY/laZgbvYhxtZQGDYE=",
- "dev": true,
- "requires": {
- "caseless": "0.11.0",
- "concat-stream": "1.6.0",
- "http-basic": "2.5.1",
- "http-response-object": "1.1.0",
- "promise": "7.3.1",
- "qs": "6.4.0"
- }
+ "dev": true
},
"throat": {
"version": "3.2.0",
@@ -5021,10 +4026,7 @@
"tmp": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz",
- "integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA=",
- "requires": {
- "os-tmpdir": "1.0.2"
- }
+ "integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA="
},
"tmpl": {
"version": "1.0.4",
@@ -5042,10 +4044,7 @@
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
"integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
- "dev": true,
- "requires": {
- "kind-of": "3.2.2"
- }
+ "dev": true
},
"toml": {
"version": "2.3.2",
@@ -5058,8 +4057,13 @@
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz",
"integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=",
"dev": true,
- "requires": {
- "punycode": "1.3.2"
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ }
}
},
"tr46": {
@@ -5071,10 +4075,7 @@
"trim-repeated": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
- "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=",
- "requires": {
- "escape-string-regexp": "1.0.5"
- }
+ "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE="
},
"trim-right": {
"version": "1.0.1",
@@ -5089,9 +4090,9 @@
"dev": true
},
"tunnel-agent": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
- "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us="
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0="
},
"tweetnacl": {
"version": "0.14.5",
@@ -5104,10 +4105,7 @@
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
"integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
- "dev": true,
- "requires": {
- "prelude-ls": "1.1.2"
- }
+ "dev": true
},
"type-detect": {
"version": "1.0.0",
@@ -5126,16 +4124,11 @@
"integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
"dev": true,
"optional": true,
- "requires": {
- "source-map": "0.5.6",
- "uglify-to-browserify": "1.0.2",
- "yargs": "3.10.0"
- },
"dependencies": {
"source-map": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
- "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true,
"optional": true
}
@@ -5149,13 +4142,9 @@
"optional": true
},
"unbzip2-stream": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.4.tgz",
- "integrity": "sha1-jITITVtMwo/B+fV3IDu9PLhgoWo=",
- "requires": {
- "buffer": "3.6.0",
- "through": "2.3.8"
- },
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz",
+ "integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==",
"dependencies": {
"base64-js": {
"version": "0.0.8",
@@ -5165,15 +4154,22 @@
"buffer": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz",
- "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=",
- "requires": {
- "base64-js": "0.0.8",
- "ieee754": "1.1.8",
- "isarray": "1.0.0"
- }
+ "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs="
}
}
},
+ "underscore": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz",
+ "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=",
+ "dev": true
+ },
+ "underscore.string": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz",
+ "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=",
+ "dev": true
+ },
"unzip-response": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
@@ -5183,9 +4179,6 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz",
"integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=",
- "requires": {
- "punycode": "2.1.0"
- },
"dependencies": {
"punycode": {
"version": "2.1.0",
@@ -5195,38 +4188,38 @@
}
},
"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"
- }
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE="
},
"url-parse-lax": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
- "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
- "requires": {
- "prepend-http": "1.0.4"
- }
+ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM="
+ },
+ "url-to-options": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
+ "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k="
},
"user-home": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
"integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=",
- "dev": true,
- "requires": {
- "os-homedir": "1.0.2"
- }
+ "dev": true
},
"util": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
"dev": true,
- "requires": {
- "inherits": "2.0.3"
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+ "dev": true
+ }
}
},
"util-deprecate": {
@@ -5243,19 +4236,20 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
"integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
- "dev": true,
- "requires": {
- "spdx-correct": "1.0.2",
- "spdx-expression-parse": "1.0.4"
- }
+ "dev": true
},
"verror": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz",
- "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=",
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"dev": true,
- "requires": {
- "extsprintf": "1.0.2"
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true
+ }
}
},
"walkdir": {
@@ -5267,10 +4261,7 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",
"integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=",
- "dev": true,
- "requires": {
- "makeerror": "1.0.11"
- }
+ "dev": true
},
"watch": {
"version": "0.10.0",
@@ -5279,9 +4270,9 @@
"dev": true
},
"webidl-conversions": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.1.tgz",
- "integrity": "sha1-gBWherg+fhsxFjhIas6B2mziBqA=",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
"dev": true
},
"whatwg-encoding": {
@@ -5289,8 +4280,13 @@
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz",
"integrity": "sha1-PGxFGhmO567FWx7GHQkgxngBpfQ=",
"dev": true,
- "requires": {
- "iconv-lite": "0.4.17"
+ "dependencies": {
+ "iconv-lite": {
+ "version": "0.4.13",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
+ "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=",
+ "dev": true
+ }
}
},
"whatwg-fetch": {
@@ -5303,10 +4299,6 @@
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-4.8.0.tgz",
"integrity": "sha1-0pgaqRSMHgCkHFphMRZqtGg7vMA=",
"dev": true,
- "requires": {
- "tr46": "0.0.3",
- "webidl-conversions": "3.0.1"
- },
"dependencies": {
"webidl-conversions": {
"version": "3.0.1",
@@ -5317,13 +4309,10 @@
}
},
"which": {
- "version": "1.2.14",
- "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
- "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=",
- "dev": true,
- "requires": {
- "isexe": "2.0.0"
- }
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
+ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
+ "dev": true
},
"which-module": {
"version": "1.0.0",
@@ -5345,24 +4334,16 @@
"dev": true
},
"worker-farm": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.4.1.tgz",
- "integrity": "sha512-tgFAtgOYLPutkAyzgpS6VJFL5HY+0ui1Tvua+fITgz8ByaJTMFGtazR6xxQfwfiAcbwE+2fLG/K49wc2TfwCNw==",
- "dev": true,
- "requires": {
- "errno": "0.1.4",
- "xtend": "4.0.1"
- }
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.5.0.tgz",
+ "integrity": "sha512-DHRiUggxtbruaTwnLDm2/BRDKZIoOYvrgYUj5Bam4fU6Gtvc0FaEyoswFPBjMXAweGW2H4BDNIpy//1yXXuaqQ==",
+ "dev": true
},
"wrap-ansi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
- "dev": true,
- "requires": {
- "string-width": "1.0.2",
- "strip-ansi": "3.0.1"
- }
+ "dev": true
},
"wrappy": {
"version": "1.0.2",
@@ -5373,20 +4354,12 @@
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
"integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
- "dev": true,
- "requires": {
- "mkdirp": "0.5.1"
- }
+ "dev": true
},
"write-file-atomic": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.1.0.tgz",
- "integrity": "sha1-F2n0tVHu3OQZ8FBd6uLiZ2NULTc=",
- "requires": {
- "graceful-fs": "4.1.11",
- "imurmurhash": "0.1.4",
- "slide": "1.1.6"
- }
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz",
+ "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA=="
},
"xml-name-validator": {
"version": "2.0.1",
@@ -5397,19 +4370,12 @@
"xml2js": {
"version": "0.4.17",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz",
- "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=",
- "requires": {
- "sax": "1.2.1",
- "xmlbuilder": "4.2.1"
- }
+ "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg="
},
"xmlbuilder": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz",
- "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=",
- "requires": {
- "lodash": "4.17.4"
- }
+ "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU="
},
"xtend": {
"version": "4.0.1",
@@ -5432,22 +4398,13 @@
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
"integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
"dev": true,
- "optional": true,
- "requires": {
- "camelcase": "1.2.1",
- "cliui": "2.1.0",
- "decamelize": "1.2.0",
- "window-size": "0.1.0"
- }
+ "optional": true
},
"yargs-parser": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
"integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
"dev": true,
- "requires": {
- "camelcase": "3.0.0"
- },
"dependencies": {
"camelcase": {
"version": "3.0.0",
@@ -5460,22 +4417,17 @@
"yauzl": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz",
- "integrity": "sha1-eUUK/yKyqcWkHvVOAtuQfM+/nuI=",
- "requires": {
- "buffer-crc32": "0.2.13",
- "fd-slicer": "1.0.1"
- }
+ "integrity": "sha1-eUUK/yKyqcWkHvVOAtuQfM+/nuI="
+ },
+ "zen-observable-ts": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.4.0.tgz",
+ "integrity": "sha1-p0vJ/ll0eUild71RPUOOcPz65+I="
},
"zip-stream": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.1.1.tgz",
- "integrity": "sha1-Uha0i7tNJlH2TVxubwnrSnOZ1Vc=",
- "requires": {
- "archiver-utils": "1.3.0",
- "compress-commons": "1.2.0",
- "lodash": "4.17.4",
- "readable-stream": "2.2.11"
- }
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz",
+ "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ="
}
}
}
diff --git a/package.json b/package.json
index 1885b888a..88710be34 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "serverless",
- "version": "1.19.0",
+ "version": "1.20.2",
"engines": {
"node": ">=4.0"
},
@@ -51,7 +51,8 @@
"sls": "./bin/serverless"
},
"scripts": {
- "test": "istanbul cover -x '**/*.test.js' node_modules/mocha/bin/_mocha '!(node_modules)/**/*.test.js' -- --require=sinon-bluebird -R spec --recursive",
+ "test-bare": "env FORCE_COLOR=0 node_modules/mocha/bin/_mocha \"!(node_modules)/**/*.test.js\" --require=sinon-bluebird -R spec --recursive --no-exit",
+ "test": "env FORCE_COLOR=0 istanbul cover -x \"**/*.test.js\" node_modules/mocha/bin/_mocha \"!(node_modules)/**/*.test.js\" -- --require=sinon-bluebird -R spec --recursive",
"lint": "eslint . --cache",
"docs": "node scripts/generate-readme.js",
"simple-integration-test": "jest --maxWorkers=5 simple-suite",
@@ -86,21 +87,24 @@
"sinon-chai": "^2.9.0"
},
"dependencies": {
+ "@serverless/fdk": "^0.3.0",
"apollo-client": "^1.4.2",
"archiver": "^1.1.0",
"async": "^1.5.2",
"aws-sdk": "^2.7.13",
"bluebird": "^3.4.0",
- "chalk": "^1.1.1",
+ "chalk": "^2.0.0",
"ci-info": "^1.0.0",
"download": "^5.0.2",
"filesize": "^3.3.0",
"fs-extra": "^0.26.7",
"get-stdin": "^5.0.1",
"globby": "^6.1.0",
+ "graceful-fs": "^4.1.11",
"graphql": "^0.10.1",
"graphql-tag": "^2.4.0",
"https-proxy-agent": "^1.0.0",
+ "is-docker": "^1.1.0",
"js-yaml": "^3.6.1",
"json-refs": "^2.1.5",
"jwt-decode": "^2.2.0",
diff --git a/tests/templates/test_all_templates b/tests/templates/test_all_templates
index b539c35d1..cf587e778 100755
--- a/tests/templates/test_all_templates
+++ b/tests/templates/test_all_templates
@@ -17,4 +17,6 @@ integration-test aws-scala-sbt sbt assembly
integration-test aws-nodejs
integration-test aws-python
integration-test aws-python3
+integration-test aws-nodejs-typescript
+integration-test aws-nodejs-ecma-script
integration-test google-nodejs