Commit 141f1755 authored by Searev's avatar Searev

Merge branch 'develop' into 'master'

Develop

See merge request !5
parents a672d7c3 fdf79f29
Pipeline #82213505 canceled with stage
in 4 seconds
node_modules
.idea
.gitignore
.gitlab-ci.yml
*.md
.env
.env.dist
dist
Dockerfile
docker-compose.yml
\ No newline at end of file
APP_PORT=80
RABBITMQ_PROTOCOL=amqp
RABBITMQ_HOST=rabbitmq
RABBITMQ_PORT=5672
RABBITMQ_USERNAME=guest
RABBITMQ_PASSWORD=guest
EVENTS_URL=events.treviz.org
NODE_ENV=production
PUBLIC_KEY_PATH=/var/data/keys/public.pem
\ No newline at end of file
dist
node_modules
\ No newline at end of file
node_modules
.env
.idea
\ No newline at end of file
stages:
- build
build:
stage: build
only:
- tags
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
......@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [1.0.3] - 2019-09-14
### Refactor
- Use a specific RabbitMQ exchange to retrieve notifications
- Use Gitlab CI to build and push images to registry
## [1.0.2] - 2018-11-04
### Added
- Docker-compose file with labels for easy deployment with [Traefik](http://traefik.io/)
## [1.0.1] - 2018-10-30
### Added
- Specify the port of the RabbitMQ instance in the configuration
### Fixed
- Stop listening to messages from a RabbitMQ queue when the user has disconnected
## [1.0.0] - 2018-10-14
### Added
- Create microservice
......
FROM node:alpine
FROM node:latest as builder
WORKDIR /var/www/api
COPY ./package*.json ./
RUN npm install
COPY . ./
RUN npm run build
FROM node:alpine
COPY ./package*.json ./
RUN npm install --production
COPY --from=builder /var/www/api/dist ./dist
CMD [ "npm", "start" ]
\ No newline at end of file
......@@ -8,12 +8,12 @@ Treviz Events
Treviz is an open-source web platform that helps you set up and join open, collaborative organizations, in which you
can work on the projects you want and get rewarded for your work.
This repository contains the code of micro-service that handles server-sent events. It is developped using the
This repository contains the code of micro-service that handles server-sent events. It is developed using the
[Express microframework](http://expressjs.com), and uses [RabbitMQ](https://www.rabbitmq.com/) as a message broker (but
you can definitely replace it with any other amqp server). The language used is [Typescript][typescriptlang.org].
You may use this service independently from any Treviz instance, for instance if you want to add some real-time features
to your own application.
to your own application.
## Features
This service is used to perform real-time features:
......@@ -46,6 +46,28 @@ npm run serve
You can also use Docker to launch the microservice.
## Deploying the API
The API can easily be deployed on a server using [Traefik](http://traefik.io/). To do so, clone the project, and copy the `.env.dist` file
as `.env`. Then, fill it with the specifics attributes of your environment. The `PUBLIC_KEY_PATH` variable should match the path, on your
server, of the public key that will be used to validate JWT, and authenticate users. It should also be noted that we expect a rabbitmq
instance to be already running as a docker container in the network `web`.
You can now launch a docker instance with
```
$ docker-compose up -d
```
## Usage
You can start a connection by making an http request to `/:username`, where `username` is the name of a RabbitMQ Queue. The webservice
expects a Json Web Token to be sent as a `Bearer` token in the `Authorization` header. This token is then validated using the public key
specified when running the node server. The `username` contained in the JWT should match the name of the queue to listen to.
Once the connection is established, it writes a dummy response to notify the client, then sends any message that is received on the RabbitMQ
queue.
## Contributing
Check out our [Contributing Guide](./CONTRIBUTING.md) if you are interested in joining the development team, if you want
......@@ -68,4 +90,4 @@ You can learn more about Treviz on:
* our documentation [doc.treviz.xyz](https://doc.treviz.xyz)
* our blog [blog.treviz.xyz](https://blog.treviz.xyz)
Feel free ton [contact us](https://treviz.xyz/contact) if you have any question.
Feel free to [contact us](https://treviz.xyz/contact) if you have any question.
version: '3.1'
services:
events:
build:
context: ./
environment:
APP_PORT: ${APP_PORT}
PUBLIC_KEY_PATH: /run/secrets/public_key_cert
RABBITMQ_PROTOCOL: ${RABBITMQ_PROTOCOL}
RABBITMQ_HOST: ${RABBITMQ_HOST}
RABBITMQ_PORT: ${RABBITMQ_PORT}
RABBITMQ_USERNAME: ${RABBITMQ_USERNAME}
RABBITMQ_PASSWORD: ${RABBITMQ_PASSWORD}
NODE_ENV: ${NODE_ENV}
networks:
- web
- default
expose:
- "80"
secrets:
- public_key_cert
restart: always
labels:
- "traefik.backend=api_events"
- "traefik.docker.network=web"
- "traefik.enable=true"
- "traefik.basic.frontend.rule=Host:${EVENTS_URL}"
- "traefik.basic.port=80"
- "traefik.basic.protocol=http"
networks:
web:
external: true
secrets:
public_key_cert:
file: ${PUBLIC_KEY_PATH}
\ No newline at end of file
......@@ -10,9 +10,9 @@
"integrity": "sha512-zHRQ7RvL7Jjpw8LfcfuSWBX2Zbv+8gau5Q0CFuL9WuKQMXqyIzV1PaABv13yMTQq1+5IzsEhHw0eGJl+WzbbbA==",
"dev": true,
"requires": {
"@types/bluebird": "3.5.24",
"@types/events": "1.2.0",
"@types/node": "10.11.7"
"@types/bluebird": "*",
"@types/events": "*",
"@types/node": "*"
}
},
"@types/bluebird": {
......@@ -27,8 +27,8 @@
"integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==",
"dev": true,
"requires": {
"@types/connect": "3.4.32",
"@types/node": "10.11.7"
"@types/connect": "*",
"@types/node": "*"
}
},
"@types/connect": {
......@@ -37,7 +37,7 @@
"integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==",
"dev": true,
"requires": {
"@types/node": "10.11.7"
"@types/node": "*"
}
},
"@types/events": {
......@@ -52,9 +52,9 @@
"integrity": "sha512-TtPEYumsmSTtTetAPXlJVf3kEqb6wZK0bZojpJQrnD/djV4q1oB6QQ8aKvKqwNPACoe02GNiy5zDzcYivR5Z2w==",
"dev": true,
"requires": {
"@types/body-parser": "1.17.0",
"@types/express-serve-static-core": "4.16.0",
"@types/serve-static": "1.13.2"
"@types/body-parser": "*",
"@types/express-serve-static-core": "*",
"@types/serve-static": "*"
}
},
"@types/express-serve-static-core": {
......@@ -63,9 +63,9 @@
"integrity": "sha512-lTeoCu5NxJU4OD9moCgm0ESZzweAx0YqsAcab6OB0EB3+As1OaHtKnaGJvcngQxYsi9UNv0abn4/DRavrRxt4w==",
"dev": true,
"requires": {
"@types/events": "1.2.0",
"@types/node": "10.11.7",
"@types/range-parser": "1.2.2"
"@types/events": "*",
"@types/node": "*",
"@types/range-parser": "*"
}
},
"@types/jsonwebtoken": {
......@@ -73,7 +73,7 @@
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-7.2.8.tgz",
"integrity": "sha512-XENN3YzEB8D6TiUww0O8SRznzy1v+77lH7UmuN54xq/IHIsyWjWOzZuFFTtoiRuaE782uAoRwBe/wwow+vQXZw==",
"requires": {
"@types/node": "10.11.7"
"@types/node": "*"
}
},
"@types/mime": {
......@@ -99,8 +99,8 @@
"integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==",
"dev": true,
"requires": {
"@types/express-serve-static-core": "4.16.0",
"@types/mime": "2.0.0"
"@types/express-serve-static-core": "*",
"@types/mime": "*"
}
},
"accepts": {
......@@ -108,7 +108,7 @@
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
"integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
"requires": {
"mime-types": "2.1.20",
"mime-types": "~2.1.18",
"negotiator": "0.6.1"
}
},
......@@ -117,11 +117,11 @@
"resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz",
"integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==",
"requires": {
"bitsyntax": "0.0.4",
"bluebird": "3.5.2",
"bitsyntax": "~0.0.4",
"bluebird": "^3.4.6",
"buffer-more-ints": "0.0.2",
"readable-stream": "1.1.14",
"safe-buffer": "5.1.2"
"readable-stream": "1.x >=1.1.9",
"safe-buffer": "^5.0.1"
}
},
"ansi-regex": {
......@@ -142,7 +142,7 @@
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"requires": {
"sprintf-js": "1.0.3"
"sprintf-js": "~1.0.2"
}
},
"array-flatten": {
......@@ -156,9 +156,9 @@
"integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
"dev": true,
"requires": {
"chalk": "1.1.3",
"esutils": "2.0.2",
"js-tokens": "3.0.2"
"chalk": "^1.1.3",
"esutils": "^2.0.2",
"js-tokens": "^3.0.2"
},
"dependencies": {
"chalk": {
......@@ -167,11 +167,11 @@
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"dev": true,
"requires": {
"ansi-styles": "2.2.1",
"escape-string-regexp": "1.0.5",
"has-ansi": "2.0.0",
"strip-ansi": "3.0.1",
"supports-color": "2.0.0"
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
}
}
}
......@@ -201,15 +201,15 @@
"integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
"requires": {
"bytes": "3.0.0",
"content-type": "1.0.4",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "1.1.2",
"http-errors": "1.6.3",
"depd": "~1.1.2",
"http-errors": "~1.6.3",
"iconv-lite": "0.4.23",
"on-finished": "2.3.0",
"on-finished": "~2.3.0",
"qs": "6.5.2",
"raw-body": "2.3.3",
"type-is": "1.6.16"
"type-is": "~1.6.16"
}
},
"brace-expansion": {
......@@ -218,7 +218,7 @@
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "1.0.0",
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
......@@ -249,9 +249,9 @@
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
"dev": true,
"requires": {
"ansi-styles": "3.2.1",
"escape-string-regexp": "1.0.5",
"supports-color": "5.5.0"
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"ansi-styles": {
......@@ -260,7 +260,7 @@
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "1.9.3"
"color-convert": "^1.9.0"
}
},
"supports-color": {
......@@ -269,7 +269,7 @@
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "3.0.0"
"has-flag": "^3.0.0"
}
}
}
......@@ -355,7 +355,7 @@
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz",
"integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=",
"requires": {
"safe-buffer": "5.1.2"
"safe-buffer": "^5.0.1"
}
},
"ee-first": {
......@@ -401,36 +401,36 @@
"resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
"integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
"requires": {
"accepts": "1.3.5",
"accepts": "~1.3.5",
"array-flatten": "1.1.1",
"body-parser": "1.18.3",
"content-disposition": "0.5.2",
"content-type": "1.0.4",
"content-type": "~1.0.4",
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "1.1.2",
"encodeurl": "1.0.2",
"escape-html": "1.0.3",
"etag": "1.8.1",
"depd": "~1.1.2",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.1.1",
"fresh": "0.5.2",
"merge-descriptors": "1.0.1",
"methods": "1.1.2",
"on-finished": "2.3.0",
"parseurl": "1.3.2",
"methods": "~1.1.2",
"on-finished": "~2.3.0",
"parseurl": "~1.3.2",
"path-to-regexp": "0.1.7",
"proxy-addr": "2.0.4",
"proxy-addr": "~2.0.4",
"qs": "6.5.2",
"range-parser": "1.2.0",
"range-parser": "~1.2.0",
"safe-buffer": "5.1.2",
"send": "0.16.2",
"serve-static": "1.13.2",
"setprototypeof": "1.1.0",
"statuses": "1.4.0",
"type-is": "1.6.16",
"statuses": "~1.4.0",
"type-is": "~1.6.16",
"utils-merge": "1.0.1",
"vary": "1.1.2"
"vary": "~1.1.2"
}
},
"finalhandler": {
......@@ -439,12 +439,12 @@
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
"requires": {
"debug": "2.6.9",
"encodeurl": "1.0.2",
"escape-html": "1.0.3",
"on-finished": "2.3.0",
"parseurl": "1.3.2",
"statuses": "1.4.0",
"unpipe": "1.0.0"
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"on-finished": "~2.3.0",
"parseurl": "~1.3.2",
"statuses": "~1.4.0",
"unpipe": "~1.0.0"
}
},
"forwarded": {
......@@ -469,12 +469,12 @@
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"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"
"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"
}
},
"has-ansi": {
......@@ -483,7 +483,7 @@
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
"dev": true,
"requires": {
"ansi-regex": "2.1.1"
"ansi-regex": "^2.0.0"
}
},
"has-flag": {
......@@ -497,10 +497,10 @@
"resolved": "http://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.4.0"
"statuses": ">= 1.4.0 < 2"
}
},
"iconv-lite": {
......@@ -508,7 +508,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"
}
},
"inflight": {
......@@ -517,8 +517,8 @@
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
......@@ -543,13 +543,13 @@
"dev": true
},
"js-yaml": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
"dev": true,
"requires": {
"argparse": "1.0.10",
"esprima": "4.0.1"
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"jsonwebtoken": {
......@@ -557,15 +557,15 @@
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz",
"integrity": "sha512-oge/hvlmeJCH+iIz1DwcO7vKPkNGJHhgkspk8OH3VKlw+mbi42WtD4ig1+VXRln765vxptAv+xT26Fd3cteqag==",
"requires": {
"jws": "3.1.5",
"lodash.includes": "4.3.0",
"lodash.isboolean": "3.0.3",
"lodash.isinteger": "4.0.4",
"lodash.isnumber": "3.0.3",
"lodash.isplainobject": "4.0.6",
"lodash.isstring": "4.0.1",
"lodash.once": "4.1.1",
"ms": "2.1.1"
"jws": "^3.1.5",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1"
},
"dependencies": {
"ms": {
......@@ -582,7 +582,7 @@
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.10",
"safe-buffer": "5.1.2"
"safe-buffer": "^5.0.1"
}
},
"jws": {
......@@ -590,8 +590,8 @@
"resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz",
"integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==",
"requires": {
"jwa": "1.1.6",
"safe-buffer": "5.1.2"
"jwa": "^1.1.5",
"safe-buffer": "^5.0.1"
}
},
"lodash.includes": {
......@@ -659,7 +659,7 @@
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
"integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
"requires": {
"mime-db": "1.36.0"
"mime-db": "~1.36.0"
}
},
"minimatch": {
......@@ -668,7 +668,7 @@
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "1.1.11"
"brace-expansion": "^1.1.7"
}
},
"ms": {
......@@ -695,7 +695,7 @@
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1.0.2"
"wrappy": "1"
}
},
"parseurl": {
......@@ -725,7 +725,7 @@
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
"integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
"requires": {
"forwarded": "0.1.2",
"forwarded": "~0.1.2",
"ipaddr.js": "1.8.0"
}
},
......@@ -755,10 +755,10 @@
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "0.10.31"
"string_decoder": "~0.10.x"
}
},
"resolve": {
......@@ -767,7 +767,7 @@
"integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
"dev": true,
"requires": {
"path-parse": "1.0.6"
"path-parse": "^1.0.5"
}
},