Merge pull request #6 from Seich/hosts

Added support for multiple hosts.
This commit is contained in:
Sergio Díaz 2018-01-21 15:37:56 -06:00 committed by GitHub
commit 59acbd59b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 797 additions and 1101 deletions

View File

@ -1,4 +1,4 @@
Copyright 2017 David Sergio Díaz
Copyright 2018 David Sergio Díaz
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:

View File

@ -12,14 +12,18 @@
## What is Beau?
Beau, is a CLI that executes HTTP requests based on a YAML configuration file. This makes testing easy, it allows you to share test requests with others as part of your repo.
Beau, is a CLI that executes HTTP requests based on a YAML configuration file.
This makes testing easy, it allows you to share test requests with others as
part of your repo.
![A Gif showing how beau works](http://files.martianwabbit.com/beau2.gif)
## Installation
npm install -g beau
## Usage
⚡ beau --help
Usage: beau [options] [command]
@ -60,15 +64,30 @@ Beau, is a CLI that executes HTTP requests based on a YAML configuration file. T
archived: true
## Example Usage
beau request profile
That would execute the profile request along with it´s dependencies. In this case, the session request would be made as well since we are using it´s response value as part of our current request.
That would execute the profile request along with it´s dependencies. In this
case, the session request would be made as well since we are using it´s response
value as part of our current request.
## License
Copyright 2017 David Sergio Díaz
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:
Copyright 2018 David Sergio Díaz
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
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 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.
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.

View File

@ -20,7 +20,7 @@ program
'beau.yml'
)
.option(
'-v --verbose',
'--verbose',
'Show all the information available on the current request.',
false
)

32
examples/hosts.yml Normal file
View File

@ -0,0 +1,32 @@
version: 1
environment:
the:
post: 2
defaults:
headers:
hello: 'Hello2'
GET http://jsonplaceholder.typicode.com/posts/1:
alias: a-post
headers:
hello: $jpa2:get-post.body.id
hosts:
- host: jpa
endpoint: http://jsonplaceholder.typicode.com
GET /posts/$env.the.post: get-post
GET /users/$jpa:get-post.body.userId: hello
- host: jpa2
endpoint: http://jsonplaceholder.typicode.com
defaults:
headers: false
GET /posts/$jpa:get-post.body.id:
alias: get-post

906
package-lock.json generated
View File

@ -1145,910 +1145,6 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"fsevents": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz",
"integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==",
"dev": true,
"optional": true,
"requires": {
"nan": "2.8.0",
"node-pre-gyp": "0.6.39"
},
"dependencies": {
"abbrev": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
},
"ajv": {
"version": "4.11.8",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"co": "4.6.0",
"json-stable-stringify": "1.0.1"
}
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
},
"aproba": {
"version": "1.1.1",
"bundled": true,
"dev": true,
"optional": true
},
"are-we-there-yet": {
"version": "1.1.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"delegates": "1.0.0",
"readable-stream": "2.2.9"
}
},
"asn1": {
"version": "0.2.3",
"bundled": true,
"dev": true,
"optional": true
},
"assert-plus": {
"version": "0.2.0",
"bundled": true,
"dev": true,
"optional": true
},
"asynckit": {
"version": "0.4.0",
"bundled": true,
"dev": true,
"optional": true
},
"aws-sign2": {
"version": "0.6.0",
"bundled": true,
"dev": true,
"optional": true
},
"aws4": {
"version": "1.6.0",
"bundled": true,
"dev": true,
"optional": true
},
"balanced-match": {
"version": "0.4.2",
"bundled": true,
"dev": true
},
"bcrypt-pbkdf": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"tweetnacl": "0.14.5"
}
},
"block-stream": {
"version": "0.0.9",
"bundled": true,
"dev": true,
"requires": {
"inherits": "2.0.3"
}
},
"boom": {
"version": "2.10.1",
"bundled": true,
"dev": true,
"requires": {
"hoek": "2.16.3"
}
},
"brace-expansion": {
"version": "1.1.7",
"bundled": true,
"dev": true,
"requires": {
"balanced-match": "0.4.2",
"concat-map": "0.0.1"
}
},
"buffer-shims": {
"version": "1.0.0",
"bundled": true,
"dev": true
},
"caseless": {
"version": "0.12.0",
"bundled": true,
"dev": true,
"optional": true
},
"co": {
"version": "4.6.0",
"bundled": true,
"dev": true,
"optional": true
},
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
},
"combined-stream": {
"version": "1.0.5",
"bundled": true,
"dev": true,
"requires": {
"delayed-stream": "1.0.0"
}
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
},
"core-util-is": {
"version": "1.0.2",
"bundled": true,
"dev": true
},
"cryptiles": {
"version": "2.0.5",
"bundled": true,
"dev": true,
"requires": {
"boom": "2.10.1"
}
},
"dashdash": {
"version": "1.14.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"assert-plus": "1.0.0"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
}
}
},
"debug": {
"version": "2.6.8",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ms": "2.0.0"
}
},
"deep-extend": {
"version": "0.4.2",
"bundled": true,
"dev": true,
"optional": true
},
"delayed-stream": {
"version": "1.0.0",
"bundled": true,
"dev": true
},
"delegates": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
},
"detect-libc": {
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true
},
"ecc-jsbn": {
"version": "0.1.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"jsbn": "0.1.1"
}
},
"extend": {
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true
},
"extsprintf": {
"version": "1.0.2",
"bundled": true,
"dev": true
},
"forever-agent": {
"version": "0.6.1",
"bundled": true,
"dev": true,
"optional": true
},
"form-data": {
"version": "2.1.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"asynckit": "0.4.0",
"combined-stream": "1.0.5",
"mime-types": "2.1.15"
}
},
"fs.realpath": {
"version": "1.0.0",
"bundled": true,
"dev": true
},
"fstream": {
"version": "1.0.11",
"bundled": true,
"dev": true,
"requires": {
"graceful-fs": "4.1.11",
"inherits": "2.0.3",
"mkdirp": "0.5.1",
"rimraf": "2.6.1"
}
},
"fstream-ignore": {
"version": "1.0.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"fstream": "1.0.11",
"inherits": "2.0.3",
"minimatch": "3.0.4"
}
},
"gauge": {
"version": "2.7.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"aproba": "1.1.1",
"console-control-strings": "1.1.0",
"has-unicode": "2.0.1",
"object-assign": "4.1.1",
"signal-exit": "3.0.2",
"string-width": "1.0.2",
"strip-ansi": "3.0.1",
"wide-align": "1.1.2"
}
},
"getpass": {
"version": "0.1.7",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"assert-plus": "1.0.0"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
}
}
},
"glob": {
"version": "7.1.2",
"bundled": true,
"dev": true,
"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"
}
},
"graceful-fs": {
"version": "4.1.11",
"bundled": true,
"dev": true
},
"har-schema": {
"version": "1.0.5",
"bundled": true,
"dev": true,
"optional": true
},
"har-validator": {
"version": "4.2.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ajv": "4.11.8",
"har-schema": "1.0.5"
}
},
"has-unicode": {
"version": "2.0.1",
"bundled": true,
"dev": true,
"optional": true
},
"hawk": {
"version": "3.1.3",
"bundled": true,
"dev": true,
"requires": {
"boom": "2.10.1",
"cryptiles": "2.0.5",
"hoek": "2.16.3",
"sntp": "1.0.9"
}
},
"hoek": {
"version": "2.16.3",
"bundled": true,
"dev": true
},
"http-signature": {
"version": "1.1.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"assert-plus": "0.2.0",
"jsprim": "1.4.0",
"sshpk": "1.13.0"
}
},
"inflight": {
"version": "1.0.6",
"bundled": true,
"dev": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
},
"ini": {
"version": "1.3.4",
"bundled": true,
"dev": true,
"optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"requires": {
"number-is-nan": "1.0.1"
}
},
"is-typedarray": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
},
"isarray": {
"version": "1.0.0",
"bundled": true,
"dev": true
},
"isstream": {
"version": "0.1.2",
"bundled": true,
"dev": true,
"optional": true
},
"jodid25519": {
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"jsbn": "0.1.1"
}
},
"jsbn": {
"version": "0.1.1",
"bundled": true,
"dev": true,
"optional": true
},
"json-schema": {
"version": "0.2.3",
"bundled": true,
"dev": true,
"optional": true
},
"json-stable-stringify": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"jsonify": "0.0.0"
}
},
"json-stringify-safe": {
"version": "5.0.1",
"bundled": true,
"dev": true,
"optional": true
},
"jsonify": {
"version": "0.0.0",
"bundled": true,
"dev": true,
"optional": true
},
"jsprim": {
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": 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",
"bundled": true,
"dev": true,
"optional": true
}
}
},
"mime-db": {
"version": "1.27.0",
"bundled": true,
"dev": true
},
"mime-types": {
"version": "2.1.15",
"bundled": true,
"dev": true,
"requires": {
"mime-db": "1.27.0"
}
},
"minimatch": {
"version": "3.0.4",
"bundled": true,
"dev": true,
"requires": {
"brace-expansion": "1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
},
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"dev": true,
"requires": {
"minimist": "0.0.8"
}
},
"ms": {
"version": "2.0.0",
"bundled": true,
"dev": true,
"optional": true
},
"node-pre-gyp": {
"version": "0.6.39",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"detect-libc": "1.0.2",
"hawk": "3.1.3",
"mkdirp": "0.5.1",
"nopt": "4.0.1",
"npmlog": "4.1.0",
"rc": "1.2.1",
"request": "2.81.0",
"rimraf": "2.6.1",
"semver": "5.3.0",
"tar": "2.2.1",
"tar-pack": "3.4.0"
}
},
"nopt": {
"version": "4.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"abbrev": "1.1.0",
"osenv": "0.1.4"
}
},
"npmlog": {
"version": "4.1.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"are-we-there-yet": "1.1.4",
"console-control-strings": "1.1.0",
"gauge": "2.7.4",
"set-blocking": "2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
},
"oauth-sign": {
"version": "0.8.2",
"bundled": true,
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
"bundled": true,
"dev": true,
"optional": true
},
"once": {
"version": "1.4.0",
"bundled": true,
"dev": true,
"requires": {
"wrappy": "1.0.2"
}
},
"os-homedir": {
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true
},
"os-tmpdir": {
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true
},
"osenv": {
"version": "0.1.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"os-homedir": "1.0.2",
"os-tmpdir": "1.0.2"
}
},
"path-is-absolute": {
"version": "1.0.1",
"bundled": true,
"dev": true
},
"performance-now": {
"version": "0.2.0",
"bundled": true,
"dev": true,
"optional": true
},
"process-nextick-args": {
"version": "1.0.7",
"bundled": true,
"dev": true
},
"punycode": {
"version": "1.4.1",
"bundled": true,
"dev": true,
"optional": true
},
"qs": {
"version": "6.4.0",
"bundled": true,
"dev": true,
"optional": true
},
"rc": {
"version": "1.2.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"deep-extend": "0.4.2",
"ini": "1.3.4",
"minimist": "1.2.0",
"strip-json-comments": "2.0.1"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"bundled": true,
"dev": true,
"optional": true
}
}
},
"readable-stream": {
"version": "2.2.9",
"bundled": true,
"dev": true,
"requires": {
"buffer-shims": "1.0.0",
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"string_decoder": "1.0.1",
"util-deprecate": "1.0.2"
}
},
"request": {
"version": "2.81.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"aws-sign2": "0.6.0",
"aws4": "1.6.0",
"caseless": "0.12.0",
"combined-stream": "1.0.5",
"extend": "3.0.1",
"forever-agent": "0.6.1",
"form-data": "2.1.4",
"har-validator": "4.2.1",
"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",
"performance-now": "0.2.0",
"qs": "6.4.0",
"safe-buffer": "5.0.1",
"stringstream": "0.0.5",
"tough-cookie": "2.3.2",
"tunnel-agent": "0.6.0",
"uuid": "3.0.1"
}
},
"rimraf": {
"version": "2.6.1",
"bundled": true,
"dev": true,
"requires": {
"glob": "7.1.2"
}
},
"safe-buffer": {
"version": "5.0.1",
"bundled": true,
"dev": true
},
"semver": {
"version": "5.3.0",
"bundled": true,
"dev": true,
"optional": true
},
"set-blocking": {
"version": "2.0.0",
"bundled": true,
"dev": true,
"optional": true
},
"signal-exit": {
"version": "3.0.2",
"bundled": true,
"dev": true,
"optional": true
},
"sntp": {
"version": "1.0.9",
"bundled": true,
"dev": true,
"requires": {
"hoek": "2.16.3"
}
},
"sshpk": {
"version": "1.13.0",
"bundled": true,
"dev": true,
"optional": 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",
"jodid25519": "1.0.2",
"jsbn": "0.1.1",
"tweetnacl": "0.14.5"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
}
}
},
"string-width": {
"version": "1.0.2",
"bundled": true,
"dev": true,
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
}
},
"string_decoder": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"requires": {
"safe-buffer": "5.0.1"
}
},
"stringstream": {
"version": "0.0.5",
"bundled": true,
"dev": true,
"optional": true
},
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"dev": true,
"requires": {
"ansi-regex": "2.1.1"
}
},
"strip-json-comments": {
"version": "2.0.1",
"bundled": true,
"dev": true,
"optional": true
},
"tar": {
"version": "2.2.1",
"bundled": true,
"dev": true,
"requires": {
"block-stream": "0.0.9",
"fstream": "1.0.11",
"inherits": "2.0.3"
}
},
"tar-pack": {
"version": "3.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"debug": "2.6.8",
"fstream": "1.0.11",
"fstream-ignore": "1.0.5",
"once": "1.4.0",
"readable-stream": "2.2.9",
"rimraf": "2.6.1",
"tar": "2.2.1",
"uid-number": "0.0.6"
}
},
"tough-cookie": {
"version": "2.3.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"punycode": "1.4.1"
}
},
"tunnel-agent": {
"version": "0.6.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "5.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"bundled": true,
"dev": true,
"optional": true
},
"uid-number": {
"version": "0.0.6",
"bundled": true,
"dev": true,
"optional": true
},
"util-deprecate": {
"version": "1.0.2",
"bundled": true,
"dev": true
},
"uuid": {
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true
},
"verror": {
"version": "1.3.6",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"extsprintf": "1.0.2"
}
},
"wide-align": {
"version": "1.1.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"string-width": "1.0.2"
}
},
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
}
}
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -3087,7 +2183,6 @@
"anymatch": "1.3.2",
"exec-sh": "0.2.1",
"fb-watchman": "2.0.0",
"fsevents": "1.1.3",
"minimatch": "3.0.4",
"minimist": "1.2.0",
"walker": "1.0.7",
@ -3779,7 +2874,6 @@
"anymatch": "1.3.2",
"exec-sh": "0.2.1",
"fb-watchman": "2.0.0",
"fsevents": "1.1.3",
"minimatch": "3.0.4",
"minimist": "1.2.0",
"walker": "1.0.7",

View File

@ -1,8 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Beau's config Loader. should set up defaults for all requests 1`] = `
exports[`Beau's config Loader. should create a request list 1`] = `
Beau {
"config": Object {
"config": Config {
"CACHE": false,
"DEFAULTS": Object {
"headers": Object {
@ -11,9 +11,9 @@ Beau {
},
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"ENVIRONMENT": Object {},
"HOSTS": Array [],
"PLUGINS": Array [],
"VERSION": 1,
},
"configKeys": Array [
"VERSION",
"CACHE",
@ -21,18 +21,52 @@ Beau {
"PLUGINS",
"DEFAULTS",
"ENVIRONMENT",
"HOSTS",
],
"defaults": Object {
"defaultConfigValues": Object {
"CACHE": false,
"DEFAULTS": Object {
"DEFAULTS": Object {},
"ENDPOINT": "",
"ENVIRONMENT": Object {},
"HOSTS": Array [],
"PLUGINS": Array [],
"VERSION": 1,
},
"doc": Object {
"GET /posts/1": "get-post",
"GET /user": Object {
"alias": "user",
"headers": Object {
"hello": "world",
},
},
"defaults": Object {
"headers": Object {
"authentication": "hello",
},
},
"endpoint": "http://jsonplaceholder.typicode.com",
"version": 1,
},
"requests": Array [
Object {
"ALIAS": "get-post",
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"ENVIRONMENT": Object {},
"PLUGINS": Array [],
"VERSION": 1,
"HEADERS": Object {
"authentication": "hello",
},
"REQUEST": "GET /posts/1",
},
Object {
"ALIAS": "user",
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
"hello": "world",
},
"REQUEST": "GET /user",
},
],
},
"requests": RequestList {
"cache": RequestCache {
@ -40,7 +74,7 @@ Beau {
"$env": Object {},
},
},
"config": Object {
"config": Config {
"CACHE": false,
"DEFAULTS": Object {
"headers": Object {
@ -49,14 +83,67 @@ Beau {
},
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"ENVIRONMENT": Object {},
"HOSTS": Array [],
"PLUGINS": Array [],
"VERSION": 1,
"configKeys": Array [
"VERSION",
"CACHE",
"ENDPOINT",
"PLUGINS",
"DEFAULTS",
"ENVIRONMENT",
"HOSTS",
],
"defaultConfigValues": Object {
"CACHE": false,
"DEFAULTS": Object {},
"ENDPOINT": "",
"ENVIRONMENT": Object {},
"HOSTS": Array [],
"PLUGINS": Array [],
"VERSION": 1,
},
"doc": Object {
"GET /posts/1": "get-post",
"GET /user": Object {
"alias": "user",
"headers": Object {
"hello": "world",
},
},
"defaults": Object {
"headers": Object {
"authentication": "hello",
},
},
"endpoint": "http://jsonplaceholder.typicode.com",
"version": 1,
},
"requests": Array [
Object {
"ALIAS": "get-post",
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
},
"REQUEST": "GET /posts/1",
},
Object {
"ALIAS": "user",
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
"hello": "world",
},
"REQUEST": "GET /user",
},
],
},
"list": Array [
Request {
"ALIAS": "get-post",
"DEPENDENCIES": Set {},
"DOCUMENTATION": undefined,
"ENDPOINT": "http://jsonplaceholder.typicode.com/posts/1",
"HEADERS": Object {
"authentication": "hello",
@ -67,16 +154,15 @@ Beau {
"originalRequest": Object {
"ALIAS": "get-post",
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"headers": Object {
"HEADERS": Object {
"authentication": "hello",
},
"request": "GET /posts/1",
"REQUEST": "GET /posts/1",
},
},
Request {
"ALIAS": "user",
"DEPENDENCIES": Set {},
"DOCUMENTATION": undefined,
"ENDPOINT": "http://jsonplaceholder.typicode.com/user",
"HEADERS": Object {
"authentication": "hello",
@ -86,17 +172,36 @@ Beau {
"PAYLOAD": undefined,
"VERB": "GET",
"originalRequest": Object {
"ALIAS": "user",
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"alias": "user",
"headers": Object {
"HEADERS": Object {
"authentication": "hello",
"hello": "world",
},
"request": "GET /user",
"REQUEST": "GET /user",
},
},
],
"modifiers": Array [],
"requests": Array [
Object {
"ALIAS": "get-post",
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
},
"REQUEST": "GET /posts/1",
},
Object {
"ALIAS": "user",
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
"hello": "world",
},
"REQUEST": "GET /user",
},
],
},
}
`;

View File

@ -0,0 +1,228 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Config should load multiple hosts 1`] = `
Config {
"CACHE": false,
"DEFAULTS": Object {
"HEADERS": Object {
"hello": "mars",
},
},
"ENDPOINT": "http://example.org",
"ENVIRONMENT": Object {},
"HOSTS": Array [
Object {
"GET /e2": "e2",
"GET /posts": "posts",
"defaults": Object {
"HEADERS": Object {
"hello": "world",
"world": "hello",
},
},
"endpoint": "http://example.com",
"host": "com",
},
Object {
"GET /e3": "e3",
"GET /posts": "posts",
"defaults": Object {
"HEADERS": Object {
"hello": "world",
"world": "bye",
},
},
"endpoint": "http://example.net",
"host": "net",
},
Object {
"GET /posts": "posts",
"endpoint": "http://example.info",
"host": "info",
},
],
"PLUGINS": Array [],
"VERSION": 1,
"configKeys": Array [
"VERSION",
"CACHE",
"ENDPOINT",
"PLUGINS",
"DEFAULTS",
"ENVIRONMENT",
"HOSTS",
],
"defaultConfigValues": Object {
"CACHE": false,
"DEFAULTS": Object {},
"ENDPOINT": "",
"ENVIRONMENT": Object {},
"HOSTS": Array [],
"PLUGINS": Array [],
"VERSION": 1,
},
"doc": Object {
"GET /e1": "e1",
"defaults": Object {
"HEADERS": Object {
"hello": "mars",
},
},
"endpoint": "http://example.org",
"hosts": Array [
Object {
"GET /e2": "e2",
"GET /posts": "posts",
"defaults": Object {
"HEADERS": Object {
"hello": "world",
"world": "hello",
},
},
"endpoint": "http://example.com",
"host": "com",
},
Object {
"GET /e3": "e3",
"GET /posts": "posts",
"defaults": Object {
"HEADERS": Object {
"hello": "world",
"world": "bye",
},
},
"endpoint": "http://example.net",
"host": "net",
},
Object {
"GET /posts": "posts",
"endpoint": "http://example.info",
"host": "info",
},
],
},
"requests": Array [
Object {
"ALIAS": "e1",
"ENDPOINT": "http://example.org",
"HEADERS": Object {
"hello": "mars",
},
"REQUEST": "GET /e1",
},
Object {
"ALIAS": "com:e2",
"ENDPOINT": "http://example.com",
"HEADERS": Object {
"hello": "world",
"world": "hello",
},
"REQUEST": "GET /e2",
},
Object {
"ALIAS": "com:posts",
"ENDPOINT": "http://example.com",
"HEADERS": Object {
"hello": "world",
"world": "hello",
},
"REQUEST": "GET /posts",
},
Object {
"ALIAS": "net:e3",
"ENDPOINT": "http://example.net",
"HEADERS": Object {
"hello": "world",
"world": "bye",
},
"REQUEST": "GET /e3",
},
Object {
"ALIAS": "net:posts",
"ENDPOINT": "http://example.net",
"HEADERS": Object {
"hello": "world",
"world": "bye",
},
"REQUEST": "GET /posts",
},
Object {
"ALIAS": "info:posts",
"ENDPOINT": "http://example.info",
"HEADERS": Object {
"hello": "mars",
},
"REQUEST": "GET /posts",
},
],
}
`;
exports[`Config should set up defaults for all requests 1`] = `
Config {
"CACHE": false,
"DEFAULTS": Object {
"HEADERS": Object {
"authentication": "hello",
},
},
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"ENVIRONMENT": Object {},
"HOSTS": Array [],
"PLUGINS": Array [],
"VERSION": 1,
"configKeys": Array [
"VERSION",
"CACHE",
"ENDPOINT",
"PLUGINS",
"DEFAULTS",
"ENVIRONMENT",
"HOSTS",
],
"defaultConfigValues": Object {
"CACHE": false,
"DEFAULTS": Object {},
"ENDPOINT": "",
"ENVIRONMENT": Object {},
"HOSTS": Array [],
"PLUGINS": Array [],
"VERSION": 1,
},
"doc": Object {
"GET /posts/1": "get-post",
"GET /user": Object {
"alias": "user",
"headers": Object {
"hello": "world",
},
},
"defaults": Object {
"HEADERS": Object {
"authentication": "hello",
},
},
"endpoint": "http://jsonplaceholder.typicode.com",
"version": 1,
},
"requests": Array [
Object {
"ALIAS": "get-post",
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
},
"REQUEST": "GET /posts/1",
},
Object {
"ALIAS": "user",
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
"hello": "world",
},
"REQUEST": "GET /user",
},
],
}
`;

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Request It should execute a request 1`] = `
exports[`Request should execute a request 1`] = `
Object {
"body": "{\\"hello\\": \\"world\\"}",
"request": Object {
@ -20,7 +20,7 @@ Object {
}
`;
exports[`Request It should execute a request 2`] = `
exports[`Request should execute a request 2`] = `
Object {
"body": "{\\"hello\\": \\"world\\"}",
"request": Object {
@ -36,7 +36,7 @@ Object {
}
`;
exports[`Request It should use modifiers 1`] = `
exports[`Request should use modifiers 1`] = `
Array [
Array [
Object {

View File

@ -2,23 +2,7 @@ const yaml = require('js-yaml');
const Beau = require('../beau');
describe(`Beau's config Loader.`, () => {
it('Should only load valid configuration keys', () => {
const doc = yaml.safeLoad(`
version: 1
endpoint: http://martianwabbit.com
cache: false
shouldntBeAdded: true
`);
const beau = new Beau(doc);
expect(beau.config.ENDPOINT).toBe(doc.endpoint);
expect(beau.config.CACHE).toBe(doc.cache);
expect(beau.config.VERSION).toBe(doc.version);
expect(beau.config.shouldntBeAdded).toBeUndefined();
});
it('should set up defaults for all requests', () => {
it('should create a request list', () => {
const doc = yaml.safeLoad(`
version: 1
endpoint: 'http://jsonplaceholder.typicode.com'
@ -36,9 +20,7 @@ describe(`Beau's config Loader.`, () => {
const beau = new Beau(doc);
expect(beau.requests).toBeDefined();
expect(beau).toMatchSnapshot();
beau.requests.list.forEach(r => {
expect(r.HEADERS.authentication).toMatch('hello');
});
});
});

View File

@ -0,0 +1,158 @@
const yaml = require('js-yaml');
const Config = require('../config');
describe('Config', () => {
it('should load valid config keys', () => {
const doc = yaml.safeLoad(`
version: 1
endpoint: http://martianwabbit.com
cache: false
shouldntBeAdded: true
`);
const config = new Config(doc);
expect(config.ENDPOINT).toBe(doc.endpoint);
expect(config.CACHE).toBe(doc.cache);
expect(config.VERSION).toBe(doc.version);
expect(config.shouldntBeAdded).toBeUndefined();
});
it('should load requests', () => {
const doc = yaml.safeLoad(`
endpoint: http://example.com
GET /profile: get-profile
GET /posts: get-posts
GET /posts/1: get-post
GET /user:
alias: user
headers:
hello: world
`);
const config = new Config(doc);
expect(Object.keys(config.requests).length).toBe(4);
});
it('should set up defaults for all requests', () => {
const doc = yaml.safeLoad(`
version: 1
endpoint: 'http://jsonplaceholder.typicode.com'
defaults:
HEADERS:
authentication: hello
GET /posts/1: get-post
GET /user:
alias: user
headers:
hello: world
`);
const config = new Config(doc);
expect(config).toMatchSnapshot();
Object.values(config.requests).forEach(r => {
expect(r.HEADERS.authentication).toMatch('hello');
});
});
it('should load multiple hosts', () => {
const doc = yaml.safeLoad(`
endpoint: http://example.org
defaults:
HEADERS:
hello: mars
GET /e1: e1
hosts:
- host: com
endpoint: http://example.com
defaults:
HEADERS:
hello: world
world: hello
GET /e2: e2
GET /posts: posts
- host: net
endpoint: http://example.net
defaults:
HEADERS:
hello: world
world: bye
GET /e3: e3
GET /posts: posts
- host: info
endpoint: http://example.info
GET /posts: posts
`);
let config = new Config(doc);
expect(config).toMatchSnapshot();
});
it('should namespace all aliases within an host', () => {
const doc = yaml.safeLoad(`
hosts:
- host: test1
endpoint: http://example.com
GET /posts: posts
- host: test2
endpoint: http://example.net
GET /posts: posts
`);
let config = new Config(doc);
expect(config.requests[0].ALIAS).toBe('test1:posts');
expect(config.requests[1].ALIAS).toBe('test2:posts');
});
it(`should throw if host doesn't have a host key`, () => {
const doc = yaml.safeLoad(`
hosts:
- endpoint: http://example.com
GET /posts: posts
- host: test2
endpoint: http://example.net
GET /posts: posts
`);
expect(() => new Config(doc)).toThrow();
});
it(`should merge host settings with global settings`, () => {
const doc = yaml.safeLoad(`
defaults:
headers:
hello: 1
hosts:
- host: test
endpoint: http://example.net
GET /posts: posts
- host: test2
endpoint: http://example.org
defaults:
headers: false
GET /posts: posts
`);
let config = new Config(doc);
expect(config.requests[0].HEADERS.hello).toBe(1);
});
});

View File

@ -4,13 +4,14 @@ const RequestList = require('../requestList');
const requestPromiseNativeMock = require('request-promise-native');
describe('Request', () => {
let req;
let cache;
let validRequestConfig;
let invalidRequestConfig;
let request;
let requestWithoutDependencies;
beforeEach(() => {
req = {
validRequestConfig = {
request: 'POST /user',
endpoint: 'http://martianwabbit.com',
alias: 'update',
@ -25,11 +26,16 @@ describe('Request', () => {
}
};
invalidRequestConfig = {
request: `POST /session`,
endpoint: 'http://martianwabbit.com'
};
cache = new RequestCache();
cache.add('$session', { token: 'abc123' });
cache.add('$profile', { UserId: 14 });
request = new Request(req);
request = new Request(validRequestConfig);
requestWithoutDependencies = new Request({
endpoint: 'http://martianwabbit.com',
request: 'GET /user',
@ -39,33 +45,37 @@ describe('Request', () => {
requestPromiseNativeMock.fail = false;
});
test('It should load up the given request', () => {
it('should load up the given request', () => {
expect(request.VERB).toBe('POST');
expect(request.ENDPOINT).toBe(req.endpoint + '/user');
expect(request.ENDPOINT).toBe(validRequestConfig.endpoint + '/user');
expect(request.HEADERS).toBeDefined();
expect(request.PAYLOAD).toBeDefined();
expect(request.PARAMS).toBeDefined();
});
test('It should list all of its dependencies', () => {
it('should throw if a given request is invalid', () => {
expect(() => new Request(invalidRequestConfig)).toThrow();
});
it('should list all of its dependencies', () => {
expect(request.DEPENDENCIES.size).toBe(2);
expect(request.DEPENDENCIES).toContain('session');
expect(request.DEPENDENCIES).toContain('profile');
});
test('It should execute a request', async () => {
it('should execute a request', async () => {
await expect(request.exec([], cache)).resolves.toMatchSnapshot();
await expect(
requestWithoutDependencies.exec()
).resolves.toMatchSnapshot();
});
test('It should throw if the request fails', async () => {
it('should throw if the request fails', async () => {
requestPromiseNativeMock.fail = true;
await expect(requestWithoutDependencies.exec()).rejects.toThrow(Error);
});
test('It should use modifiers', async () => {
it('should use modifiers', async () => {
const preRequest = jest.fn();
const withPreRequest = [{ preRequest }];

View File

@ -1,15 +1,28 @@
const Config = require('../config');
const RequestList = require('../requestList');
const requestPromiseNativeMock = require('request-promise-native');
describe('RequestList', () => {
const endpoint = 'http://martianwabbit.com';
let env = {
environmental: true
};
const doc = {
'POST /session': null,
'Not a Request': null,
ENDPOINT: endpoint,
ENVIRONMENT: env,
PLUGINS: [
{
'beau-jwt': {
data: {
secret: 'shhh.',
userId: 412
}
}
},
'beau-document'
],
'GET /post': { alias: 'get-posts' },
'POST /user': {
alias: 'user',
@ -23,29 +36,13 @@ describe('RequestList', () => {
let requests;
beforeEach(() => {
requestPromiseNativeMock.fail = false;
requests = new RequestList(doc, {
ENDPOINT: endpoint,
ENVIRONMENT: env,
PLUGINS: [
{
'beau-jwt': {
data: {
secret: 'shhh.',
userId: 412
}
}
},
'beau-document'
]
});
let config = new Config(doc);
requests = new RequestList(config.requests, config);
});
it('should load valid requests', () => {
const request = requests.list[0];
expect(requests.list.length).toBe(3);
expect(request.VERB).toBe('POST');
expect(request.ENDPOINT).toBe(endpoint + '/session');
expect(requests.list.length).toBe(2);
});
it('should fetch dependencies', () => {
@ -64,7 +61,7 @@ describe('RequestList', () => {
it('should fail if the request fails', async () => {
requestPromiseNativeMock.fail = true;
await expect(requests.execByAlias('user')).rejects.toThrow(Error);
await expect(requests.execByAlias('user')).rejects.toThrow();
});
it('should return a cached result if available', async () => {
@ -74,6 +71,18 @@ describe('RequestList', () => {
});
it('should fail if the alias is not found', async () => {
await expect(requests.execByAlias('notAnAlias')).rejects.toThrow(Error);
await expect(requests.execByAlias('notAnAlias')).rejects.toThrow();
});
it(`should fail if a given request doesn't have an alias`, () => {
let config = new Config({
'GET /hello': {
headers: {
hello: 1
}
}
});
expect(() => new RequestList(config.requests, config)).toThrow();
});
});

View File

@ -1,54 +1,11 @@
const deepMerge = require('deepmerge');
const RequestList = require('./requestList');
const requestRegex = require('./shared').requestRegex;
const Config = require('./config');
class Beau {
constructor(doc) {
this.defaults = {
VERSION: 1,
CACHE: false,
ENDPOINT: '',
PLUGINS: [],
DEFAULTS: [],
ENVIRONMENT: {}
};
this.config = new Config(doc);
this.configKeys = Object.keys(this.defaults);
this.config = this.loadConfig(doc);
this.requests = this.getRequests(doc);
this.requests = new RequestList(this.requests, this.config);
}
getRequests(doc) {
let requests = Object.keys(doc).filter(key => {
return requestRegex.test(key);
});
let results = {};
requests.forEach(r => {
if (typeof doc[r] === 'string') {
results[r] = {
ALIAS: doc[r]
};
} else {
results[r] = doc[r];
}
results[r] = deepMerge(this.config.DEFAULTS, results[r]);
});
return results;
}
loadConfig(doc) {
let result = this.defaults;
Object.keys(doc)
.filter(k => this.configKeys.indexOf(k.toUpperCase()) > -1)
.forEach(k => (result[k.toUpperCase()] = doc[k]));
return result;
this.requests = new RequestList(this.config.requests, this.config);
}
}

92
src/config.js Normal file
View File

@ -0,0 +1,92 @@
const deepMerge = require('deepmerge');
const { requestRegex, UpperCaseKeys } = require('./shared');
class Config {
constructor(doc) {
this.defaultConfigValues = {
VERSION: 1,
CACHE: false,
ENDPOINT: '',
PLUGINS: [],
DEFAULTS: {},
ENVIRONMENT: {},
HOSTS: []
};
this.configKeys = Object.keys(this.defaultConfigValues);
this.doc = doc;
let config = this.loadConfig(doc);
this.configKeys.forEach(k => {
this[k] = config[k] || this.defaultConfigValues[k];
});
this.requests = [];
this.loadRequests(doc, {
DEFAULTS: this.DEFAULTS,
ENDPOINT: this.ENDPOINT
});
this.loadHosts(this.HOSTS, config);
}
loadHosts(hosts, rootConfig) {
hosts.forEach(host => {
if (typeof host.host === 'undefined') {
throw new Error(`Host doesn't indicate it's host name.`);
}
let config = deepMerge(
this.defaultConfigValues,
this.loadConfig(host)
);
config.DEFAULTS = deepMerge(rootConfig.DEFAULTS, config.DEFAULTS);
this.loadRequests(host, {
DEFAULTS: config.DEFAULTS,
ENDPOINT: config.ENDPOINT,
NAMESPACE: host.host
});
});
}
loadRequests(host, settings) {
let requests = Object.keys(host)
.filter(key => requestRegex.test(key))
.map(key => {
let requestDefinitionIsString = typeof host[key] === 'string';
let originalRequest = requestDefinitionIsString
? { ALIAS: host[key] }
: deepMerge.all([host[key]]);
let request = UpperCaseKeys(originalRequest);
if (settings.NAMESPACE) {
request.ALIAS = `${settings.NAMESPACE}:${request.ALIAS}`;
}
request.REQUEST = key;
request.ENDPOINT = settings.ENDPOINT;
let defaults = UpperCaseKeys(settings.DEFAULTS);
return deepMerge(defaults, request);
});
this.requests = this.requests.concat(requests);
}
loadConfig(host) {
let config = {};
Object.keys(host)
.filter(k => this.configKeys.includes(k.toUpperCase()))
.forEach(k => (config[k.toUpperCase()] = host[k]));
return config;
}
}
module.exports = Config;

View File

@ -1,24 +1,30 @@
const request = require('request-promise-native');
const { httpVerbs, requestRegex, replacementRegex } = require('./shared');
const {
httpVerbs,
requestRegex,
replacementRegex,
UpperCaseKeys
} = require('./shared');
const RequestList = require('./requestList');
const RequestCache = require('./requestCache');
class Request {
constructor(req) {
let config = {};
this.originalRequest = req;
Object.keys(req).forEach(k => (config[k.toUpperCase()] = req[k]));
const {
REQUEST,
ALIAS,
PAYLOAD,
ENDPOINT,
PARAMS,
HEADERS,
DOCUMENTATION
} = config;
HEADERS
} = UpperCaseKeys(req);
if (!ALIAS) {
throw new Error(`${REQUEST} is missing an alias.`);
}
const { verb, path } = this.parseRequest(REQUEST);
this.VERB = verb;
@ -29,11 +35,6 @@ class Request {
this.PARAMS = PARAMS;
this.ALIAS = ALIAS;
this.DOCUMENTATION = DOCUMENTATION;
if (typeof this.ALIAS === 'undefined') {
console.info(`${REQUEST} is missing an alias.`);
}
this.DEPENDENCIES = this.findDependencies(req);
}

View File

@ -4,11 +4,12 @@ const httpVerbs = require('./shared').httpVerbs;
const requireg = require('requireg');
class RequestList {
constructor(doc = {}, config = {}) {
constructor(requests = [], config = {}) {
this.config = config;
this.requests = requests;
this.modifiers = this.loadPlugins();
this.list = this.loadRequests(doc);
this.list = this.loadRequests();
this.cache = new RequestCache();
this.cache.add(`$env`, this.config.ENVIRONMENT);
@ -32,7 +33,9 @@ class RequestList {
return this.applyPostResponseModifiers(response);
} catch (reason) {
throw new Error(
`Request: ${request.VERB} ${request.ENDPOINT} FAILED. \n${reason}`
`Request: ${request.VERB} ${
request.ENDPOINT
} FAILED. \n${reason}`
);
}
}
@ -44,19 +47,18 @@ class RequestList {
return this.cache;
}
loadRequests(doc) {
const requests = Object.keys(doc).filter(key => {
const verb = key.split(' ')[0].toUpperCase();
return httpVerbs.indexOf(verb) > -1;
loadRequests() {
let requests = [];
this.requests.forEach(request => {
try {
let r = new Request(request);
requests.push(r);
} catch (e) {
throw new Error(`${request.request} was ignored: ${e}`);
}
});
return requests.map(request => {
doc[request] = doc[request] || {};
doc[request].ENDPOINT = this.config.ENDPOINT;
doc[request].request = request;
return new Request(doc[request]);
});
return requests;
}
loadPlugins() {

View File

@ -11,10 +11,17 @@ const httpVerbs = [
];
const requestRegex = new RegExp(`(${httpVerbs.join('|')})\\s(.*)`, 'i');
const replacementRegex = /\$([a-zA-Z\.\d\-\_\/\\]*)/g;
const replacementRegex = /\$([a-zA-Z\.\d\-\_\/\\\:]*)/g;
const UpperCaseKeys = function(obj) {
let result = {};
Object.keys(obj).forEach(k => (result[k.toUpperCase()] = obj[k]));
return result;
};
module.exports = {
httpVerbs,
requestRegex,
replacementRegex
replacementRegex,
UpperCaseKeys
};