diff --git a/.gitignore b/.gitignore index 17ce749..e36f880 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ yarn-error.log* web/dist api/src/static/index.js api/src/static/static +secrets.json # Runtime data pids diff --git a/api/package-lock.json b/api/package-lock.json index f1c6d4d..28c070b 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -9,7 +9,7 @@ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "requires": { - "mime-types": "2.1.18", + "mime-types": "~2.1.18", "negotiator": "0.6.1" } }, @@ -18,10 +18,10 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } }, "any-promise": { @@ -44,7 +44,7 @@ "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "requires": { - "lodash": "4.17.10" + "lodash": "^4.17.10" } }, "asynckit": { @@ -76,7 +76,7 @@ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "bluebird": { @@ -99,8 +99,8 @@ "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.0.tgz", "integrity": "sha512-cVbmz0rAnsK3jPcQAlK4IDUUPaYAe4yl7MAfiKftHAcrW/azF1yikn2wE/8VAcC3yWtXi3lvXwsF1akK27Vo7w==", "requires": { - "mime-types": "2.1.18", - "ylru": "1.2.1" + "mime-types": "^2.1.18", + "ylru": "^1.2.0" } }, "caseless": { @@ -118,10 +118,10 @@ "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.0.0.tgz", "integrity": "sha512-9ZIcixguuuKIptnY8yemEOuhb71L/lLf+Rl5JfJEUiDNJk0e02MBt7BPxR2GEh5mw8dPthQYR4jPI/BnS1MQgw==", "requires": { - "inflation": "2.0.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "1.6.16" + "inflation": "^2.0.0", + "qs": "^6.5.2", + "raw-body": "^2.3.3", + "type-is": "^1.6.16" } }, "combined-stream": { @@ -129,7 +129,7 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "content-disposition": { @@ -147,8 +147,8 @@ "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.1.tgz", "integrity": "sha1-fIphX1SBxhq58WyDNzG8uPZjuZs=", "requires": { - "depd": "1.1.2", - "keygrip": "1.0.2" + "depd": "~1.1.1", + "keygrip": "~1.0.2" } }, "copy-to": { @@ -166,7 +166,7 @@ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "debug": { @@ -208,7 +208,7 @@ "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0" } }, "ee-first": { @@ -256,9 +256,9 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "requires": { - "asynckit": "0.4.0", + "asynckit": "^0.4.0", "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "mime-types": "^2.1.12" } }, "fresh": { @@ -271,7 +271,7 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "har-schema": { @@ -284,8 +284,8 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" + "ajv": "^5.1.0", + "har-schema": "^2.0.0" } }, "http-assert": { @@ -293,8 +293,8 @@ "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.3.0.tgz", "integrity": "sha1-oxpc+IyHPsu1eWkH1NbxMujAHko=", "requires": { - "deep-equal": "1.0.1", - "http-errors": "1.6.3" + "deep-equal": "~1.0.1", + "http-errors": "~1.6.1" } }, "http-errors": { @@ -302,10 +302,10 @@ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "requires": { - "depd": "1.1.2", + "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", - "statuses": "1.5.0" + "statuses": ">= 1.4.0 < 2" } }, "http-signature": { @@ -313,9 +313,9 @@ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.2" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "iconv-lite": { @@ -323,7 +323,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": ">= 2.1.2 < 3" } }, "inflation": { @@ -403,30 +403,30 @@ "resolved": "https://registry.npmjs.org/koa/-/koa-2.5.2.tgz", "integrity": "sha512-MoVGWre9g3p35pCqXNhOT/a4trwK5CGvalIoPi7qOA2RCZaep3GCsa/G/tD9QMjQI7bmVWn3XF3SOau8RkPh6w==", "requires": { - "accepts": "1.3.5", - "cache-content-type": "1.0.0", - "content-disposition": "0.5.2", - "content-type": "1.0.4", - "cookies": "0.7.1", - "debug": "3.1.0", - "delegates": "1.0.0", - "depd": "1.1.2", - "destroy": "1.0.4", - "error-inject": "1.0.0", - "escape-html": "1.0.3", - "fresh": "0.5.2", - "http-assert": "1.3.0", - "http-errors": "1.6.3", - "is-generator-function": "1.0.7", - "koa-compose": "4.1.0", - "koa-convert": "1.2.0", - "koa-is-json": "1.0.0", - "on-finished": "2.3.0", - "only": "0.0.2", - "parseurl": "1.3.2", - "statuses": "1.5.0", - "type-is": "1.6.16", - "vary": "1.1.2" + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.7.1", + "debug": "^3.1.0", + "delegates": "^1.0.0", + "depd": "^1.1.2", + "destroy": "^1.0.4", + "error-inject": "^1.0.0", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^1.2.0", + "koa-is-json": "^1.0.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" } }, "koa-bodyparser": { @@ -434,8 +434,8 @@ "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-4.2.1.tgz", "integrity": "sha512-UIjPAlMZfNYDDe+4zBaOAUKYqkwAGcIU6r2ARf1UOXPAlfennQys5IiShaVeNf7KkVBlf88f2LeLvBFvKylttw==", "requires": { - "co-body": "6.0.0", - "copy-to": "2.0.1" + "co-body": "^6.0.0", + "copy-to": "^2.0.1" } }, "koa-compose": { @@ -448,8 +448,8 @@ "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", "requires": { - "co": "4.6.0", - "koa-compose": "3.2.1" + "co": "^4.6.0", + "koa-compose": "^3.0.0" }, "dependencies": { "koa-compose": { @@ -457,7 +457,7 @@ "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", "requires": { - "any-promise": "1.3.0" + "any-promise": "^1.1.0" } } } @@ -472,7 +472,7 @@ "resolved": "https://registry.npmjs.org/koa-morgan/-/koa-morgan-1.0.1.tgz", "integrity": "sha1-CAUuDODYOdPEMXi5CluzQkvvH5k=", "requires": { - "morgan": "1.9.0" + "morgan": "^1.6.1" } }, "koa-mount": { @@ -480,8 +480,8 @@ "resolved": "https://registry.npmjs.org/koa-mount/-/koa-mount-3.0.0.tgz", "integrity": "sha1-CMqzuD0xRC7Yt+dcVLGr65IuwZc=", "requires": { - "debug": "2.6.9", - "koa-compose": "3.2.1" + "debug": "^2.6.1", + "koa-compose": "^3.2.1" }, "dependencies": { "debug": { @@ -497,7 +497,7 @@ "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", "requires": { - "any-promise": "1.3.0" + "any-promise": "^1.1.0" } } } @@ -512,12 +512,12 @@ "resolved": "https://registry.npmjs.org/koa-router/-/koa-router-7.4.0.tgz", "integrity": "sha512-IWhaDXeAnfDBEpWS6hkGdZ1ablgr6Q6pGdXCyK38RbzuH4LkUOpPqPw+3f8l8aTDrQmBQ7xJc0bs2yV4dzcO+g==", "requires": { - "debug": "3.1.0", - "http-errors": "1.6.3", - "koa-compose": "3.2.1", - "methods": "1.1.2", - "path-to-regexp": "1.7.0", - "urijs": "1.19.1" + "debug": "^3.1.0", + "http-errors": "^1.3.1", + "koa-compose": "^3.0.0", + "methods": "^1.0.1", + "path-to-regexp": "^1.1.1", + "urijs": "^1.19.0" }, "dependencies": { "koa-compose": { @@ -525,7 +525,7 @@ "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", "requires": { - "any-promise": "1.3.0" + "any-promise": "^1.1.0" } } } @@ -535,10 +535,10 @@ "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-4.1.3.tgz", "integrity": "sha512-3UetMBdaXSiw24qM2Mx5mKmxLKw5ZTPRjACjfhK6Haca55RKm9hr/uHDrkrxhSl5/S1CKI/RivZVIopiatZuTA==", "requires": { - "debug": "2.6.9", - "http-errors": "1.6.3", - "mz": "2.7.0", - "resolve-path": "1.4.0" + "debug": "^2.6.3", + "http-errors": "^1.6.1", + "mz": "^2.6.0", + "resolve-path": "^1.4.0" }, "dependencies": { "debug": { @@ -556,8 +556,8 @@ "resolved": "https://registry.npmjs.org/koa-static-server/-/koa-static-server-1.3.4.tgz", "integrity": "sha512-YBwszbVim1r0RLbc4nWAi/rsfhwy+iQEP82Hg0OAGlI/tc6phpbMask8qndURuq7OobTkTQGmtLdt12Fq7Ojxg==", "requires": { - "koa-send": "4.1.3", - "upath": "1.1.0" + "koa-send": "~4.1.0", + "upath": "^1.0.2" } }, "lodash": { @@ -590,7 +590,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "requires": { - "mime-db": "1.33.0" + "mime-db": "~1.33.0" } }, "mongodb": { @@ -606,9 +606,9 @@ "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.1.0.tgz", "integrity": "sha512-qRjG62Fu//CZhkgn0jA/k8jh5MhACIq8cOJUryH6sck87pgt+C222MSD02tsCq5zNo/B6ZFHtNodZ2qpf8E86g==", "requires": { - "bson": "1.0.9", - "require_optional": "1.0.1", - "saslprep": "1.0.0" + "bson": "~1.0.4", + "require_optional": "^1.0.1", + "saslprep": "^1.0.0" } }, "mongoose": { @@ -617,7 +617,7 @@ "integrity": "sha512-LQM/6zHV9944+attF4Blw22QClU2s3M68w49WF4tJKQI2pkC9f/WMTL2FGndsEHq5m5KQ0roE9pX8I8LiTDGeg==", "requires": { "async": "2.6.1", - "bson": "1.0.9", + "bson": "~1.0.5", "kareem": "2.2.1", "lodash.get": "4.4.2", "mongodb": "3.1.1", @@ -640,11 +640,11 @@ "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", "integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=", "requires": { - "basic-auth": "2.0.0", + "basic-auth": "~2.0.0", "debug": "2.6.9", - "depd": "1.1.2", - "on-finished": "2.3.0", - "on-headers": "1.0.1" + "depd": "~1.1.1", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" }, "dependencies": { "debug": { @@ -698,9 +698,17 @@ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "requires": { - "any-promise": "1.3.0", - "object-assign": "4.1.1", - "thenify-all": "1.6.0" + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "nano-cache": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/nano-cache/-/nano-cache-1.1.2.tgz", + "integrity": "sha512-tqs6EYyIq8oCQMc1L+QSUdZYOk/STwWCmIqyGO6cXI4QhejSb586WPBgO3nplzD5L3+aJCAITMVtMTFFLAdb7w==", + "requires": { + "extend": "~3.0.0" } }, "negotiator": { @@ -790,26 +798,26 @@ "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.7.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.2", - "safe-buffer": "5.1.1", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.6.0", - "uuid": "3.3.2" + "aws-sign2": "~0.7.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.3.1", + "har-validator": "~5.0.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" } }, "request-promise": { @@ -817,10 +825,19 @@ "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz", "integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=", "requires": { - "bluebird": "3.5.0", + "bluebird": "^3.5.0", "request-promise-core": "1.1.1", - "stealthy-require": "1.1.1", - "tough-cookie": "2.3.4" + "stealthy-require": "^1.1.0", + "tough-cookie": ">=2.3.3" + } + }, + "request-promise-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/request-promise-cache/-/request-promise-cache-2.0.0.tgz", + "integrity": "sha512-hiGZuJZXXcTvC1/79fk9PI70RCwBrCoykTiA1S7WH0f+Tq2Xhv/qODaxXKDtl5Ka04Zyiz+Ql8pEWuTE2E9Lxg==", + "requires": { + "nano-cache": "^1.1.2", + "request": "^2.87.0" } }, "request-promise-core": { @@ -828,7 +845,7 @@ "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", "requires": { - "lodash": "4.17.10" + "lodash": "^4.13.1" } }, "require_optional": { @@ -836,8 +853,8 @@ "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", "requires": { - "resolve-from": "2.0.0", - "semver": "5.5.0" + "resolve-from": "^2.0.0", + "semver": "^5.1.0" } }, "resolve-from": { @@ -850,7 +867,7 @@ "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=", "requires": { - "http-errors": "1.6.3", + "http-errors": "~1.6.2", "path-is-absolute": "1.0.1" } }, @@ -890,15 +907,15 @@ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.2", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "safer-buffer": "2.1.2", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" } }, "statuses": { @@ -916,7 +933,7 @@ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", "requires": { - "any-promise": "1.3.0" + "any-promise": "^1.0.0" } }, "thenify-all": { @@ -924,7 +941,7 @@ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", "requires": { - "thenify": "3.3.0" + "thenify": ">= 3.1.0 < 4" } }, "tough-cookie": { @@ -932,7 +949,7 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "requires": { - "punycode": "1.4.1" + "punycode": "^1.4.1" } }, "tunnel-agent": { @@ -940,7 +957,7 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { @@ -955,7 +972,7 @@ "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.18" + "mime-types": "~2.1.18" } }, "unpipe": { @@ -988,9 +1005,9 @@ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" } }, "ylru": { diff --git a/api/package.json b/api/package.json index a0dd56d..3503583 100644 --- a/api/package.json +++ b/api/package.json @@ -26,6 +26,7 @@ "koa-static-server": "^1.3.4", "mongoose": "^5.2.3", "request": "^2.87.0", - "request-promise": "^4.2.2" + "request-promise": "^4.2.2", + "request-promise-cache": "^2.0.0" } } diff --git a/api/src/api/products/controller.js b/api/src/api/products/controller.js index 1dce8c2..e73c83a 100644 --- a/api/src/api/products/controller.js +++ b/api/src/api/products/controller.js @@ -1,26 +1,41 @@ const Product = require('./model') -const request = require('request-promise') +const request = require('request-promise-cache') +const config = require('../../configuration') +const apiKey = config.get('GOOGLE_BOOKS_API_KEY') -exports.getProductDetails = async function(googleId) { - const result = await request.get( - `https://www.googleapis.com/books/v1/volumes/${googleId}` - ) +const getProductDetails = async function(googleId) { + const url = + `https://www.googleapis.com/books/v1/volumes/${googleId}?key=${apiKey}` + const result = await request({ + url: url, + cacheKey: url, + cacheTTL: 3600 * 24, + cacheLimit: 24, + resolveWithFullResponse: false + }) return JSON.parse(result) } -exports.getProducts = async function() { - const products = await Product.find() - const results = await Promise.all(products.map(async (product) => { - try { - const details = await this.getProductDetails(product.googleId) - return { - price: product.price, - info: details.volumeInfo, - } - } catch (error) { - console.log(error) +const populateDetails = async function(product) { + try { + const details = await getProductDetails(product.googleId) + return { + _id: product._id, + price: product.price, + info: details.volumeInfo, } - })) + } catch (error) { + console.log(error) + } +} +exports.getProducts = async function() { + const products = await Product.find() + const results = await Promise.all(products.map(populateDetails)) return results } + +exports.getProduct = async function(id) { + const product = await Product.findById(id) + return populateDetails(product); +} diff --git a/api/src/api/products/routes.js b/api/src/api/products/routes.js index 2f2039d..e792685 100644 --- a/api/src/api/products/routes.js +++ b/api/src/api/products/routes.js @@ -4,7 +4,13 @@ exports.get = async function(ctx) { ctx.body = await controller.getProducts() } +exports.getWithId = async function(ctx) { + const id = ctx.params.id + ctx.body = await controller.getProduct(id) +} + exports.routes = function(router) { router.get('/', this.get) + router.get('/:id', this.getWithId) return router } diff --git a/api/src/configuration/index.js b/api/src/configuration/index.js index 0c5bb5f..9cfc8e3 100644 --- a/api/src/configuration/index.js +++ b/api/src/configuration/index.js @@ -1,5 +1,10 @@ const config = require('../config') +const secrets = require('../../../secrets.json') exports.get = key => { - return process.env[key] || config.env[key] + return process.env[key] || secrets.env[key] || config.env[key] +} + +exports.secret = key => { + return process.env[key] || secrets.env[key] } diff --git a/products.json b/products.json index 4f31327..f9212a0 100644 --- a/products.json +++ b/products.json @@ -2,7 +2,7 @@ "google_id": "j2uGDAAAQBAJ", "price": 9.50 }, { - "google_id": "5QRZ4z6A1WwC", + "google_id": "yl4dILkcqm4C", "price": 12.99 }, { "google_id": "1Rb0Lv8bOFAC", @@ -11,7 +11,7 @@ "google_id": "os7Er28Nw_kC", "price": 3.45 }, { - "google_id": "i_SorqUvsOEC", + "google_id": "3Wf_ffkFQmgC", "price": 18.99 }, { "google_id": "iaD7DAAAQBAJ", @@ -20,6 +20,6 @@ "google_id": "7Z_eDQAAQBAJ", "price": 8.00 }, { - "google_id": "LkUsDwAAQBAJ", + "google_id": "v3hSnQAACAAJ", "price": 4.65 }] diff --git a/web/src/api/products.js b/web/src/api/products.js index 5a5385c..ddc95a6 100644 --- a/web/src/api/products.js +++ b/web/src/api/products.js @@ -2,6 +2,10 @@ import axios from 'axios' export default { async get() { - return axios.get('/api/products') + return axios.get('/api/products').then(r => r.data) + }, + + async getWithId(id) { + return axios.get(`/api/products/${id}`).then(r => r.data) } } diff --git a/web/src/components/card-form.vue b/web/src/components/card-form.vue new file mode 100644 index 0000000..550b8b4 --- /dev/null +++ b/web/src/components/card-form.vue @@ -0,0 +1,32 @@ + diff --git a/web/src/components/product.vue b/web/src/components/product.vue index 18e419d..d6fb3ce 100644 --- a/web/src/components/product.vue +++ b/web/src/components/product.vue @@ -1,8 +1,24 @@ @@ -13,6 +29,11 @@ export default { type: Object, required: true } + }, + methods: { + orderUrl(product) { + return `/checkout/${product._id}` + } } } diff --git a/web/src/pages/checkout.vue b/web/src/pages/checkout.vue new file mode 100644 index 0000000..dc7ce31 --- /dev/null +++ b/web/src/pages/checkout.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/web/src/pages/products.vue b/web/src/pages/products.vue index e7965aa..1aa1d00 100644 --- a/web/src/pages/products.vue +++ b/web/src/pages/products.vue @@ -12,9 +12,11 @@ -
-
-
+
+
+
+
@@ -37,6 +39,7 @@ export default { }, async mounted() { this.products = await Products.get() + console.log(this.products) } } diff --git a/web/src/router/index.js b/web/src/router/index.js index 2c9bc0e..9278c65 100644 --- a/web/src/router/index.js +++ b/web/src/router/index.js @@ -2,6 +2,7 @@ import Vue from 'vue' import Router from 'vue-router' import Home from '@/pages/home' import Products from '@/pages/products' +import Checkout from '@/pages/checkout' Vue.use(Router) @@ -15,5 +16,9 @@ export default new Router({ path: '/products', name: 'Products', component: Products + }, { + path: '/checkout/:id', + name: 'Checkout', + component: Checkout }] }) diff --git a/web/src/styles/configure.scss b/web/src/styles/configure.scss index 7d99088..e8d6e8f 100644 --- a/web/src/styles/configure.scss +++ b/web/src/styles/configure.scss @@ -12,9 +12,9 @@ $colors: ( "danger": ($danger, $danger-invert) ); -$link: $primary; -$link-invert: $primary-invert; -$link-focus-border: $primary; +$link: $info; +$link-invert: $info-invert; +$link-focus-border: $info; @import "~bulma";