diff --git a/README.md b/README.md index 3c2b6cc0dc..a61cf39dd5 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,12 @@ Notes * Discord: https://discord.gg/opendota * Strongly recommended for active developers! We move fast and it's helpful to be up to speed with everything that's happening. +HTTPS +--- +Service Worker development requires HTTPS, and if you're developing on a remote host, this may be a challenge +(otherwise, localhost is a trusted origin). `https-docker-compose.yml` sets up HTTPS proxy via Nginx and LetsEncrypt. +You must set `VIRTUAL_HOST` `LETSENCRYPT_HOST` (which should be the same value) and `LETSENCRYPT_EMAIL`. + Resources ---- * New to React/Redux? Read these articles on React and watch video tutorials by Redux creator Dan Abramov. diff --git a/https-docker-compose.yml b/https-docker-compose.yml new file mode 100644 index 0000000000..46af7f6c91 --- /dev/null +++ b/https-docker-compose.yml @@ -0,0 +1,49 @@ +# You don't usually need to edit this file. +# If it does not fit your personal use case, docker-compose.override.yml is a preferred way to go. + +version: '2' +services: + ui: + build: + context: . + image: odota/web + container_name: odota-web + expose: + - "8080" + ports: + - "8080:8080" + volumes: + - .:/usr/src + environment: + - PORT=8080 + - VIRTUAL_PORT=8080 + - VIRTUAL_HOST + - LETSENCRYPT_HOST + - LETSENCRYPT_EMAIL + networks: + - odota + nginx-proxy: + image: jwilder/nginx-proxy + container_name: odota-nginx-proxy + ports: + - "80:80" + - "443:443" + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - /etc/nginx/vhost.d + - /usr/share/nginx/html + - /etc/nginx/certs + networks: + - odota + letsencrypt-nginx: + image: jrcs/letsencrypt-nginx-proxy-companion + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + volumes_from: + - "nginx-proxy" + networks: + - odota + container_name: odota-nginx-letsencrypt +networks: + odota: + driver: bridge diff --git a/package-lock.json b/package-lock.json index 1b4382f6bf..83f9d54836 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,11 +4,154 @@ "lockfileVersion": 1, "requires": true, "dependencies": { +<<<<<<< HEAD + "@firebase/app": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.2.0.tgz", + "integrity": "sha512-hu+HGRXER3URCb8sZdd4f3QzvVWfuKvJoqd1mlEx9vWQ0fMpFqMeYgOaO7+x7PkNzamMHetItfws5TK9pmnStQ==", + "requires": { + "@firebase/app-types": "0.2.0", + "@firebase/util": "0.1.11", + "tslib": "1.9.0" + } + }, + "@firebase/app-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.2.0.tgz", + "integrity": "sha512-0hTbuFmTr5sBvn9r2w5nk9FeMkuscj+ClPUBimtOkOnoLvIWRICILRiPTV1CX+7Th4EJ7y17UWx8jieY0f8GtA==" + }, + "@firebase/auth": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.4.2.tgz", + "integrity": "sha512-gMEKuKDdO2oB9c2zmj6NlFOY1ynzummXuUWz6cFgUdNd/Pw5ZpkOlGzS7yxZ7NI0dZXV/xccamN7CN9/vol+cA==", + "requires": { + "@firebase/auth-types": "0.2.1" + } + }, + "@firebase/auth-types": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.2.1.tgz", + "integrity": "sha512-zjObje4RYJ7RJHt1z8A6xGnfLw/5RwUvk7AHrYwS4N3Mq17j/ZumBvYlAQz4k8sNe9GFDmjmHa30ezFWOglLEQ==" + }, + "@firebase/database": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.2.2.tgz", + "integrity": "sha512-iTNEN33D3V0hAG2hdx+guFBXaN4hcFS2k2EGp/bzNviAG7n2AotMscdbkS6xDS2e3Uk2/D3lfibHQO4zgJ3LIg==", + "requires": { + "@firebase/database-types": "0.2.1", + "@firebase/logger": "0.1.1", + "@firebase/util": "0.1.11", + "faye-websocket": "0.11.1", + "tslib": "1.9.0" + } + }, + "@firebase/database-types": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.2.1.tgz", + "integrity": "sha512-LyvTpLImnhSTyHfPGcBxhD0tHw+R7FUb+als23Ad5hPCcGxlRgLhA+ukrhFIGA8Mt8FYHWgFm7TCX4YDRDxK6w==" + }, + "@firebase/firestore": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-0.4.1.tgz", + "integrity": "sha512-RsceKkGQyiTJq/9odss6v+6KgJVLr5H8hgVO/u+d1Is20cQXJFpDjrgcoGairVb4S/jav2LV1/bHXj3HVLObvw==", + "requires": { + "@firebase/firestore-types": "0.3.0", + "@firebase/logger": "0.1.1", + "@firebase/webchannel-wrapper": "0.2.8", + "grpc": "1.10.1", + "tslib": "1.9.0" + } + }, + "@firebase/firestore-types": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-0.3.0.tgz", + "integrity": "sha512-pWqIALmvp91ELeFiiAOIDVvcCxkLxXffp5KYNL1I/mNgqe2CyGoNB6+pUb/S+FH3oCh/HWHBW+0lXDszcP42aA==" + }, + "@firebase/functions": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.1.1.tgz", + "integrity": "sha512-olSryAPNcH47WFCUmooNgO4P61dmlUEPVYOa0urTLiQh+8M8E7RuDWcqxxxiPk4BCN/l2ZeO0uCDsrzBMX4OqA==", + "requires": { + "@firebase/functions-types": "0.1.1", + "@firebase/messaging-types": "0.1.3", + "isomorphic-fetch": "2.2.1" + } + }, + "@firebase/functions-types": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.1.1.tgz", + "integrity": "sha512-DMCQAuSafYChef2Wa4yYNPeToEDggnlaUHvseKxPzUwOVVmPdr9dxmqQW+UKeGYeUHfiTWFzvsrk8u1ifyvTZA==" + }, + "@firebase/logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.1.1.tgz", + "integrity": "sha512-5jn3HHbEfdOwychyIEIkP1cik+MW/vvoOavTOzwDkH+fv6Bx+HBUOzh09M7sCYzXFtKzjbUax9+g39mJNBLklQ==" + }, + "@firebase/messaging": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.2.4.tgz", + "integrity": "sha512-bgnIhKETgA8ZgWXFmF0+RLqr93/nxqnncRndxNcKTPyq4syah703NeTtaJCMR3LWrfKGV9blpEBogtX3JmJK1g==", + "requires": { + "@firebase/messaging-types": "0.1.3", + "@firebase/util": "0.1.11", + "tslib": "1.9.0" + } + }, + "@firebase/messaging-types": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.1.3.tgz", + "integrity": "sha512-kDixnQujUuwvqc12iFLd6ygb+cdCCXCNeJpQD7jV0mnYMbE1Sp4Y7sl2G7N7r0kcoJPHUQHERBkZlw2N3xyJCw==" + }, + "@firebase/polyfill": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.1.tgz", + "integrity": "sha512-TkmIU4OZeE+rZoQFvq9qYsHv3IYeWahvPUTknUiqN14XJ1777ZEZ+oHBM116/R/Ej3kA5EZxhahqlRHOOD/Dwg==", + "requires": { + "core-js": "2.5.5", + "promise-polyfill": "7.1.2", + "whatwg-fetch": "2.0.4" + }, + "dependencies": { + "whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + } + } + }, + "@firebase/storage": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.1.9.tgz", + "integrity": "sha512-CrlreoXIlWNAAHnOAlP0KpZ2aM8s4QFOcrIhBE3f7vE6h30TuBuhFFra4slUykCuUflyVjBYlea6ph0fJsJr0w==", + "requires": { + "@firebase/storage-types": "0.1.3", + "tslib": "1.9.0" + } + }, + "@firebase/storage-types": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.1.3.tgz", + "integrity": "sha512-xM939ObH7MLDhhrEi/UyEDj87b3AGypGp5YPpEOwvtL2KpF7VQf7g715LoaWmhGd4+e1MHFMCktQbejkpkj63A==" + }, + "@firebase/util": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.1.11.tgz", + "integrity": "sha512-xUMugOJBSKVKOjrKJIVeIr4Z/6iDxSuOlOJRdz0xsOBJ9+lZVxGZs0U4oZmszWhQER1zzR+EQWIYFYePt6/QMQ==", + "requires": { + "tslib": "1.9.0" + } + }, + "@firebase/webchannel-wrapper": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.2.8.tgz", + "integrity": "sha512-ToJbeJnxDc3O325FvcKVb3yHO1hvgHjCFvhKol6Z17GiB7vL104POjFQT4RnlLiAGSRCBAMxinDec9y9vQYdyg==" +======= "@babel/parser": { "version": "7.0.0-beta.53", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.0.0-beta.53.tgz", "integrity": "sha1-H0XrYXv5Rj1IKywE00nZ5O2/SJI=", "dev": true +>>>>>>> a715327c735e81debd2616fa006fbddba22a902c }, "@storybook/addon-actions": { "version": "3.4.8", @@ -866,6 +1009,15 @@ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "0.7.1", + "optjs": "3.2.2" + } + }, "asn1": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", @@ -2779,6 +2931,21 @@ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "requires": { + "long": "3.2.0" + }, + "dependencies": { + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + } + } + }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -3243,6 +3410,11 @@ "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, "combined-stream": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", @@ -4221,6 +4393,11 @@ } } }, + "dom-storage": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz", + "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q==" + }, "dom-urls": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/dom-urls/-/dom-urls-1.1.0.tgz", @@ -5581,6 +5758,23 @@ "locate-path": "^2.0.0" } }, + "firebase": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-4.13.1.tgz", + "integrity": "sha512-vi+DbUPRrsUaLxuMLgCuyISTBNQ/TqrEwWzUpMqyABPwE6YhGplNnCDPs+/kRDXxdqWUdwrUEXo1ansBSimoNw==", + "requires": { + "@firebase/app": "0.2.0", + "@firebase/auth": "0.4.2", + "@firebase/database": "0.2.2", + "@firebase/firestore": "0.4.1", + "@firebase/functions": "0.1.1", + "@firebase/messaging": "0.2.4", + "@firebase/polyfill": "0.3.1", + "@firebase/storage": "0.1.9", + "dom-storage": "2.1.0", + "xmlhttprequest": "1.8.0" + } + }, "flat": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/flat/-/flat-4.0.0.tgz", @@ -6117,239 +6311,1040 @@ "bundled": true, "optional": true }, - "signal-exit": { - "version": "3.0.2", + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz", + "integrity": "sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "is-callable": "^1.1.3" + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "fuse.js": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.2.1.tgz", + "integrity": "sha1-YyDLlM5W7JdVyJred1vNuwNY1CU=", + "dev": true + }, + "fuzzy": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/fuzzy/-/fuzzy-0.1.3.tgz", + "integrity": "sha1-THbsL/CsGjap3M+aAN+GIweNTtg=" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glamor": { + "version": "2.20.40", + "resolved": "https://registry.npmjs.org/glamor/-/glamor-2.20.40.tgz", + "integrity": "sha512-DNXCd+c14N9QF8aAKrfl4xakPk5FdcFwmH7sD0qnC0Pr7xoZ5W9yovhUrY/dJc3psfGGXC58vqQyRtuskyUJxA==", + "dev": true, + "requires": { + "fbjs": "^0.8.12", + "inline-style-prefixer": "^3.0.6", + "object-assign": "^4.1.1", + "prop-types": "^15.5.10", + "through": "^2.3.8" + }, + "dependencies": { + "prop-types": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", + "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", + "dev": true, + "requires": { + "fbjs": "^0.8.16", + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + } + } + }, + "glamorous": { + "version": "4.12.4", + "resolved": "https://registry.npmjs.org/glamorous/-/glamorous-4.12.4.tgz", + "integrity": "sha512-9XjKfMnVJlohSa6ZYrrOz/ZW1xu3JK6zjRTCTkLLJowlmEU7zt9uvIZeUHiYEkr8qDfhhSDDOYZrMiknz0r1Iw==", + "dev": true, + "requires": { + "brcast": "^3.0.0", + "csstype": "^2.2.0", + "fast-memoize": "^2.2.7", + "html-tag-names": "^1.1.1", + "is-function": "^1.0.1", + "is-plain-object": "^2.0.4", + "react-html-attributes": "^1.4.2", + "svg-tag-names": "^1.1.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "2.0.1" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "dev": true, + "requires": { + "min-document": "2.19.0", + "process": "0.5.2" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "requires": { + "ini": "1.3.5" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.1", + "safe-buffer": "5.1.1", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" + }, + "grpc": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.10.1.tgz", + "integrity": "sha512-xmhA11h2XhqpSVzDAmoQAYdNQ+swILXpKOiRpAEQ2kX55ioxVADc6v7SkS4zQBxm4klhQHgGqpGKvoL6LGx4VQ==", + "requires": { + "lodash": "4.17.5", + "nan": "2.10.0", + "node-pre-gyp": "0.7.0", + "protobufjs": "5.0.2" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ajv": { + "version": "5.5.2", + "bundled": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.5" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "1.0.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.7.0", + "bundled": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "4.3.1", + "bundled": true, + "requires": { + "hoek": "4.2.1" + } + }, + "brace-expansion": { + "version": "1.1.8", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "combined-stream": { + "version": "1.0.6", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "cryptiles": { + "version": "3.1.2", + "bundled": true, + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "bundled": true, + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "fast-deep-equal": { + "version": "1.1.0", + "bundled": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "bundled": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.3.2", + "bundled": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "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, + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": 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 + }, + "har-schema": { + "version": "2.0.0", + "bundled": true + }, + "har-validator": { + "version": "5.0.3", + "bundled": true, + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hawk": { + "version": "6.0.2", + "bundled": true, + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.1", + "bundled": true + }, + "http-signature": { + "version": "1.2.0", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "bundled": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "mime-db": { + "version": "1.33.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.18", + "bundled": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "node-pre-gyp": { + "version": "0.7.0", + "bundled": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.2.6", + "request": "2.83.0", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "2.2.1", + "tar-pack": "3.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": 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 + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "performance-now": { + "version": "2.1.0", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qs": { + "version": "6.5.1", + "bundled": true + }, + "rc": { + "version": "1.2.6", + "bundled": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + } + }, + "readable-stream": { + "version": "2.3.5", + "bundled": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.83.0", + "bundled": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.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", + "hawk": "6.0.2", + "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.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sntp": { + "version": "2.1.0", + "bundled": true, + "requires": { +<<<<<<< HEAD + "hoek": "4.2.1" +======= + "is-glob": "^2.0.0" +>>>>>>> a715327c735e81debd2616fa006fbddba22a902c + } + }, + "sshpk": { + "version": "1.14.1", "bundled": 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", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } }, "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, "string_decoder": { - "version": "1.1.1", + "version": "1.0.3", "bundled": true, - "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } }, + "stringstream": { + "version": "0.0.5", + "bundled": true + }, "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-json-comments": { "version": "2.0.1", - "bundled": true, - "optional": true + "bundled": true }, "tar": { - "version": "4.4.1", + "version": "2.2.1", "bundled": true, - "optional": true, "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" +<<<<<<< HEAD + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" } }, - "util-deprecate": { - "version": "1.0.2", + "tar-pack": { + "version": "3.4.1", "bundled": true, - "optional": true + "requires": { + "debug": "2.6.9", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.3.5", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } }, - "wide-align": { - "version": "1.1.2", + "tough-cookie": { + "version": "2.3.4", "bundled": true, - "optional": true, "requires": { - "string-width": "^1.0.2" + "punycode": "1.4.1" } }, - "wrappy": { - "version": "1.0.2", + "tunnel-agent": { + "version": "0.6.0", "bundled": true, - "optional": true + "requires": { + "safe-buffer": "5.1.1" + } }, - "yallist": { - "version": "3.0.2", + "tweetnacl": { + "version": "0.14.5", "bundled": true, "optional": true - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "function.prototype.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz", - "integrity": "sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "is-callable": "^1.1.3" - } - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" - }, - "fuse.js": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.2.1.tgz", - "integrity": "sha1-YyDLlM5W7JdVyJred1vNuwNY1CU=", - "dev": true - }, - "fuzzy": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/fuzzy/-/fuzzy-0.1.3.tgz", - "integrity": "sha1-THbsL/CsGjap3M+aAN+GIweNTtg=" - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glamor": { - "version": "2.20.40", - "resolved": "https://registry.npmjs.org/glamor/-/glamor-2.20.40.tgz", - "integrity": "sha512-DNXCd+c14N9QF8aAKrfl4xakPk5FdcFwmH7sD0qnC0Pr7xoZ5W9yovhUrY/dJc3psfGGXC58vqQyRtuskyUJxA==", - "dev": true, - "requires": { - "fbjs": "^0.8.12", - "inline-style-prefixer": "^3.0.6", - "object-assign": "^4.1.1", - "prop-types": "^15.5.10", - "through": "^2.3.8" - }, - "dependencies": { - "prop-types": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", - "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", - "dev": true, - "requires": { - "fbjs": "^0.8.16", - "loose-envify": "^1.3.1", - "object-assign": "^4.1.1" - } - } - } - }, - "glamorous": { - "version": "4.12.4", - "resolved": "https://registry.npmjs.org/glamorous/-/glamorous-4.12.4.tgz", - "integrity": "sha512-9XjKfMnVJlohSa6ZYrrOz/ZW1xu3JK6zjRTCTkLLJowlmEU7zt9uvIZeUHiYEkr8qDfhhSDDOYZrMiknz0r1Iw==", - "dev": true, - "requires": { - "brcast": "^3.0.0", - "csstype": "^2.2.0", - "fast-memoize": "^2.2.7", - "html-tag-names": "^1.1.1", - "is-function": "^1.0.1", - "is-plain-object": "^2.0.4", - "react-html-attributes": "^1.4.2", - "svg-tag-names": "^1.1.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "requires": { - "is-glob": "^2.0.0" - } }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + "uid-number": { + "version": "0.0.6", + "bundled": true }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "uuid": { + "version": "3.2.1", + "bundled": true + }, + "verror": { + "version": "1.10.0", + "bundled": true, "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" +======= "is-extglob": "^1.0.0" } } @@ -6370,10 +7365,24 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "requires": { "is-extglob": "^2.1.0" +>>>>>>> a715327c735e81debd2616fa006fbddba22a902c + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "1.0.2" } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true } } }, +<<<<<<< HEAD +======= "global": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", @@ -6460,6 +7469,7 @@ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" }, +>>>>>>> a715327c735e81debd2616fa006fbddba22a902c "gzip-size": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", @@ -9520,8 +10530,7 @@ "nan": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "optional": true + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" }, "nanomatch": { "version": "1.2.9", @@ -9917,6 +10926,11 @@ } } }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, "original": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", @@ -11517,6 +12531,11 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "promise-polyfill": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-7.1.2.tgz", + "integrity": "sha512-FuEc12/eKqqoRYIGBrUptCBRhobL19PS2U31vMNTfyck1FxPyMfgsXyW4Mav85y/ZN1hop3hOwRlUDok23oYfQ==" + }, "promise.prototype.finally": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.0.tgz", @@ -11537,6 +12556,61 @@ "object-assign": "^4.1.1" } }, + "protobufjs": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.2.tgz", + "integrity": "sha1-WXSNfc8D0tsiwT2p/rAk4Wq4DJE=", + "requires": { + "ascli": "1.0.1", + "bytebuffer": "5.0.1", + "glob": "7.1.2", + "yargs": "3.32.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "2.1.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "string-width": "1.0.2", + "window-size": "0.1.4", + "y18n": "3.2.1" + } + } + } + }, "proxy-addr": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", @@ -14913,6 +15987,11 @@ "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.2.tgz", "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==" }, + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -16224,6 +17303,11 @@ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=" }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", diff --git a/package.json b/package.json index b0411229ba..4c6d9ea3fa 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "core-js": "^2.5.5", "dota2-emoticons": "^1.0.1", "dotaconstants": "^5.36.0", + "firebase": "^4.13.1", "fuzzy": "^0.1.3", "heatmap.js": "^2.0.5", "history": "^4.7.2", diff --git a/public/firebase-messaging-sw.js b/public/firebase-messaging-sw.js new file mode 100644 index 0000000000..d16adc76c0 --- /dev/null +++ b/public/firebase-messaging-sw.js @@ -0,0 +1,51 @@ +/* eslint-disable no-undef, no-restricted-globals */ +/** + * Here is is the code snippet to initialize Firebase Messaging in the Service + * Worker when your app is not hosted on Firebase Hosting. + // [START initialize_firebase_in_sw] + // Give the service worker access to Firebase Messaging. + // Note that you can only use Firebase Messaging here, other Firebase libraries + // are not available in the service worker. + * */ +importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js'); +importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js'); +// Initialize the Firebase app in the service worker by passing in the +// messagingSenderId. + +firebase.initializeApp({ + messagingSenderId: '94888484309', +}); + +// Retrieve an instance of Firebase Messaging so that it can handle background +// messages. +const messaging = firebase.messaging(); +// [END initialize_firebase_in_sw] + +// If you would like to customize notifications that are received in the +// background (Web app is closed or not in browser focus) then you should +// implement this optional method. +// [START background_handler] +messaging.setBackgroundMessageHandler((payload) => { + // Customize notification here + let title = ''; + const options = { + data: payload.data, + }; + + if (payload.data.type === 'MATCH') { + title = 'Parsed $match'.replace('$match', payload.data.match_id); + options.body = 'Check out your performance on OpenDota.'; + options.actions = [{ action: 'View Match', title: 'View Match' }]; + } + + return self.registration.showNotification(title, options); +}); + +self.addEventListener('notificationclick', (event) => { + event.notification.close(); + + // Allow the notification to open page even if the button isn't clicked + if (event.action === 'View Match' || event.notification.data.type === 'MATCH') { + event.waitUntil(clients.openWindow(`https://www.opendota.com/matches/${event.notification.data.match_id}?notification=true`)); + } +}); diff --git a/public/manifest.json b/public/manifest.json index e7cb0bf44b..f34d6ada34 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -48,5 +48,6 @@ "type": "image/png" } ], - "splash_pages": null + "splash_pages": null, + "gcm_sender_id": "103953800507" } \ No newline at end of file diff --git a/src/components/App/App.jsx b/src/components/App/App.jsx index c2ae8f7d56..1ee996c4a8 100644 --- a/src/components/App/App.jsx +++ b/src/components/App/App.jsx @@ -1,12 +1,18 @@ +/* global Notification */ import React from 'react'; +import fetch from 'isomorphic-fetch'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import getMuiTheme from 'material-ui/styles/getMuiTheme'; import darkBaseTheme from 'material-ui/styles/baseThemes/darkBaseTheme'; import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; +import FlatButton from 'material-ui/FlatButton'; +import RaisedButton from 'material-ui/RaisedButton'; import Helmet from 'react-helmet'; import styled from 'styled-components'; import { Route, Switch } from 'react-router-dom'; +import * as firebase from 'firebase/app'; +import 'firebase/messaging'; import Header from '../Header'; import Player from '../Player'; import Home from '../Home'; @@ -28,6 +34,44 @@ import Api from '../Api'; import Footer from '../Footer'; import constants from '../constants'; import FourOhFour from '../../components/FourOhFour'; +import { heroSelector } from '../../reducers/selectors'; + +const path = '/notifications'; + +firebase.initializeApp({ + messagingSenderId: '94888484309', +}); + +const messaging = firebase.messaging(); + +function getMessagingToken() { + messaging.getToken() + .then((token) => { + if (token) { + fetch(`${process.env.REACT_APP_API_HOST}${path}`, { + credentials: 'include', + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + token, + }), + }) + .then((res) => { + if (!res.ok) { + throw Error(); + } + }) + .catch(err => console.log(err)); + } + }).catch((err) => { + console.log('An error occurred while retrieving token. ', err); + }); +} + +getMessagingToken(); const muiTheme = { fontFamily: constants.fontFamily, @@ -85,6 +129,35 @@ const AdBannerDiv = styled.div` } `; +const Prompt = styled.div` + position: fixed; + right: 0px; + bottom: 0px; + background: #0d2e39; + width: 325px; + z-index: 100; + box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.4); + margin: 0 5px 5px 0; + + @media only screen and (max-width: 480px) { + width: 100%; + margin: 0; + } +`; + +const PromptContainer = styled.div` + padding: 10px; + + & img { + height: 25px; + margin: 0 5px -4px 0; + } + + & button { + margin: 5px; + } +`; + class App extends React.Component { static propTypes = { params: PropTypes.shape({}), @@ -93,6 +166,19 @@ class App extends React.Component { key: PropTypes.string, }), strings: PropTypes.shape({}), + user: PropTypes.shape({}), + } + + constructor(props) { + super(props); + + + this.state = { + canNotify: 'Notification' in window && Notification.permission, + showLoginPrompt: true, + }; + + this.askForNotifiyPermission = this.askForNotifiyPermission.bind(this); } componentDidUpdate(prevProps) { @@ -100,10 +186,45 @@ class App extends React.Component { window.scrollTo(0, 0); } } + + componentDidMount() { + messaging.onTokenRefresh(getMessagingToken); + + messaging.onMessage((payload) => { + console.log('Message received. ', payload); + + if (payload.data.type === 'MATCH' && Object.keys(this.props.strings).length) { + const n = new Notification( + this.props.strings.notify_match_title.replace('$match', payload.data.match_id), + { + body: this.props.strings.notify_match_body, + }, + ); + n.onclick = (event) => { + console.log(event); + event.preventDefault(); // prevent the browser from focusing the Notification's tab + window.open(`https://opendota.com/matches/${payload.data.match_id}`, '_blank'); + }; + } + }); + } + + askForNotifiyPermission(strings) { + Notification.requestPermission() + .then((permission) => { + this.setState({ canNotify: permission }); + if (permission === 'granted') { + new Notification(`${strings.notify_granted_title}!`, { // eslint-disable-line no-new + body: strings.notify_granted_body, + }); + getMessagingToken(); + } + }); + } render() { const { - params, width, location, strings, + params, width, location, strings, user, heroes } = this.props; const includeAds = !['/', '/api-keys'].includes(location.pathname); return ( @@ -114,6 +235,50 @@ class App extends React.Component { titleTemplate={strings.title_template} />
+ { + user && this.state.canNotify !== false && !['denied', 'granted'].includes(this.state.canNotify) ? + + + logo +

{strings.notify_prompt_title}

+

{strings.notify_prompt_body}

+ this.askForNotifiyPermission(strings)} + /> + this.setState({canNotify: false})} + /> +
+
+ :
+ } + { + !user && this.state.showLoginPrompt ? + + + logo +

{strings.login_prompt_title}

+

{strings.login_prompt_body}

+ + this.setState({ showLoginPrompt: false })} + /> +
+
+ :
+ } { includeAds && @@ -161,6 +326,8 @@ class App extends React.Component { const mapStateToProps = state => ({ strings: state.app.strings, + user: state.app.metadata.data.user, + heroes: state.app.heroStats.data, }); export default connect(mapStateToProps)(App); diff --git a/src/index.js b/src/index.js index ca1a958215..fe58f15531 100644 --- a/src/index.js +++ b/src/index.js @@ -22,8 +22,7 @@ import store from './store'; import { getMetadata, getStrings, getAbilities, getNeutralAbilities, getAbilityIds } from './actions'; import App from './components/App'; import constants from './components/constants'; -// import registerServiceWorker from './registerServiceWorker'; -import { unregister } from './registerServiceWorker'; +import registerServiceWorker from './registerServiceWorker'; // Inject global styles injectGlobal([` @@ -176,6 +175,7 @@ store.dispatch(getAbilityIds()); ReactGA.initialize('UA-55757642-1'); ReactGA.pageview(window.location.pathname + window.location.search); + const history = createHistory(); history.listen((location) => { ReactGA.pageview(location.pathname); @@ -193,6 +193,6 @@ if (rootElement.hasChildNodes()) { } else { hydrate(app, rootElement); } -// registerServiceWorker(); -unregister(); +registerServiceWorker(); + // document.getElementById('loader').style.display = 'none'; diff --git a/src/lang/en-US.json b/src/lang/en-US.json index 63142bdc65..2295cc17da 100644 --- a/src/lang/en-US.json +++ b/src/lang/en-US.json @@ -102,7 +102,20 @@ "app_pro_players": "Pro Players", "app_public_players": "Public Players", "app_my_profile": "My Profile", - + + "login_prompt_title": "Join the OpenDota Community", + "login_prompt_body": "Log in and get advanced stats for all your matches. All for free.", + "login_prompt_dismiss": "Dismiss", + + "notify_prompt_title": "Get Notified", + "notify_prompt_body": "Enable automatic updates for whenever your match is parsed.", + "notify_prompt_enable": "Enable", + "notify_prompt_dismiss": "Dismiss", + "notify_granted_title": "Awesome", + "notify_granted_body": "You'll get a notification like this when your match is parsed.", + "notify_match_title": "Parsed $match", + "notify_match_body": "Check out your performance on OpenDota.", + "barracks_value_1": "Dire Bot Melee", "barracks_value_2": "Dire Bot Ranged", "barracks_value_4": "Dire Mid Melee", diff --git a/src/registerServiceWorker.js b/src/registerServiceWorker.js index 10a1cda468..833c48fc76 100644 --- a/src/registerServiceWorker.js +++ b/src/registerServiceWorker.js @@ -31,7 +31,7 @@ export default function register() { } window.addEventListener('load', () => { - const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + const swUrl = `${process.env.PUBLIC_URL}/firebase-messaging-sw.js`; if (!isLocalhost) { // Is not local host. Just register service worker