~tcarrio/serverless-offline-aws-sqs

a48c053a56ec02d81c5a55e1cb91e17260b3c1bf — Tom Carrio 4 years ago
Initial commit of @0xc/serverless-offline-aws-sqs
6 files changed, 1850 insertions(+), 0 deletions(-)

A .gitignore
A LICENSE
A README.md
A package-lock.json
A package.json
A src/index.js
A  => .gitignore +8 -0
@@ 1,8 @@
node_modules
.env
.webpack
.serverless
.env*
.build
.idea
.vscode

A  => LICENSE +21 -0
@@ 1,21 @@
The MIT License (MIT)

Copyright (c) 2020 Thomas Carrio

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

A  => README.md +103 -0
@@ 1,103 @@
# serverless-offline-sqs

This Serverless-offline plugin emulates AWS λ and SQS queue on your local machine by using ElasticMQ. To do so, it listens SQS queue and invokes your handlers.

## Installation

First, add `@0xc/serverless-offline-aws-sqs` to your project:

```sh
yarn add @0xc/serverless-offline-aws-sqs
```

Then inside your project's `serverless.yml` file, add following entry to the plugins section before `serverless-offline` (and after `serverless-webpack` if presents): `@0xc/serverless-offline-aws-sqs`.

```yml
plugins:
  - serverless-webpack
  - "@0xc/serverless-offline-aws-sqs"
  - serverless-offline
```

## Configure

### Functions

Ths configuration of function of the plugin follows the [serverless documentation](https://serverless.com/framework/docs/providers/aws/events/sqs/).

```yml
functions:
  mySQSHandler:
    handler: handler.default
    events:
      - sqs:
          queueName: MyQueue
          arn:
            Fn::GetAtt:
              - MyQueue
              - Arn
resources:
  Resources:
    MyQueue:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: MyQueue
```

Inside your functions you could use a wrapper to switch between local and (aws) production environment.

```js
const AWS = require("aws-sdk");

let options = {};

// connect to local ElasticMQ if running offline
if (process.env.IS_OFFLINE) {
  options = {
    apiVersion: "2012-11-05",
    region: "localhost",
    endpoint: "http://0.0.0.0:9324",
    sslEnabled: false
  };
}

const client = new AWS.SQS(options);

export default client;
```

### Local SQS (ElasticMQ)

The configuration of [`aws.SQS`'s client](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SQS.html#constructor-property) of the plugin is done by defining a `custom: serverless-offline-sqs` object in your `serverless.yml` with your specific configuration.

You could use [ElasticMQ](https://github.com/adamw/elasticmq) with the following configuration:

```yml
custom:
  "@0xc/serverless-offline-aws-sqs":
    apiVersion: "2012-11-05"
    endpoint: http://0.0.0.0:9324
    region: eu-west-1
    accessKeyId: root
    secretAccessKey: root
    skipCacheInvalidation: false
```

Before you start your serverless functions you ElasticMQ needs to run.

```
docker run -it -p 9324:9324 s12v/elasticmq:latest

```

Queues will be automatically created.

## Roadmap

- install ElasticMQ automatically or start docker automatically

PLEASE HELP ME TO GET THIS DONE! EVERY PR IS WELCOME.

## Credits

This is a custom fork from [@meuschke/serverless-offline-aws-sqs](https://github.com/CoorpAcademy/serverless-plugins) Project

A  => package-lock.json +1296 -0
@@ 1,1296 @@
{
	"name": "@0xc/serverless-offline-aws-sqs",
	"version": "1.2.3",
	"lockfileVersion": 1,
	"requires": true,
	"dependencies": {
		"@babel/code-frame": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz",
			"integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==",
			"requires": {
				"@babel/highlight": "^7.10.1"
			}
		},
		"@babel/core": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.1.tgz",
			"integrity": "sha512-u8XiZ6sMXW/gPmoP5ijonSUln4unazG291X0XAQ5h0s8qnAFr6BRRZGUEK+jtRWdmB0NTJQt7Uga25q8GetIIg==",
			"requires": {
				"@babel/code-frame": "^7.10.1",
				"@babel/generator": "^7.10.1",
				"@babel/helper-module-transforms": "^7.10.1",
				"@babel/helpers": "^7.10.1",
				"@babel/parser": "^7.10.1",
				"@babel/template": "^7.10.1",
				"@babel/traverse": "^7.10.1",
				"@babel/types": "^7.10.1",
				"convert-source-map": "^1.7.0",
				"debug": "^4.1.0",
				"gensync": "^1.0.0-beta.1",
				"json5": "^2.1.2",
				"lodash": "^4.17.13",
				"resolve": "^1.3.2",
				"semver": "^5.4.1",
				"source-map": "^0.5.0"
			}
		},
		"@babel/generator": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.1.tgz",
			"integrity": "sha512-AT0YPLQw9DI21tliuJIdplVfLHya6mcGa8ctkv7n4Qv+hYacJrKmNWIteAK1P9iyLikFIAkwqJ7HAOqIDLFfgA==",
			"requires": {
				"@babel/types": "^7.10.1",
				"jsesc": "^2.5.1",
				"lodash": "^4.17.13",
				"source-map": "^0.5.0"
			}
		},
		"@babel/helper-function-name": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz",
			"integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==",
			"requires": {
				"@babel/helper-get-function-arity": "^7.10.1",
				"@babel/template": "^7.10.1",
				"@babel/types": "^7.10.1"
			}
		},
		"@babel/helper-get-function-arity": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz",
			"integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==",
			"requires": {
				"@babel/types": "^7.10.1"
			}
		},
		"@babel/helper-member-expression-to-functions": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz",
			"integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==",
			"requires": {
				"@babel/types": "^7.10.1"
			}
		},
		"@babel/helper-module-imports": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz",
			"integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==",
			"requires": {
				"@babel/types": "^7.10.1"
			}
		},
		"@babel/helper-module-transforms": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz",
			"integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==",
			"requires": {
				"@babel/helper-module-imports": "^7.10.1",
				"@babel/helper-replace-supers": "^7.10.1",
				"@babel/helper-simple-access": "^7.10.1",
				"@babel/helper-split-export-declaration": "^7.10.1",
				"@babel/template": "^7.10.1",
				"@babel/types": "^7.10.1",
				"lodash": "^4.17.13"
			}
		},
		"@babel/helper-optimise-call-expression": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz",
			"integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==",
			"requires": {
				"@babel/types": "^7.10.1"
			}
		},
		"@babel/helper-replace-supers": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz",
			"integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==",
			"requires": {
				"@babel/helper-member-expression-to-functions": "^7.10.1",
				"@babel/helper-optimise-call-expression": "^7.10.1",
				"@babel/traverse": "^7.10.1",
				"@babel/types": "^7.10.1"
			}
		},
		"@babel/helper-simple-access": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz",
			"integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==",
			"requires": {
				"@babel/template": "^7.10.1",
				"@babel/types": "^7.10.1"
			}
		},
		"@babel/helper-split-export-declaration": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz",
			"integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==",
			"requires": {
				"@babel/types": "^7.10.1"
			}
		},
		"@babel/helper-validator-identifier": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz",
			"integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw=="
		},
		"@babel/helpers": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz",
			"integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==",
			"requires": {
				"@babel/template": "^7.10.1",
				"@babel/traverse": "^7.10.1",
				"@babel/types": "^7.10.1"
			}
		},
		"@babel/highlight": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz",
			"integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==",
			"requires": {
				"@babel/helper-validator-identifier": "^7.10.1",
				"chalk": "^2.0.0",
				"js-tokens": "^4.0.0"
			}
		},
		"@babel/parser": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.1.tgz",
			"integrity": "sha512-AUTksaz3FqugBkbTZ1i+lDLG5qy8hIzCaAxEtttU6C0BtZZU9pkNZtWSVAht4EW9kl46YBiyTGMp9xTTGqViNg=="
		},
		"@babel/register": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/register/-/register-7.10.1.tgz",
			"integrity": "sha512-sl96+kB3IA2B9EzpwwBmYadOT14vw3KaXOknGDbJaZCOj52GDA4Tivudq9doCJcB+bEIKCEARZYwRgBBsCGXyg==",
			"requires": {
				"find-cache-dir": "^2.0.0",
				"lodash": "^4.17.13",
				"make-dir": "^2.1.0",
				"pirates": "^4.0.0",
				"source-map-support": "^0.5.16"
			}
		},
		"@babel/template": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz",
			"integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==",
			"requires": {
				"@babel/code-frame": "^7.10.1",
				"@babel/parser": "^7.10.1",
				"@babel/types": "^7.10.1"
			}
		},
		"@babel/traverse": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz",
			"integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==",
			"requires": {
				"@babel/code-frame": "^7.10.1",
				"@babel/generator": "^7.10.1",
				"@babel/helper-function-name": "^7.10.1",
				"@babel/helper-split-export-declaration": "^7.10.1",
				"@babel/parser": "^7.10.1",
				"@babel/types": "^7.10.1",
				"debug": "^4.1.0",
				"globals": "^11.1.0",
				"lodash": "^4.17.13"
			}
		},
		"@babel/types": {
			"version": "7.10.1",
			"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.1.tgz",
			"integrity": "sha512-L2yqUOpf3tzlW9GVuipgLEcZxnO+96SzR6fjXMuxxNkIgFJ5+07mHCZ+HkHqaeZu8+3LKnNJJ1bKbjBETQAsrA==",
			"requires": {
				"@babel/helper-validator-identifier": "^7.10.1",
				"lodash": "^4.17.13",
				"to-fast-properties": "^2.0.0"
			}
		},
		"accept": {
			"version": "2.1.4",
			"resolved": "https://registry.npmjs.org/accept/-/accept-2.1.4.tgz",
			"integrity": "sha1-iHr1TO7lx/RDBGGXHsQAxh0JrLs=",
			"requires": {
				"boom": "5.x.x",
				"hoek": "4.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"ammo": {
			"version": "2.0.4",
			"resolved": "https://registry.npmjs.org/ammo/-/ammo-2.0.4.tgz",
			"integrity": "sha1-v4CqshFpjqePY+9efxE91dnokX8=",
			"requires": {
				"boom": "5.x.x",
				"hoek": "4.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"ansi-styles": {
			"version": "3.2.1",
			"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
			"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
			"requires": {
				"color-convert": "^1.9.0"
			}
		},
		"aws-sdk": {
			"version": "2.686.0",
			"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.686.0.tgz",
			"integrity": "sha512-QhYhJ5y8tUG5SlmY3CSf9RBaa3EFbta28oarOyiwceHKmY80cMCafRI1YypT6CVDx/q91dbnSNQfWhs0cZPbBQ==",
			"requires": {
				"buffer": "4.9.1",
				"events": "1.1.1",
				"ieee754": "1.1.13",
				"jmespath": "0.15.0",
				"querystring": "0.2.0",
				"sax": "1.2.1",
				"url": "0.10.3",
				"uuid": "3.3.2",
				"xml2js": "0.4.19"
			}
		},
		"b64": {
			"version": "3.0.3",
			"resolved": "https://registry.npmjs.org/b64/-/b64-3.0.3.tgz",
			"integrity": "sha512-Pbeh0i6OLubPJdIdCepn8ZQHwN2MWznZHbHABSTEfQ706ie+yuxNSaPdqX1xRatT6WanaS1EazMiSg0NUW2XxQ=="
		},
		"base64-js": {
			"version": "1.3.1",
			"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
			"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
		},
		"boom": {
			"version": "7.3.0",
			"resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz",
			"integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==",
			"requires": {
				"hoek": "6.x.x"
			}
		},
		"bourne": {
			"version": "1.1.2",
			"resolved": "https://registry.npmjs.org/bourne/-/bourne-1.1.2.tgz",
			"integrity": "sha512-b2dgVkTZhkQirNMohgC00rWfpVqEi9y5tKM1k3JvoNx05ODtfQoPPd4js9CYFQoY0IM8LAmnJulEuWv74zjUOg=="
		},
		"buffer": {
			"version": "4.9.1",
			"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
			"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
			"requires": {
				"base64-js": "^1.0.2",
				"ieee754": "^1.1.4",
				"isarray": "^1.0.0"
			}
		},
		"buffer-equal-constant-time": {
			"version": "1.0.1",
			"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
			"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
		},
		"buffer-from": {
			"version": "1.1.1",
			"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
			"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
		},
		"call": {
			"version": "4.0.2",
			"resolved": "https://registry.npmjs.org/call/-/call-4.0.2.tgz",
			"integrity": "sha1-33b19R7o3Ui4VqyEAPfmnm1zmcQ=",
			"requires": {
				"boom": "5.x.x",
				"hoek": "4.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"catbox": {
			"version": "7.1.5",
			"resolved": "https://registry.npmjs.org/catbox/-/catbox-7.1.5.tgz",
			"integrity": "sha512-4fui5lELzqZ+9cnaAP/BcqXTH6LvWLBRtFhJ0I4FfgfXiSaZcf6k9m9dqOyChiTxNYtvLk7ZMYSf7ahMq3bf5A==",
			"requires": {
				"boom": "5.x.x",
				"hoek": "4.x.x",
				"joi": "10.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"catbox-memory": {
			"version": "2.0.4",
			"resolved": "https://registry.npmjs.org/catbox-memory/-/catbox-memory-2.0.4.tgz",
			"integrity": "sha1-Qz4lWQLK9UIz0ShkKcj03xToItU=",
			"requires": {
				"hoek": "4.x.x"
			},
			"dependencies": {
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"chalk": {
			"version": "2.4.2",
			"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
			"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
			"requires": {
				"ansi-styles": "^3.2.1",
				"escape-string-regexp": "^1.0.5",
				"supports-color": "^5.3.0"
			}
		},
		"color-convert": {
			"version": "1.9.3",
			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
			"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
			"requires": {
				"color-name": "1.1.3"
			}
		},
		"color-name": {
			"version": "1.1.3",
			"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
			"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
		},
		"commondir": {
			"version": "1.0.1",
			"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
			"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
		},
		"content": {
			"version": "3.0.7",
			"resolved": "https://registry.npmjs.org/content/-/content-3.0.7.tgz",
			"integrity": "sha512-LXtnSnvE+Z1Cjpa3P9gh9kb396qV4MqpfwKy777BOSF8n6nw2vAi03tHNl0/XRqZUyzVzY/+nMXOZVnEapWzdg==",
			"requires": {
				"boom": "5.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"convert-source-map": {
			"version": "1.7.0",
			"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
			"integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
			"requires": {
				"safe-buffer": "~5.1.1"
			}
		},
		"cryptiles": {
			"version": "4.1.3",
			"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-4.1.3.tgz",
			"integrity": "sha512-gT9nyTMSUC1JnziQpPbxKGBbUg8VL7Zn2NB4E1cJYvuXdElHrwxrV9bmltZGDzet45zSDGyYceueke1TjynGzw==",
			"requires": {
				"boom": "7.x.x"
			}
		},
		"debug": {
			"version": "4.1.1",
			"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
			"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
			"requires": {
				"ms": "^2.1.1"
			}
		},
		"ecdsa-sig-formatter": {
			"version": "1.0.11",
			"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
			"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
			"requires": {
				"safe-buffer": "^5.0.1"
			}
		},
		"escape-string-regexp": {
			"version": "1.0.5",
			"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
			"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
		},
		"events": {
			"version": "1.1.1",
			"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
			"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
		},
		"figures": {
			"version": "2.0.0",
			"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
			"integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
			"requires": {
				"escape-string-regexp": "^1.0.5"
			}
		},
		"find-cache-dir": {
			"version": "2.1.0",
			"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
			"integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
			"requires": {
				"commondir": "^1.0.1",
				"make-dir": "^2.0.0",
				"pkg-dir": "^3.0.0"
			}
		},
		"find-up": {
			"version": "3.0.0",
			"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
			"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
			"requires": {
				"locate-path": "^3.0.0"
			}
		},
		"gensync": {
			"version": "1.0.0-beta.1",
			"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
			"integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg=="
		},
		"globals": {
			"version": "11.12.0",
			"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
			"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
		},
		"h2o2": {
			"version": "6.1.0",
			"resolved": "https://registry.npmjs.org/h2o2/-/h2o2-6.1.0.tgz",
			"integrity": "sha1-Ky5/zKDjZlyUl2ReMgOvme2QM/E=",
			"requires": {
				"boom": "5.x.x",
				"hoek": "4.x.x",
				"joi": "10.x.x",
				"wreck": "12.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"hapi": {
			"version": "16.7.0",
			"resolved": "https://registry.npmjs.org/hapi/-/hapi-16.7.0.tgz",
			"integrity": "sha512-UeMX1LMWmHEIgMlwZGK/3lhI7X0VRvOioVply0Y9qF+/O5woGdQzNB8ZmDnLOBjnB6bdWWHyo5DEamuCsE1vmg==",
			"requires": {
				"accept": "2.x.x",
				"ammo": "2.x.x",
				"boom": "5.x.x",
				"call": "4.x.x",
				"catbox": "7.x.x",
				"catbox-memory": "2.x.x",
				"cryptiles": "3.x.x",
				"heavy": "4.x.x",
				"hoek": "4.x.x",
				"iron": "4.x.x",
				"items": "2.x.x",
				"joi": "11.x.x",
				"mimos": "3.x.x",
				"podium": "1.x.x",
				"shot": "3.x.x",
				"somever": "1.x.x",
				"statehood": "5.x.x",
				"subtext": "5.x.x",
				"topo": "2.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"cryptiles": {
					"version": "3.1.4",
					"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.4.tgz",
					"integrity": "sha512-8I1sgZHfVwcSOY6mSGpVU3lw/GSIZvusg8dD2+OGehCJpOhQRLNcH0qb9upQnOH4XhgxxFJSg6E2kx95deb1Tw==",
					"requires": {
						"boom": "5.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				},
				"isemail": {
					"version": "3.2.0",
					"resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz",
					"integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==",
					"requires": {
						"punycode": "2.x.x"
					}
				},
				"joi": {
					"version": "11.4.0",
					"resolved": "https://registry.npmjs.org/joi/-/joi-11.4.0.tgz",
					"integrity": "sha512-O7Uw+w/zEWgbL6OcHbyACKSj0PkQeUgmehdoXVSxt92QFCq4+1390Rwh5moI2K/OgC7D8RHRZqHZxT2husMJHA==",
					"requires": {
						"hoek": "4.x.x",
						"isemail": "3.x.x",
						"topo": "2.x.x"
					}
				},
				"punycode": {
					"version": "2.1.1",
					"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
					"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
				}
			}
		},
		"hapi-cors-headers": {
			"version": "1.0.3",
			"resolved": "https://registry.npmjs.org/hapi-cors-headers/-/hapi-cors-headers-1.0.3.tgz",
			"integrity": "sha512-U/y+kpVLUJ0y86fEk8yleou9C1T5wFopcWQjuxKdMXzCcymTjfSqGz59waqvngUs1SbeXav/y8Ga9C0G0L1MGg=="
		},
		"has-flag": {
			"version": "3.0.0",
			"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
			"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
		},
		"heavy": {
			"version": "4.0.4",
			"resolved": "https://registry.npmjs.org/heavy/-/heavy-4.0.4.tgz",
			"integrity": "sha1-NskTNsAMz+hSyqTRUwhjNc0vAOk=",
			"requires": {
				"boom": "5.x.x",
				"hoek": "4.x.x",
				"joi": "10.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"hoek": {
			"version": "6.1.3",
			"resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
			"integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ=="
		},
		"ieee754": {
			"version": "1.1.13",
			"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
			"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
		},
		"iron": {
			"version": "4.0.5",
			"resolved": "https://registry.npmjs.org/iron/-/iron-4.0.5.tgz",
			"integrity": "sha1-TwQszri5c480a1mqc0yDqJvDFCg=",
			"requires": {
				"boom": "5.x.x",
				"cryptiles": "3.x.x",
				"hoek": "4.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"cryptiles": {
					"version": "3.1.4",
					"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.4.tgz",
					"integrity": "sha512-8I1sgZHfVwcSOY6mSGpVU3lw/GSIZvusg8dD2+OGehCJpOhQRLNcH0qb9upQnOH4XhgxxFJSg6E2kx95deb1Tw==",
					"requires": {
						"boom": "5.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"isarray": {
			"version": "1.0.0",
			"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
			"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
		},
		"isemail": {
			"version": "2.2.1",
			"resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz",
			"integrity": "sha1-A1PT2aYpUQgMJiwqoKQrjqjp4qY="
		},
		"items": {
			"version": "2.1.2",
			"resolved": "https://registry.npmjs.org/items/-/items-2.1.2.tgz",
			"integrity": "sha512-kezcEqgB97BGeZZYtX/MA8AG410ptURstvnz5RAgyFZ8wQFPMxHY8GpTq+/ZHKT3frSlIthUq7EvLt9xn3TvXg=="
		},
		"jmespath": {
			"version": "0.15.0",
			"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz",
			"integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc="
		},
		"joi": {
			"version": "10.6.0",
			"resolved": "https://registry.npmjs.org/joi/-/joi-10.6.0.tgz",
			"integrity": "sha512-hBF3LcqyAid+9X/pwg+eXjD2QBZI5eXnBFJYaAkH4SK3mp9QSRiiQnDYlmlz5pccMvnLcJRS4whhDOTCkmsAdQ==",
			"requires": {
				"hoek": "4.x.x",
				"isemail": "2.x.x",
				"items": "2.x.x",
				"topo": "2.x.x"
			},
			"dependencies": {
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"js-string-escape": {
			"version": "1.0.1",
			"resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
			"integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8="
		},
		"js-tokens": {
			"version": "4.0.0",
			"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
			"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
		},
		"jsesc": {
			"version": "2.5.2",
			"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
			"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
		},
		"json5": {
			"version": "2.1.3",
			"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
			"integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
			"requires": {
				"minimist": "^1.2.5"
			}
		},
		"jsonpath-plus": {
			"version": "0.16.0",
			"resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-0.16.0.tgz",
			"integrity": "sha1-/kQbI/A+xpeaVgNROYjNPtt9tdw="
		},
		"jsonwebtoken": {
			"version": "8.5.1",
			"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
			"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
			"requires": {
				"jws": "^3.2.2",
				"lodash.includes": "^4.3.0",
				"lodash.isboolean": "^3.0.3",
				"lodash.isinteger": "^4.0.4",
				"lodash.isnumber": "^3.0.3",
				"lodash.isplainobject": "^4.0.6",
				"lodash.isstring": "^4.0.1",
				"lodash.once": "^4.0.0",
				"ms": "^2.1.1",
				"semver": "^5.6.0"
			}
		},
		"jwa": {
			"version": "1.4.1",
			"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
			"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
			"requires": {
				"buffer-equal-constant-time": "1.0.1",
				"ecdsa-sig-formatter": "1.0.11",
				"safe-buffer": "^5.0.1"
			}
		},
		"jws": {
			"version": "3.2.2",
			"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
			"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
			"requires": {
				"jwa": "^1.4.1",
				"safe-buffer": "^5.0.1"
			}
		},
		"locate-path": {
			"version": "3.0.0",
			"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
			"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
			"requires": {
				"p-locate": "^3.0.0",
				"path-exists": "^3.0.0"
			}
		},
		"lodash": {
			"version": "4.17.15",
			"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
			"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
		},
		"lodash.includes": {
			"version": "4.3.0",
			"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
			"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
		},
		"lodash.isboolean": {
			"version": "3.0.3",
			"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
			"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
		},
		"lodash.isinteger": {
			"version": "4.0.4",
			"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
			"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
		},
		"lodash.isnumber": {
			"version": "3.0.3",
			"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
			"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
		},
		"lodash.isplainobject": {
			"version": "4.0.6",
			"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
			"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
		},
		"lodash.isstring": {
			"version": "4.0.1",
			"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
			"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
		},
		"lodash.once": {
			"version": "4.1.1",
			"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
			"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
		},
		"make-dir": {
			"version": "2.1.0",
			"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
			"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
			"requires": {
				"pify": "^4.0.1",
				"semver": "^5.6.0"
			}
		},
		"mime-db": {
			"version": "1.44.0",
			"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
			"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
		},
		"mimos": {
			"version": "3.0.3",
			"resolved": "https://registry.npmjs.org/mimos/-/mimos-3.0.3.tgz",
			"integrity": "sha1-uRCQcq03jCty9qAQHEPd+ys2ZB8=",
			"requires": {
				"hoek": "4.x.x",
				"mime-db": "1.x.x"
			},
			"dependencies": {
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"minimist": {
			"version": "1.2.5",
			"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
			"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
		},
		"ms": {
			"version": "2.1.2",
			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
			"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
		},
		"nigel": {
			"version": "2.0.2",
			"resolved": "https://registry.npmjs.org/nigel/-/nigel-2.0.2.tgz",
			"integrity": "sha1-k6GGb7DFLYc5CqdeKxYfS1x15bE=",
			"requires": {
				"hoek": "4.x.x",
				"vise": "2.x.x"
			},
			"dependencies": {
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"node-modules-regexp": {
			"version": "1.0.0",
			"resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
			"integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA="
		},
		"p-limit": {
			"version": "2.3.0",
			"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
			"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
			"requires": {
				"p-try": "^2.0.0"
			}
		},
		"p-locate": {
			"version": "3.0.0",
			"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
			"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
			"requires": {
				"p-limit": "^2.0.0"
			}
		},
		"p-try": {
			"version": "2.2.0",
			"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
			"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
		},
		"path-exists": {
			"version": "3.0.0",
			"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
			"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
		},
		"path-parse": {
			"version": "1.0.6",
			"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
			"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
		},
		"pez": {
			"version": "2.1.5",
			"resolved": "https://registry.npmjs.org/pez/-/pez-2.1.5.tgz",
			"integrity": "sha1-XsLMYlAMw+tCNtSkFM9aF7XrUAc=",
			"requires": {
				"b64": "3.x.x",
				"boom": "5.x.x",
				"content": "3.x.x",
				"hoek": "4.x.x",
				"nigel": "2.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"pify": {
			"version": "4.0.1",
			"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
			"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
		},
		"pirates": {
			"version": "4.0.1",
			"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz",
			"integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==",
			"requires": {
				"node-modules-regexp": "^1.0.0"
			}
		},
		"pkg-dir": {
			"version": "3.0.0",
			"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
			"integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
			"requires": {
				"find-up": "^3.0.0"
			}
		},
		"podium": {
			"version": "1.3.0",
			"resolved": "https://registry.npmjs.org/podium/-/podium-1.3.0.tgz",
			"integrity": "sha512-ZIujqk1pv8bRZNVxwwwq0BhXilZ2udycQT3Kp8ah3f3TcTmVg7ILJsv/oLf47gRa2qeiP584lNq+pfvS9U3aow==",
			"requires": {
				"hoek": "4.x.x",
				"items": "2.x.x",
				"joi": "10.x.x"
			},
			"dependencies": {
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"punycode": {
			"version": "1.3.2",
			"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
			"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
		},
		"querystring": {
			"version": "0.2.0",
			"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
			"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
		},
		"resolve": {
			"version": "1.17.0",
			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
			"integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
			"requires": {
				"path-parse": "^1.0.6"
			}
		},
		"safe-buffer": {
			"version": "5.1.2",
			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
			"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
		},
		"sax": {
			"version": "1.2.1",
			"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
			"integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
		},
		"semver": {
			"version": "5.7.1",
			"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
			"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
		},
		"serverless-offline": {
			"version": "4.0.0",
			"resolved": "https://registry.npmjs.org/serverless-offline/-/serverless-offline-4.0.0.tgz",
			"integrity": "sha512-KG8wzrMZyOdI3MtDRahZq0u1O+MCHTRQVugitTo5wfLJKCqWSdtSXy6lW18NLMHoPYfCf+5hdB3vT/nCK6zqug==",
			"requires": {
				"@babel/core": "^7.0.0",
				"@babel/register": "^7.0.0",
				"boom": "^7.3.0",
				"cryptiles": "^4.1.2",
				"h2o2": "^6.1.0",
				"hapi": "^16.7.0",
				"hapi-cors-headers": "^1.0.3",
				"js-string-escape": "^1.0.1",
				"jsonpath-plus": "^0.16.0",
				"jsonwebtoken": "^8.3.0",
				"uuid": "^3.3.2",
				"velocityjs": "^1.1.2"
			}
		},
		"shot": {
			"version": "3.4.2",
			"resolved": "https://registry.npmjs.org/shot/-/shot-3.4.2.tgz",
			"integrity": "sha1-Hlw/bysmZJrcQvfrNQIUpaApHWc=",
			"requires": {
				"hoek": "4.x.x",
				"joi": "10.x.x"
			},
			"dependencies": {
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"somever": {
			"version": "1.0.1",
			"resolved": "https://registry.npmjs.org/somever/-/somever-1.0.1.tgz",
			"integrity": "sha512-PCDMBcega4n7wuBUKmkiXidF3cOwtHHGg2qJYl0Rkw7StZqORoCgqce7HUuWNta/NAiQhwLDezNnTANxEWPCGA==",
			"requires": {
				"hoek": "4.x.x"
			},
			"dependencies": {
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"source-map": {
			"version": "0.5.7",
			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
			"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
		},
		"source-map-support": {
			"version": "0.5.19",
			"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
			"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
			"requires": {
				"buffer-from": "^1.0.0",
				"source-map": "^0.6.0"
			},
			"dependencies": {
				"source-map": {
					"version": "0.6.1",
					"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
					"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
				}
			}
		},
		"statehood": {
			"version": "5.0.4",
			"resolved": "https://registry.npmjs.org/statehood/-/statehood-5.0.4.tgz",
			"integrity": "sha512-6/feFLqqHylvA/dHwJA0DgXvbEcKgbhRUeljsuu6+cIr8PO88nax7Wc+celZlPTncqT2arsxXL8P329Q1yfe9Q==",
			"requires": {
				"boom": "5.x.x",
				"bourne": "1.x.x",
				"cryptiles": "3.x.x",
				"hoek": "4.x.x",
				"iron": "4.x.x",
				"items": "2.x.x",
				"joi": "12.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"cryptiles": {
					"version": "3.1.4",
					"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.4.tgz",
					"integrity": "sha512-8I1sgZHfVwcSOY6mSGpVU3lw/GSIZvusg8dD2+OGehCJpOhQRLNcH0qb9upQnOH4XhgxxFJSg6E2kx95deb1Tw==",
					"requires": {
						"boom": "5.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				},
				"isemail": {
					"version": "3.2.0",
					"resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz",
					"integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==",
					"requires": {
						"punycode": "2.x.x"
					}
				},
				"joi": {
					"version": "12.0.0",
					"resolved": "https://registry.npmjs.org/joi/-/joi-12.0.0.tgz",
					"integrity": "sha512-z0FNlV4NGgjQN1fdtHYXf5kmgludM65fG/JlXzU6+rwkt9U5UWuXVYnXa2FpK0u6+qBuCmrm5byPNuiiddAHvQ==",
					"requires": {
						"hoek": "4.x.x",
						"isemail": "3.x.x",
						"topo": "2.x.x"
					}
				},
				"punycode": {
					"version": "2.1.1",
					"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
					"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
				}
			}
		},
		"subtext": {
			"version": "5.0.1",
			"resolved": "https://registry.npmjs.org/subtext/-/subtext-5.0.1.tgz",
			"integrity": "sha512-zH/jaUKJ/bkrTpEe3zuTFIRnqAwv5xcGpXA2JaxEc30KRAT4k78jZnRqM45snjBSZAuvpI8chRUh1VZprcUVfw==",
			"requires": {
				"boom": "5.x.x",
				"bourne": "1.x.x",
				"content": "3.x.x",
				"hoek": "4.x.x",
				"pez": "2.x.x",
				"wreck": "12.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"supports-color": {
			"version": "5.5.0",
			"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
			"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
			"requires": {
				"has-flag": "^3.0.0"
			}
		},
		"to-fast-properties": {
			"version": "2.0.0",
			"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
			"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
		},
		"topo": {
			"version": "2.0.2",
			"resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz",
			"integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=",
			"requires": {
				"hoek": "4.x.x"
			},
			"dependencies": {
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"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"
			}
		},
		"uuid": {
			"version": "3.3.2",
			"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
			"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
		},
		"velocityjs": {
			"version": "1.1.5",
			"resolved": "https://registry.npmjs.org/velocityjs/-/velocityjs-1.1.5.tgz",
			"integrity": "sha512-U4ANK4MRYSczVZjOp9FkAQoPO9geKSy3CWrBShPxMoWyqDox8SW8AZYiKtlCrV21ucONUtlU0iF3+KKK9AGoyA=="
		},
		"vise": {
			"version": "2.0.2",
			"resolved": "https://registry.npmjs.org/vise/-/vise-2.0.2.tgz",
			"integrity": "sha1-awjo+0y3bjpQzW3Q7DczjoEaDTk=",
			"requires": {
				"hoek": "4.x.x"
			},
			"dependencies": {
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"wreck": {
			"version": "12.5.1",
			"resolved": "https://registry.npmjs.org/wreck/-/wreck-12.5.1.tgz",
			"integrity": "sha512-l5DUGrc+yDyIflpty1x9XuMj1ehVjC/dTbF3/BasOO77xk0EdEa4M/DuOY8W88MQDAD0fEDqyjc8bkIMHd2E9A==",
			"requires": {
				"boom": "5.x.x",
				"hoek": "4.x.x"
			},
			"dependencies": {
				"boom": {
					"version": "5.2.0",
					"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
					"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
					"requires": {
						"hoek": "4.x.x"
					}
				},
				"hoek": {
					"version": "4.2.1",
					"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
					"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
				}
			}
		},
		"xml2js": {
			"version": "0.4.19",
			"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
			"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
			"requires": {
				"sax": ">=0.6.0",
				"xmlbuilder": "~9.0.1"
			}
		},
		"xmlbuilder": {
			"version": "9.0.7",
			"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
			"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
		}
	}
}

A  => package.json +35 -0
@@ 1,35 @@
{
  "name": "@0xc/serverless-offline-aws-sqs",
  "version": "1.2.3",
  "description": "AWS SQS 📤 Plugin for Serverless Framework ⚡️| Webpack support | Local ElasticMQ",
  "main": "src",
  "private": false,
  "repository": {
    "type": "git",
    "url": "git@github.com:tcarrio/serverless-offline-aws-sqs.git"
  },
  "bugs": {
    "url": "https://github.com/tcarrio/serverless-offline-aws-sqs/issues"
  },
  "homepage": "https://github.com/tcarrio/serverless-offline-aws-sqs/tree/master#readme",
  "files": [
    "src/index.js"
  ],
  "author": "Tom Carrio <tom@carrio.dev>",
  "license": "MIT",
  "dependencies": {
    "aws-sdk": "^2.271.1",
    "figures": "^2.0.0",
    "lodash": "^4.17.10",
    "serverless-offline": "4.0.0"
  },
  "keywords": [
    "sqs",
    "elasticmq",
    "serverless",
    "offline",
    "local",
    "aws",
    "lambda"
  ]
}

A  => src/index.js +387 -0
@@ 1,387 @@
// FIXME: Remove the eslint disable
/* eslint-disable @typescript-eslint/no-var-requires */
const { join } = require("path");
const figures = require("figures");
const SQS = require("aws-sdk/clients/sqs");
const {
  mapValues,
  isEmpty,
  forEach,
  map,
  has,
  filter,
  get,
  pipe,
} = require("lodash/fp");
const {
  createHandler,
  getFunctionOptions,
} = require("serverless-offline/src/functionHelper");
const createLambdaContext = require("serverless-offline/src/createLambdaContext");

const fromCallback = fun =>
  new Promise((resolve, reject) => {
    fun((err, data) => {
      if (err) return reject(err);
      resolve(data);
    });
  });

const printBlankLine = () => console.log();

const getConfig = (service, pluginName) => {
  return (service && service.custom && service.custom[pluginName]) || {};
};

const extractQueueNameFromARN = arn => {
  const [, , , , , QueueName] = arn.split(":");
  return QueueName;
};

class ServerlessOfflineSQS {
  constructor(serverless, options) {
    this.serverless = serverless;
    this.service = serverless.service;
    this.options = options;
    this.config = getConfig(this.service, "serverless-offline-aws-sqs");

    this.serverless.cli.log("found SQS config:");
    this.serverless.cli.log(JSON.stringify(this.config, null, 2));

    this.commands = {};

    this.hooks = {
      "before:offline:start:init": this.offlineStartInit.bind(this),
      "before:offline:start:end": this.offlineStartEnd.bind(this),
    };

    this.streams = [];
  }

  getClient() {
    const awsConfig = Object.assign(
      {
        region:
          this.options.region || this.service.provider.region || "us-east-1",
      },
      this.config,
    );
    this.serverless.cli.log("getClient with config:");
    this.serverless.cli.log(JSON.stringify(awsConfig, null, 2));
    const awsSqs = new SQS(awsConfig);
    this.serverless.cli.log(`generated SQS with endpoint ${awsSqs.endpoint}`);
    return awsSqs;
  }

  getQueueName(queueEvent) {
    if (typeof queueEvent === "string")
      return extractQueueNameFromARN(queueEvent);
    if (typeof queueEvent.arn === "string")
      return extractQueueNameFromARN(queueEvent.arn);
    if (typeof queueEvent.queueName === "string") return queueEvent.queueName;

    if (queueEvent.arn["Fn::GetAtt"]) {
      const [ResourceName] = queueEvent.arn["Fn::GetAtt"];
      const resource = this.getReferencedQueuesName(ResourceName);
      if (resource) {
        return resource;
      }
    }

    throw new Error(`QueueName not found. See Readme`);
  }

  eventHandler(queueEvent, functionName, messages, cb) {
    if (!messages) return cb();

    const streamName = this.getQueueName(queueEvent);
    this.serverless.cli.log(`${streamName} (λ: ${functionName})`);
    let location = "";
    const offlinePlugin = this.serverless.pluginManager
      .getPlugins()
      .find(p => p.constructor && p.constructor.name === "Offline");
    if (offlinePlugin) {
      location = offlinePlugin.options.location;
    }

    const __function = this.service.getFunction(functionName);

    const { env } = process;
    const providerEnv = this.dereferencedObject(
      "service.provider.environment",
      this,
    );
    const environment = this.dereferencedObject("environment", __function);
    const functionEnv = Object.assign({}, env, providerEnv, environment);
    process.env = functionEnv;

    const servicePath = join(this.serverless.config.servicePath, location);
    const funcOptions = getFunctionOptions(
      __function,
      functionName,
      servicePath,
    );
    const handler = createHandler(
      funcOptions,
      Object.assign({}, this.options, this.config),
    );

    const lambdaContext = createLambdaContext(__function, (err, data) => {
      this.serverless.cli.log(
        `[${err ? figures.cross : figures.tick}] ${JSON.stringify(data) || ""}`,
      );
      cb(err, data);
    });

    const event = {
      Records: messages.map(
        ({
          MessageId: messageId,
          ReceiptHandle: receiptHandle,
          Body: body,
          Attributes: attributes,
          MessageAttributes: messageAttributes,
          MD5OfBody: md5OfBody,
        }) => ({
          messageId,
          receiptHandle,
          body,
          attributes,
          messageAttributes,
          md5OfBody,
          eventSource: "aws:sqs",
          eventSourceARN: queueEvent.arn,
          awsRegion: "us-east-1",
        }),
      ),
    };

    if (handler.length < 3) {
      handler(event, lambdaContext)
        .then(res => lambdaContext.done(null, res))
        .catch(lambdaContext.done);
    } else {
      handler(event, lambdaContext, lambdaContext.done);
    }

    process.env = env;
  }

  async createQueueReadable(functionName, queueEvent) {
    this.serverless.cli.log("Entered createQueueReadable");
    const client = await this.getClient();
    const queueName = this.getQueueName(queueEvent);

    this.serverless.cli.log(`QueueName is ${queueName}`);

    let { QueueUrl } = await fromCallback(cb =>
      client.getQueueUrl(
        {
          QueueName: queueName,
        },
        cb,
      ),
    );

    if (!QueueUrl.includes(client.endpoint)) {
      this.serverless.cli.log("QueueUrl does not contain the correct host");
      this.serverless.cli.log(`Found: ${QueueUrl}`);
      QueueUrl = QueueUrl.replace(
        /^https?:\/\/(localhost|127.0.0.1):\d+/,
        client.config.endpoint,
      );
    }

    this.serverless.cli.log(`QueueUrl is ${QueueUrl}`);

    const next = async () => {
      const { Messages } = await fromCallback(cb =>
        client.receiveMessage(
          {
            QueueUrl,
            MaxNumberOfMessages: queueEvent.batchSize,
            AttributeNames: ["All"],
            MessageAttributeNames: ["All"],
            WaitTimeSeconds: 1,
          },
          cb,
        ),
      );

      if (Messages) {
        await fromCallback(cb =>
          this.eventHandler(queueEvent, functionName, Messages, cb),
        );

        await fromCallback(cb =>
          client.deleteMessageBatch(
            {
              Entries: (Messages || []).map(
                ({ MessageId: Id, ReceiptHandle }) => ({
                  Id,
                  ReceiptHandle,
                }),
              ),
              QueueUrl,
            },
            () => cb(),
          ),
        );
      }

      next();
    };

    next();
  }

  async createInitialQueue(queue) {
    this.serverless.cli.log(`Creating queue: ${queue.QueueName}`);
    return new Promise(async (resolve, reject) => {
      const client = await this.getClient();

      const params = {
        QueueName: queue.QueueName /* required */,
        Attributes: {},
      };

      forEach(attribute => {
        if (attribute !== "QueueName") {
          params.Attributes = {
            ...params.Attributes,
            ...JSON.stringify(attribute, queue[attribute]),
          };
        }
      }, Object.keys(queue));

      client.createQueue(params, err => {
        if (err) reject(err);
        resolve();
      });
    });
  }

  async offlineStartInit() {
    this.serverless.cli.log(`Creating Offline SQS Queues.`);
    if (
      this.service &&
      this.service.resources &&
      this.service.resources.Resources
    ) {
      const resources = Object.keys(this.service.resources.Resources);
      const queues = resources.filter(
        r => this.service.resources.Resources[r].Type === "AWS::SQS::Queue",
      );
      const parentResources = queues
        .filter(
          r =>
            !this.referencesArn(this.service.resources.Resources[r].Properties),
        )
        .map(r => this.service.resources.Resources[r].Properties);
      const childResources = queues
        .filter(
          r =>
            !!this.referencesArn(
              this.service.resources.Resources[r].Properties,
            ),
        )
        .map(r => this.service.resources.Resources[r].Properties);

      // NOTE: In case of a parent-child reference in the SQS declarations, this
      // allows for the dependencies to be created prior to the dependents. This
      // also does not handle cases where references go multiple levels deep.
      await Promise.all(parentResources.map(q => this.createInitialQueue(q)));
      printBlankLine();
      await Promise.all(childResources.map(q => this.createInitialQueue(q)));
      printBlankLine();
    }

    this.serverless.cli.log(`Starting Offline SQS.`);

    const readableQueuePromises = [];

    mapValues.convert({ cap: false })((_function, functionName) => {
      const queues = pipe(
        get("events"),
        filter(has("sqs")),
        map(get("sqs")),
      )(_function);

      this.serverless.cli.log(
        `${functionName} has ${queues.length} events from SQS`,
      );

      if (!isEmpty(queues)) {
        printBlankLine();
        this.serverless.cli.log(`SQS for ${functionName}:`);
      }

      forEach(queueEvent => {
        readableQueuePromises.push(
          this.createQueueReadable(functionName, queueEvent),
        );
      }, queues);

      if (!isEmpty(queues)) {
        printBlankLine();
      }
    }, this.service.functions);

    await Promise.all(readableQueuePromises);
  }

  offlineStartEnd() {
    this.serverless.cli.log("offline-start-end");
  }

  referencesArn(resource) {
    return (
      resource.RedrivePolicy &&
      resource.RedrivePolicy.deadLetterTargetArn &&
      resource.RedrivePolicy.deadLetterTargetArn["Fn:GetAtt"] &&
      this.names.has(resource.RedrivePolicy.deadLetterTargetArn["Fn:GetAtt"][0])
    );
  }

  dereferencedObject(key, ref) {
    const input = get(key, ref) || {};

    const nonreferencedObj = Object.keys(input)
      .filter(k => input[k].Ref === undefined)
      .reduce((o, k) => ({ ...o, [k]: input[k] }), {});

    const dereferencedObj = Object.keys(input)
      .filter(k => input[k].Ref !== undefined)
      .reduce(
        (o, k) => ({
          ...o,
          [k]: this.getReferencedQueuesName(input[k].Ref),
        }),
        {},
      );

    return {
      ...nonreferencedObj,
      ...dereferencedObj,
    };
  }

  getReferencedQueuesName(name) {
    const queueName = get(
      `service.resources.Resources.${name}.Properties.QueueName`,
      this,
    );
    if (queueName) {
      return queueName;
    } else {
      this.serverless.cli.log(
        "Failed to retrieve reference name from service listing",
      );
      this.serverless.cli.log(this.service.resources);
    }

    return null;
  }
}

module.exports = ServerlessOfflineSQS;