diff --git a/.env_dist b/.env_dist new file mode 100644 index 0000000000000000000000000000000000000000..77eb68f731eb584245173e5048e7b15df422c72e --- /dev/null +++ b/.env_dist @@ -0,0 +1,14 @@ +# Modele du fichier '.env', definissant variables "d'environnement" utilisees dans divers fichiers de src/ et de db/. +# (Ces variables sont chargees par le package dotenv dans `process.env`, dans les fichiers .js et .ts ou dotenv.config() est appele) +#Copier et renommer .env + +TARGET_ENV=development +PORT=3000 +DB_USER=sigma +DB_PASSWD=sigmapw +DB_HOST=localhost +#DB_HOST=129.201.104.10 # for remote database +#DB_HOST=127.0.0.1 # for devs using a port forwarding +FRONTEND_SERVER_URL=http://localhost:8888 +#LDAP_URI= (loaded from ldap_config.json!) +#TEST_PORT=3001 (used only in tests/, not yet implemented) diff --git a/.eslintrc.json b/.eslintrc.json index eb8ccc675167e07c62c62873ac622b57eb1af79d..705be3165200e9112c02446561cad30da4422c99 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,7 +1,8 @@ { "env": { "es6": true, - "node": true + "node": true, + "mocha": true }, "extends": "eslint:recommended", "parserOptions": { diff --git a/.gitignore b/.gitignore index 569d2145ad83c2e513bdc93362ead6639959f2b1..5e522f55230586043cddad095cc97aaa28902fb1 100644 --- a/.gitignore +++ b/.gitignore @@ -29,9 +29,6 @@ bower_components # node-waf configuration .lock-wscript -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - # Dependency directories node_modules/ jspm_packages/ @@ -69,6 +66,7 @@ typings/ # Generated files doc/ build/ +tsbuild/ # Config files ldap_credentials.json diff --git a/Dockerfile b/Dockerfile index 8fb849a5d2cac8a5bba278a4d620d1950b7708d2..38ebd7e47cdf243b39528724c8340891ff320d04 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ COPY package*.json ./ # Install app dependencies RUN npm install --only=production && npm i -g knex -ARG ldap_uri=ldap://frankiz.eleves.polytechnique.fr:389 +ARG ldap_uri=ldap://bloaziadur.eleves.polytechnique.fr:389 ENV LDAP_URI=${ldap_uri} ENV HOST=0.0.0.0 ENV NODE_ENV=production diff --git a/README.md b/README.md index fee78e20595ca1cd8c1e2e131679939f36ead3e3..e930c7bcad9784a23b00c76d7562857937e45b26 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Ce dépôt contient le _backend_ de Sigma, le successeur de Frankiz, un site ét Le but des lignes qui suivent est de permettre au lecteur de rapidement mettre en place et lancer un sigma local et se familiariser avec son administration. Comment obtenir la documentation détaillée du projet est expliqué à la fin de ce document. +Pour avoir un guide détaillé de l'installation de l'environnement de dev, voir [ce carnet]() + Pour obtenir une copie du projet, cloner le dépôt par : ```bash git clone git@gitlab.binets.fr:br/sigma-backend.git @@ -16,9 +18,7 @@ git clone git@gitlab.binets.fr:br/sigma-backend.git git clone https://gitlab.binets.fr/br/sigma-backend.git ``` -## Démarrer le serveur (en mode développement) - -### Installer les dépendances *npm* +## Installer les dépendances *npm* On utilise un serveur node.js avec [express.js](https://expressjs.com/). [^server] Utiliser Node.js permet d'utiliser facilement [*npm*](https://www.npmjs.com/) (Node Package Manager). Une "dépendance" est un package utilisé dans le projet. @@ -36,26 +36,91 @@ Pour installer les dépendances spécifiées dans `package.json` il faut donc la npm install ``` -Certaines d'entre elles, comme KnexJS ou Webpack, *doivent être installées globalement* : -```bash -npm install -g knex -npm install -g webpack -npm install -g eslint -``` - Les dépendances principales utilisées sont - *knex.js*, qui permet de construire des requêtes SQL facilement, - *GraphQL*, qui fournit une couche d'abstraction pour l'échange de données frontend-backend, - *ldap.js*, qui permet d'interroger un serveur LDAP, - *webpack*, qui compile et optimise tout le code source javascript en un `bundle.js`, -- *ESlint*, pour le développement, outil de vérification syntaxique. +- *ESLint* et *TSLint*, pour le développement, outils de vérification syntaxique. Et une dépendance supplémentaire, PostgreSQL (linux est supposé) : ```bash sudo apt install postgresql ``` -### Setup la BDD PostgreSQL +## Configuration +L'API est conçue pour êtes modulaire et pour fonctionner dans plusieurs environnements. + +On peut donc le configurer via des fichiers ou des variables d'environnement. En deux mots : + +* [`jsdoc_config.json`](../jsdoc_config.json), [`Dockerfile`](../Dockerfile), [`.dockerignore`](../.dockerignore), [`.gitignore`](../.gitignore), [`.eslintignore`](../.eslintignore), [`webpack.config.js`](../webpack.config.js) : transparents +* [`ldap_config.json`](../ldap_config.json) : noms champs du LDAP +* [`ldap_credentials.json`](../ldap_credentials.json) : paramètres de connexion secrets au LDAP +* [`.estlintrc.json`](../.eslintrc.json) : ESLINT ou à quel point cancériser le développeur +* [`.gitattributes`](../.gitattributes) : terminaison de fichiers +* [`.gitlab-ci.yml`](../.gitlab-ci.yml) : pipeline gitlab +* [`package.json`](../package.json) et [`package-lock.json`](../package-lock.json) : gestion des dépendances usuel +* [`tsconfig.json`](../tsconfig.json) : configure la compilation de fichiers Typescript en Javascript +* [`tslint.json`](../tslint.json) : configure tslint, utilisé plutôt que tsc dans le projet final +* [`.env`](../.env) : définit les variables d'environnement et ports utilisés... + +Certains de ces fichiers de configurations ont une version "distribution" en "_dist" qui permet de les partager (le reste du temps ils sont dans le .gitignore), quitte à les renommer et à les modifier en local. + +### Configuration LDAP +L'API de Sigma nécessite de se connecter au LDAP Frankiz, à la fois pour obtenir des données et pour l'authentification des utilisateurs. Cela est fait à l'aide de la librairie [ldapjs](http://ldapjs.org) pour faire les requêtes au LDAP et [passportJS](http://www.passportjs.org/) pour l'authentification. + +* La configuration LDAP de base se situe dans [ldap_config.json](../ldap_config.json). +* Les identifiants utilisés pour authentifier le serveur au LDAP sont dans [ldap_credentials.json](../ldap_credentials.json). Ils prennent la forme suivante: +```json +{ + "dn": "uid=<username>,ou=eleves,dc=frankiz,dc=net", + "passwd": "<password>" +} +``` +On peut s'inspirer de [ldap_credentials_dist.json](../ldap_credentials_dist.json). +* Elle est importée dans l'application depuis [src/ldap/internal/config.ts](../src/ldap/internal/config.ts). +* Si la variable d'environnement `LDAP_URI` est définie, l'adresse où trouver le LDAP est remplacée. + +Le LDAP de Frankiz est sous OpenLDAP, qui a l'avantage d'être largement utilisée, documentée sur Internet, compatible avec des lecteurs génériques comme [JXplorer](http://jxplorer.org/) et gérant ses propres logs (voir [ce blog](https://www.vincentliefooghe.net/content/openldap-gestion-des-logs)). + +**Exemple** + +Si on développe en dehors du plâtal et qu'on ouvre un proxy SSH avec _port forwarding_ du LDAP de Frankiz (<frankiz.polytechnique.fr:389>) vers <localhost:8389>, on s'y connecte en définissant : `LDAP_URI=ldap://localhost:8389`, soit en faisant `export LDAP_URI=...`, soit en écrivant un fichier `.env`. Le fichier `config.js` s'occupe du reste. + +### Variables d'environnement + +| **Variable** | **Description** | **Défaut** | +| ------ | ------ | ----- | +| NODE_ENV | Type de l'environnement pour node | `development` | +| TARGET_ENV | Type de l'environnement ciblé : `development`, `staging` ou `production` | [.env](../.env) | +| HOST | Addresse sur laquelle le serveur écoute des requêtes. | [index.ts](../src/index.ts) | +| PORT | Port sur lequel le serveur écoute | [.env](../.env) | +| LDAP_URI | URI vers le serveur LDAP. | [ldap_config.json](../ldap_config.json) | +| DB_HOST | Addresse de la base de données. | [.env](../.env) | +| DB_USER | Utilisateur de la BDD | [.env](../.env) | +| DB_PASSWD | Mot de passe de la BDD | [.env](../.env) | + +Certaines variables doivent etre définies dans un fichier `.env`. On peut se contenter de recopier [.env_dist](../.env_dist) avec `cp .env_dist .env`. + +Par ailleurs, on peut définir ces variables d'environnement, **dans l'ordre décroissant de priorité :** + +* dans sa session de terminal (équivalent à `docker run -e KEY=value`) : + ```bash + export KEY=value + ``` +* au moment de lancer l'application : + ```bash + KEY=value npm start + ``` +* dans un fichier [`.env`](https://www.npmjs.com/package/dotenv) : + ```dotenv + KEY1=value1 + KEY2=value2 + ... + ``` + + +## Setup la BDD PostgreSQL La BDD PostgreSQL est utilisée pour stocker permissions, écoles des utilisateurs, annonces et événements. Créer un rôle PostgreSQL "sigma" : @@ -70,10 +135,13 @@ Créer une base de données PostgreSQL "sigma_dev" : createdb sigma_dev -U sigma -W ``` - Si vous n'arrivez pas à vous connecter (`createdb: could not connect to database template1: FATAL: Peer authentication failed for user`) : mettre à jour votre fichier `pg_hba.conf`. - - voir https://stackoverflow.com/questions/1471571/how-to-configure-postgresql-for-the-first-time -- Si vous souhaitez utiliser d'autres noms que "sigma" et "sigma_dev" : ça ne pose pas de problème, il vous faudra simplement modifier `../db/knexfile.js` et `../db/knex_init.js`. + - `sudo nano /etc/postgresql/<version>/main/pg_hba.conf` (en tant qu'utilisateur normal) + - remplacer tous les `peer` par `md5` + - redémarrer le serveur postgres : `sudo /etc/init.d/postgresql restart` +- Si vous souhaitez utiliser d'autres noms que "sigma" et "sigma_dev" : ça ne pose pas de problème, il vous faudra simplement modifier [.env](../.env). +- Sortir de l'utilisateur `postgres` avec CTRL + d -Exécuter les *migrations* et les *seeds* de knex : +Exécuter les *migrations* et les *seeds* de knex (dans le dossier `db`) : ```bash # construire le schéma de la BDD, i.e. définir les tables et leur structure. knex migrate:latest @@ -84,7 +152,7 @@ knex seed:run Voilà , vous avez une base de données à jour ! -### Démarrer le serveur +## Démarrer le serveur Dire à webpack de build le projet (build le bundle `../build/bundle.js`) : ```bash npm run dev # en mode developpement @@ -126,65 +194,19 @@ Les plus importants sont détaillées ci-dessous : - `npm run dev` : idem, mais en mode développement - `npm run watch` : idem, mais retranspile automatiquement dès que le code est modifié. - `npm run start` : lancer un serveur Node avec nodemon +- `npm run start_prod` : lancer le serveur avec Node - `npm run doc` : générer la doc JSDoc -- `npm run lint` : vérifier la syntaxe de tous les fichiers .js et .ts du dossier src/ +- `npm run lint` : discontinué +- `npm run eslint` : vérifier la syntaxe de tous les fichiers .js du dossier src/ +- `npm run tslint` : vérifier la syntaxe de tous les fichiers .ts du dossier src/ +- `npm run tsfix` : vérifie et corrige +- `npm run tsc` : compile le code TypeScript +- `npm run test` : démarre les tests unitaires `npm run start` démarre en fait le serveur buildé [`build/bundle.js`](../build/bundle.js) avec [nodemon](https://nodemon.io/), un outil de dév qui le redémarre automatiquement après toute modification *du bundle*. Donc, lancer `npm run watch` dans un terminal et `npm run start` dans un autre permet de rebuilder **et** relancer automatiquement le serveur, après toute modification *du code source*. -## Configuration -L'API est conçue pour êtes modulaire et pour fonctionner dans plusieurs environnements. - -On peut donc le configurer via des fichiers ou des variables d'environnement. - -### Configuration LDAP -L'API de Sigma nécessite de se connecter au LDAP Frankiz, à la fois pour obtenir des données et pour l'authentification des utilisateurs. Cela est fait à l'aide de la librairie [ldapjs](http://ldapjs.org) pour faire les requêtes au LDAP et [passportJS](http://www.passportjs.org/) pour l'authentification. - -* La configuration LDAP de base se situe dans [ldap_config.json](../ldap_config.json). -* Les identifiants utilisés que authentifier le serveur au LDAP sont dans [ldap_credentials.json](../ldap_credentials.json). Ils prennent la forme suivante: -```json -{ - "dn": "uid=<username>,ou=eleves,dc=frankiz,dc=net", - "passwd": "<password>" -} -``` -* Elle est importée dans l'application depuis [src/ldap/internal/config.ts](../src/ldap/internal/config.ts). -* Si la variable d'environnement `LDAP_URI` est définie, l'adresse où trouver le LDAP est remplacée. - -Le LDAP de Frankiz est sous OpenLDAP, qui a l'avantage d'être largement utilisée, documentée sur Internet, compatible avec des lecteurs génériques comme [JXplorer](http://jxplorer.org/) et gérant ses propres logs (voir [ce blog](https://www.vincentliefooghe.net/content/openldap-gestion-des-logs)). - -**Exemple** - -Si on développe en dehors du plâtal et qu'on ouvre un proxy SSH avec _port forwarding_ du LDAP de Frankiz (<frankiz.polytechnique.fr:389>) vers <localhost:8389>, on s'y connecte en définissant : `LDAP_URI=ldap://localhost:8389`, soit en faisant `export LDAP_URI=...`, soit en écrivant un fichier `.env`. Le fichier `config.js` s'occupe du reste. - -### Variables d'environnement - -| **Variable** | **Description** | **Défaut** (`ldap_config.json`) | -| ------ | ------ | ----- | -| LDAP_URI | URI vers le serveur LDAP. | <ldap://frankiz.eleves.polytechnique.fr:389> | -| TARGET_ENV | Type de l'environnement ciblé : `development`, `staging` ou `production` | `development` | -| HOST | Addresse sur laquelle le serveur écoute des requêtes. | `localhost` en développement, `0.0.0.0` en staging/prod. | -| DB_HOST | Addresse de la base de données. | `localhost` ou `129.104.201.10` en staging/prod. | -| DB_PASSWD | Mot de passe de la BDD | `password` | - -On peut définir ces variables d'environnement, **dans l'ordre décroissant de priorité :** - -* dans sa session de terminal (équivalent à `docker run -e KEY=value`) : - ```bash - export KEY=value - ``` -* au moment de lancer l'application : - ```bash - KEY=value npm start - ``` -* dans un fichier [`.env`](https://www.npmjs.com/package/dotenv) : - ```dotenv - KEY1=value1 - KEY2=value2 - ... - ``` - ## Panneau d'administration Il est accessible par navigateur au path [/adminview/admin](localhost:3000/adminview/admin) ; n'importe quel path devrait rediriger dessus. diff --git a/assets/LDAPGroup.png b/assets/LDAPGroup.png new file mode 100644 index 0000000000000000000000000000000000000000..539fb1b637a38e70f129af814dba580734e52fc7 Binary files /dev/null and b/assets/LDAPGroup.png differ diff --git a/assets/LDAPUseCase.PNG b/assets/LDAPUseCase.PNG new file mode 100644 index 0000000000000000000000000000000000000000..6aae00183835ea38cf8255669f30f7450fd0ef5b Binary files /dev/null and b/assets/LDAPUseCase.PNG differ diff --git a/assets/LDAPUser.png b/assets/LDAPUser.png new file mode 100644 index 0000000000000000000000000000000000000000..69296169c96a45c9edd7c76be9d625fb341e14e6 Binary files /dev/null and b/assets/LDAPUser.png differ diff --git a/assets/LDAP_API.png b/assets/LDAP_API.png new file mode 100644 index 0000000000000000000000000000000000000000..af9bd2dccb790afa275c2d0d36f544c75974d940 Binary files /dev/null and b/assets/LDAP_API.png differ diff --git a/db/knex_router.ts b/db/knex_router.ts index 34962cb8ef2c08b4e5682e2d959e2e4f63f2ca5f..3ce9bf2b228a4d96042af36d9033e3e280147a1e 100644 --- a/db/knex_router.ts +++ b/db/knex_router.ts @@ -3,7 +3,7 @@ */ require('dotenv').config(); -const environment = process.env.TARGET_ENV || 'development'; +const environment = process.env.TARGET_ENV; export const config = require('./knexfile')[environment]; console.log("Running Knex configuration '%s'", environment); diff --git a/db/knexfile.js b/db/knexfile.js index a439284e0e14dd16e2a64f497ccb8cbe580687f0..8b190e33fb928c76aba5262e0d191844825f7e0d 100644 --- a/db/knexfile.js +++ b/db/knexfile.js @@ -8,8 +8,8 @@ * et c'est knex_router.js qui donne la configuration de knex.js à proprement parler (i.e. les méthodes knex.insert(...) dans le code javascript) * @author manifold */ -require('dotenv').config(); const path = require('path'); +require('dotenv').config({ path: path.resolve('..', './.env') }); const knexConfig = { migrations: { @@ -26,8 +26,8 @@ module.exports = { client: 'pg', connection: { host: 'localhost', - user: process.env.DB_USER || 'sigma', - password: process.env.DB_PASSWD || 'sigmapw', + user: process.env.DB_USER, + password: process.env.DB_PASSWD, database: 'sigma_dev', charset: 'utf8' }, @@ -36,9 +36,9 @@ module.exports = { staging: { client: 'pg', connection: { - host: process.env.DB_HOST || '129.201.104.10', - user: process.env.DB_USER || 'sigma', - password: process.env.DB_PASSWD || 'password', + host: process.env.DB_HOST, + user: process.env.DB_USER, + password: process.env.DB_PASSWD, database: 'sigma_staging', charset: 'utf8' }, diff --git a/db/migrations/20190202114345_create_announcements_authors.js b/db/migrations/20190202114345_create_announcements_authors.js new file mode 100644 index 0000000000000000000000000000000000000000..e3c8ee1b3c6a23a39d15b9bc59da00a0be2b23d3 --- /dev/null +++ b/db/migrations/20190202114345_create_announcements_authors.js @@ -0,0 +1,18 @@ + +exports.up = function (knex, Promise) { + return knex.schema.createTable('announcements_authors', function (table) { + table.increments('id'); //autoincrementing (non-nullable) primary key + + table.integer('mid').notNullable() + .references('mid').inTable('messages_announcements') + .onDelete('CASCADE'); //if announcement is deleted, also delete authors + + table.string('gid', 128).notNullable() + .references('gid').inTable('groups') + .onDelete('CASCADE'); //if group is deleted, also delete authors + }); +}; + +exports.down = function (knex, Promise) { + return knex.schema.dropTable('announcements_authors'); +}; diff --git a/db/migrations/20190202114346_create_announcements_recipients.js b/db/migrations/20190202114346_create_announcements_recipients.js new file mode 100644 index 0000000000000000000000000000000000000000..dc30eab645076009cc7e49a780307b4925a01f72 --- /dev/null +++ b/db/migrations/20190202114346_create_announcements_recipients.js @@ -0,0 +1,18 @@ + +exports.up = function (knex, Promise) { + return knex.schema.createTable('announcements_recipients', function (table) { + table.increments('id'); //autoincrementing (non-nullable) primary key + + table.integer('mid').notNullable() + .references('mid').inTable('messages_announcements') + .onDelete('CASCADE'); //if announcement is deleted, also delete recipients + + table.string('gid', 128).notNullable() + .references('gid').inTable('groups') + .onDelete('CASCADE'); //if group is deleted, also delete recipient + }); +}; + +exports.down = function (knex, Promise) { + return knex.schema.dropTable('announcements_recipients'); +}; diff --git a/db/migrations/20190202114347_create_events_authors.js b/db/migrations/20190202114347_create_events_authors.js new file mode 100644 index 0000000000000000000000000000000000000000..1619ccacf96cabe2725d4d92cce5bddc0099267c --- /dev/null +++ b/db/migrations/20190202114347_create_events_authors.js @@ -0,0 +1,18 @@ + +exports.up = function (knex, Promise) { + return knex.schema.createTable('events_authors', function (table) { + table.increments('id'); //autoincrementing (non-nullable) primary key + + table.integer('mid').notNullable() + .references('mid').inTable('messages_events') + .onDelete('CASCADE'); //if event is deleted, also delete authors + + table.string('gid', 128).notNullable() + .references('gid').inTable('groups') + .onDelete('CASCADE'); //if group is deleted, also delete authors + }); +}; + +exports.down = function (knex, Promise) { + return knex.schema.dropTable('events_authors'); +}; diff --git a/db/migrations/20190202114348_create_events_recipients.js b/db/migrations/20190202114348_create_events_recipients.js new file mode 100644 index 0000000000000000000000000000000000000000..fc8a157b18e50f7ac68d6a2334581e356d5c1b89 --- /dev/null +++ b/db/migrations/20190202114348_create_events_recipients.js @@ -0,0 +1,18 @@ + +exports.up = function (knex, Promise) { + return knex.schema.createTable('events_recipients', function (table) { + table.increments('id'); //autoincrementing (non-nullable) primary key + + table.integer('mid').notNullable() + .references('mid').inTable('messages_events') + .onDelete('CASCADE'); //if event is deleted, also delete recipients + + table.string('gid', 128).notNullable() + .references('gid').inTable('groups') + .onDelete('CASCADE'); //if group is deleted, also delete recipient + }); +}; + +exports.down = function (knex, Promise) { + return knex.schema.dropTable('events_recipients'); +}; diff --git a/ldap_config.json b/ldap_config.json index 0529dc3d918958e2b832eca4065791744f0d2644..ba56ad7d85030d2c3f9098bdd84dd5e40f25b067 100644 --- a/ldap_config.json +++ b/ldap_config.json @@ -1,55 +1,58 @@ { "comment_1": "Tout ce fichier sert à protéger les vrais champs du LDAP dans les scripts dans src/ldap. Les champs ci-dessous contiennent le nécessaire à une première connexion par exemple.", "comment_tmp": "Passer en LDAPS ASAP.", - "server_prod": "ldap://frankiz.eleves.polytechnique.fr:389", - "server_dev": "ldap://129.104.201.10:389", + "comment_1bis": "Ce fichier est importé par src/ldap/internal/config.ts ; comme indiqué dans config.ts, la présence d'une variable d'environnement correspondante peut override les paramètres donnés ici.", + "server_prod_old": "ldap://frankiz.eleves.polytechnique.fr:389", + "server_dev_old": "ldap://localhost:389", + "server_prod": "ldap://ldap.eleves.polytechnique.fr:389", + "server_dev": "ldap://ldap.eleves.polytechnique.fr:389", "comment_2": "Noms de domaines dans LDAP ; le niv d'après est en uid=, voir Wikipedia", - "dn_groups":"ou=groups,dc=frankiz,dc=net", - "dn_users": "ou=eleves,dc=frankiz,dc=net", - "key_id": "uid", + "dn":{ + "group":"ou=groups,dc=frankiz,dc=net", + "user": "ou=eleves,dc=frankiz,dc=net" + }, "comment_3": "Placeholders et indications de contenu de certains champs du LDAP généré par frankiz pour les utilisateurs", "user": { "uid": "uid", - "photo": "jpegPhoto", + "password": "userPassword", "givenName": "givenName", "lastName": "sn", - "fullName": "cn", - "cleanFullName": "gecos", - "nickname": "displayName", - "birthdate": "brBirthdate", - "nationality": "country", - "promotion": "brPromo", + "nickname": "pseudonym", + "gender": "gender", + "photo": "urlPhoto", "phone": "telephoneNumber", - "adress": "brRoom", - "id": "uidNumber", - "password": "userPassword", - "idNum": "gidNumber", - "directory": "homeDirectory", + "adress": "roomNumber", + "mail": "email", + "birthdate": "birthdate", + "nationality": "nationality", "login": "loginShell", - "readPerm": "brNewsReadAccess", - "writePerm": "brNewsPostAccess", - "mail": "mail", - "ips": "brIP", - "forlifes": "brAlias", - "groups": "brMemberOf", - "classes": "objectClass" + "directory": "homeDirectory", + "classes": "objectClass", + "id": "uidNumber", + "cleanFullName": "gecos", + "admins": "adminOf", + "speakers": "speakerOf", + "members": "memberOf", + "followers": "followerOf" }, - "comment_4": "Placeholders et indications de contenu de certains champs du LDAP généré par frankiz pour les groupes", + "comment_4": "Placeholders et indications de contenu de certains champs du LDAP généré par frankiz pour les groupes (childs TBA)", "group": { - "gid": "uid", - "name": "brAlias", - "type": "brNS", - "members": "restrictedMemberUid", - "admins": "memberUid", + "gid": "cn", + "name": "sn", + "site": "website", + "description": "description", + "category": "groupCategory", + "admins": "admin", + "speakers": "speaker", + "members": "member", + "followers": "follower", "adress":"cn", - "idNumber": "uidNumber", - "idNumber2": "gidNumber", - "login": "loginShell", + "idNumber": "gidNumber", "password": "userPassword", - "directory": "homeDirectory", - "cleanFullName": "gecos", - "classes": "objectClass" + "logo": "urlPhoto", + "classes": "objectClass", + "parents": "parent" } } \ No newline at end of file diff --git a/ldap_credentials_dist.json b/ldap_credentials_dist.json new file mode 100644 index 0000000000000000000000000000000000000000..46253a9513b3bbbdf5bee96aea662eb9bba46c7e --- /dev/null +++ b/ldap_credentials_dist.json @@ -0,0 +1,6 @@ +{ + "README": "Modele du fichier 'ldap_credentials.json', requis par src/ldap/. Copier ce fichier en le renommant 'ldap_credentials.json' (le placer a la racine du repo). A copier et renommer en local.", + + "dn": "uid=sigma,ou=services,dc=frankiz,dc=net", + "passwd": "&vH}x%7;FK3j53eX" +} diff --git a/notes/CONTRIBUTING.md b/notes/CONTRIBUTING.md index c61002fed3ae236348023c56a0a65f9e51acada4..a75a55eba3e3bb6b8f83414805e114ab988ababd 100644 --- a/notes/CONTRIBUTING.md +++ b/notes/CONTRIBUTING.md @@ -15,9 +15,10 @@ Ainsi, l'idée est de conserver le LDAP Frankiz mais pas sa BDD, inutilisable ca ### L'idée Il s'agit de reprendre un nouveau Frankiz plus moderne et clairement documenté, mais pas seulement. Plusieurs fonctionnalités intéressantes sont envisageables : -- gestion des inscriptions (notamment avec nombre de places limité), -- inscription par trigramme, -- minimodules ou des greffons à étudier +- fil d'actualité avec filtre personnalisable +- gestion des inscriptions (notamment avec nombre de places limité) +- inscription par trigramme +- minimodules ou greffons à étudier - intégration des événements d'autres écoles ## Description et actualité des branches @@ -61,13 +62,9 @@ Certaines anciennes branches, fraîchement mergées, sont décrites ci-dessous. - branche sur laquelle akka vodol fait tout son travail : implémentation des resolvers pour le nouveau schéma propre (le schéma "_wish_list"). Comme ça, il peut faire d'éventuelles modifications du schéma sans faire chier les autres, et ensuite on valide ensemble pour merge. -#### LDAP-refacto - -Branche obsolète à supprimer. - #### unit-tests -- TODO (@akka vodol tu peux expliquer ici a quoi sert cette branche ? et le cas échéant, la merge dans master ?) +- branche de test-unitaires ## Structure du dossier @@ -259,4 +256,4 @@ Le BR dispose de plusieurs Virtual Machines (VM) pour faire tourner les outils e Le BR 2016, plus particulièrement Wilson Jallet, Guillaume Wang, Quentin Chevalier et Anatole Romon -Le BR 2017, plus particulièrement Olivér Facklam, Grégoire Grzeckowicz et Hadrien Renaud +Le BR 2017, plus particulièrement Olivér Facklam, Grégoire Grzeckowicz et Hadrien Renaud \ No newline at end of file diff --git a/notes/hist.json b/notes/hist.json new file mode 100644 index 0000000000000000000000000000000000000000..57723b6c4ed07d8642134189816ad96249cb9540 --- /dev/null +++ b/notes/hist.json @@ -0,0 +1,8 @@ +{ + "title": "Historiques", + "children": [ + "hist_graphql", + "hist_ldap", + "hist_rights" + ] +} \ No newline at end of file diff --git a/notes/hist.md b/notes/hist.md new file mode 100644 index 0000000000000000000000000000000000000000..84ddc0088c8613dda92fcdb0776e8546cc6f5956 --- /dev/null +++ b/notes/hist.md @@ -0,0 +1,4 @@ +Historiques +=== + +Le projet sigma a un passif. C'est le travail accumulé de plusieurs promotions qui ont été obligé de faire un certain nombre de choix techniques ou purement esthétiques. Avant de pourrir leur travail conscrit, lis ces quelques lignes. \ No newline at end of file diff --git a/notes/hist_graphql.json b/notes/hist_graphql.json new file mode 100644 index 0000000000000000000000000000000000000000..17834f602fbd2873a6c2c8b66454aaacee9cbb5d --- /dev/null +++ b/notes/hist_graphql.json @@ -0,0 +1,4 @@ +{ + "title": "Historique GraphQL, ou comment gérer les relations de couple entre front et back-end", + "children": [] +} \ No newline at end of file diff --git a/notes/hist_graphql.md b/notes/hist_graphql.md new file mode 100644 index 0000000000000000000000000000000000000000..f23b5ba184fe1ab4b4f54a1a85f211df05deac9b --- /dev/null +++ b/notes/hist_graphql.md @@ -0,0 +1,106 @@ +Remarques sur *l'implémentation*, explication de choix de design... + +Pour des commentaires sur la définition du schéma, se reporter plutôt aux commentaires en en-tête des fichiers `actions.graphql` et `objects.graphql`. + +Pour des explications plus high-level sur la gestion des droits et les authorizations sur Sigma, voir le memo idoine {@tutorial hist_rights}. + +## Structure du dossier `src/graphql` + +```bash +graphql +├── models +│ ├── authorization.ts +│ ├── groupModel.ts +│ ├── messageModel.ts +│ ├── requestModel.ts +│ ├── tools.ts +│ └── userModel.ts +├── object_resolvers +│ ├── groups.ts +│ ├── messages.ts +│ ├── requests.ts +│ └── users.ts +├── resolvers.ts +├── schema.js +└── typeDefs + ├── actions.graphql + ├── objects.graphql + └── queries.d.ts +``` + +Les sections suivantes expliqueront la logique des models et object_resolvers ; pour l'instant,expliquons quelques points simples. + +### "Points d'entrée" +`graphql/schema.js` exporte tout le schéma GraphQL, utilisé pour configurer ApolloServer dans `app.ts`. + +A la réception d'une requête GraphQL, avant de la resolver, une instance de chaque object model de `graphql/models/` est créée, et passée dans le context. Ceci est aussi effectué dans `app.ts` (`const context = ...`). + +### La définition du schéma : `src/graphql/typeDefs` + +C'est assez straightforward quand on connaît les bases de GraphQL... + +`queries.d.ts` définit l'interface Typescript `Context`. + +### Export des resolvers `graphql/resolvers.ts` + +Du point de vue de `graphql/schema.js`, qui les importe, le fichier `graphql/resolvers.ts` exporte bien tous les resolvers de tous les types du schéma GraphQL. +Pourtant, on ne définit dans `graphql/resolvers.ts` que les resolvers pour les types Query et Mutations. +En effet on exploite les default resolvers fournis par Apollo Server (le deuxième point) : + +> Explicit resolvers are not needed for every type, since Apollo Server provides a default that can perform two actions depending on the contents of parent: +> - Return the property from parent with the relevant field name +> - Calls a function on parent with the relevant field name and provide the remaining resolver parameters as arguments +https://www.apollographql.com/docs/apollo-server/v2/essentials/data.html#default + +Dans notre cas, le type de retour de chaque resolver est un objet JS (Group, Message, Request ou User) défini dans un des fichiers de `graphql/object_resolvers/` ; donc les méthodes des classes Group, Message, Request et User dont le prototype est (parent, args, context: Context, info) sont utilisées comme resolvers de l'objet GraphQL respectif. + +(Les sections suivantes donnent plus de précisions sur la logique derrière ce dernier paragraphe.) + + +## Resolvers/Models/Connectors + +Les notions de models et de connectors sont assez communes en développement web. Une définition informelle appliquée au contexte de GraphQL est donnée ici : + +https://blog.apollographql.com/how-to-build-graphql-servers-87587591ded5 +> Model: a set of functions to read/write data of a certain GraphQL type by using various connectors. Models contain additional business logic, such as permission checks, and are usually application-specific. + +> Connector: a layer on top of a database/backend driver that has GraphQL-specific error handling, logging, caching and batching. Only needs to be implemented once for each backend, and can be reused in many apps + +> By using models and connectors, my resolvers turned into simple switches that map inputs and arguments to a function call in the underlying model layer, where the actual business logic resides. + +> Note: To be clear, models and connectors aren’t abstractions that are built into GraphQL, but they emerge as a natural way to structure code in a GraphQL server. + +### Connectors + +Dans notre cas, on utilise à la fois une base de données propre à Sigma (PostgreSQL, manipulée avec Knexjs) et un LDAP (manipulé avec les fonctions de `src/ldap/export/`, développées par Quentin Chevalier, qu'il appelle son "API LDAP"). + +Knexjs et l'"API LDAP" sont les équivalents des Connectors pour notre projet. Pas besoin de se forcer à faire une couche supplémentaire, ça ne serait pas utile. + + +### Les resolvers des actions : `graphql/resolvers.ts` + +### Les resolvers des objets : `graphql/object_resolvers/` + +Les classes JS définies dans les fichiers de `graphql/object_resolvers/` jouent à la fois le rôle de resolvers (plus précisément, ont des méthodes qui sont utilisées comme resolvers), et de return type pour les resolvers. +C'est ceci qui permet d'exploiter à fond les defaults resolvers d'Apollo Server. + +Une bonne façon de le voir est de dire que : +- du point de vue de l'export du schéma (donc de `schema.js` et `resolvers.ts`), ces fichiers servent à définir les resolvers, tout simplement +- du point de vue des autres fichiers qui les importent, ces fichiers définissent des return types de resolvers. + +### Models : `graphql/models` + +Comme indiqué plus haut, une instance de chaque object model est créée et passée dans le context, à chaque réception d'une requête GraphQL. En fait, puisque les constructeurs ne prennent en paramètre que l'uid de l'utilisateur qui fait la requête, on peut dire qu'un set de models est créé pour chaque utilisateur. + +Autrement dit, chaque utilisateur a ses propres "data accessors", sa propre "vue" de la BDD, personnalisée pour prendre en compte ses memberOfs. + + + +## Implémentation de la gestion des authorizations + +En anglais, authori*s*ation est une orthographe valide, mais pour plus d'homogénéité et pour reprendre l'usage habituel sur internet, on utilisera l'orthographe américaine authori*z*ation. + +Comme déjà indiqué plus haut, pour des explications plus high-level sur la gestion des droits et les authorizations sur Sigma, voir le memo idoine (`memo_sigma_rights.md`). + +### authorization.ts + diff --git a/notes/hist_ldap.json b/notes/hist_ldap.json new file mode 100644 index 0000000000000000000000000000000000000000..cbe5b98108928441e56bb2810c66c0813a4c1a2a --- /dev/null +++ b/notes/hist_ldap.json @@ -0,0 +1,4 @@ +{ + "title": "Historique de l'API LDAP", + "children": [] +} \ No newline at end of file diff --git a/notes/hist_ldap.md b/notes/hist_ldap.md new file mode 100644 index 0000000000000000000000000000000000000000..52c0f8bbbc8bbb8c937216b428f08e3ecf1e4ce6 --- /dev/null +++ b/notes/hist_ldap.md @@ -0,0 +1,39 @@ +## Sur le LDAP Frankiz + +A l'origine Frankiz, le prédécesseur de sigma, avait sa propre base de données qu'il importait toutes les 3h dans un LDAP énorme et sale, qui contenait le strict minimum. Ce LDAP s'est révélé très utile à différents sites binets qui ont fait un usage très libre de cette ressource. + +De sorte que quand il fallut remplacer Frankiz, la destruction du LDAP n'était pas possible sans revoir plusieurs sites binets (à voir, le CAS était peut-être une solution suffisante). On a donc choisi de tuer la BDD Frankiz, mais seulement après avoir considérablement enrichi le LDAP pour en faire la BDD utilisateurs et groupes principale de sigma. + +Une documentation vieillissante est disponible sur le [`wikix`](https://wikibr.binets.fr/Admin:LDAP) par rapport au LDAP de Frankiz. + +Le BR2017 a mené un gros travail de réorganisation du LDAP donc beaucoup d'informations sur le wikix ne seront plus valides. + +### Nouvelle organisation du LDAP + +Le LDAP a été significativement enrichi depuis Frankiz, puisqu'il contient la majeure partie des données utilisateurs et groupes de sigma. Les champs parent et child permettent aux resolvers afférents de faire descendre les admins et remonter les membres, mais n'a pas d'influence à l'intérieur de l'API LDAP. + + + + + + + +#### Configuration + +L'équivalence pratique entre champs du LDAP et champs du code est dans le fichier de configuration [`ldap_config`](../ldap_config.json). Idéalement, ce .json serait ensuite porté en une calsse dynamique dans le code. En atendant une structure pareille, on se contentera des structures de données décrites dans [`config`](../src/ldap/internal/config.ts). + +#### Une structure particulière + +Les admins et membres sont de deux types ; les admins et membres stricts, acceptés par un administrateur dans le groupe, et les admins et membres hérités, qui ont rejoint ce groupe en remontant ou en descendant la structure de parenté ; voir {@tutorial hist_rights}. + +### Etat de l'API + +Cette API est voulue comme la plus simple et la plus minimaliste possible ; en effet, elle sera à réimplémenter sur toutes les instances différentes de sigma pour s'adapter aux structures de données des différentes écoles qui choisissent d'adopter sigma. On peut administrer des groupes depuis sigma, mais pour s'interfacer d'instances à instances seules deux fonctions sont indispensables ; peek et search. + +Cette API, bien que relativement naïve, doit être capable de garder la syn,chronisation entre les deux arbres du LDAP et ainsi que les problèmes de récursion posées par le choix de la structure en admin descendant et membres montant. + + + +Le détail de chaque fonction est disponible dans la documentation JSDOC : ([`User`](../doc/LDAP.User.html) et [`Group`](../doc/LDAP.Group.html)). + +La lutte contre les injections est faite au plus bas niveau possible en utilisant [`ldapEscape`](https://www.npmjs.com/package/ldap-escape) directement dans la classe [`Basics`](../doc/LDAP.Basics.html). En effet, les injections LDAP sont relativement voyantes et ne peuvent pas se faire avec des caractères usuels. \ No newline at end of file diff --git a/notes/hist_rights.json b/notes/hist_rights.json new file mode 100644 index 0000000000000000000000000000000000000000..0dd11135e2bb0f6720478e71058fbd07da9996b9 --- /dev/null +++ b/notes/hist_rights.json @@ -0,0 +1,4 @@ +{ + "title": "Bilan des droits sur sigma", + "children": [] +} \ No newline at end of file diff --git a/notes/hist_rights.md b/notes/hist_rights.md new file mode 100644 index 0000000000000000000000000000000000000000..cab6b0fde8f85f30a991025645658d6862190b3a --- /dev/null +++ b/notes/hist_rights.md @@ -0,0 +1,113 @@ +## Overview + +Chaque utilisateur a un certain niveau de droit sur chaque groupe. Ce niveau de droit indique ce qu'il a le droit de savoir et de faire. + +### Les differents niveaux de droit [specification de actions.graphql] +*Par rapport à un groupe donné*, un user peut avoir différents niveaux de droits : +- none : ne sait meme pas que le groupe existe, aucun autre droit (typiquement, une connection où l'utilisateur ne s'est pas authentifié) +- authenticated : sait que le groupe existe, aucun autre droit (une connection on-platal sans auth, ou une connection authentifiée) +- viewer : le user a aussi accès à l'activité publique du groupe : frontpage, Q&A, liste des membres, speakers et admins, Message dont le groupe est destinataire +- member : le user a aussi acces à l'activité interne du groupe : les PrivatePost, ainsi que les Message dont le groupe est auteur +- speaker : le user peut aussi parler au nom du groupe. Il a le droit de publier des annonces et d'organiser des évènements +- admin : le user a tous les droits sur le groupe + +### Le graphe organique des groupes + +Les champs `parent` et `children` de l'objet `Group` dans le schéma GraphQL définissent un graphe des groupes, appelé *graphe organique des groupes* car il définit les héritages de droits d'admin (l'admin d'un groupe peut administrer les groupes enfants) (de la même facon qu'une hiérarchie organique militaire). Ce graphe ne doit pas contenir de cycles, i.e. doit être un arbre. + +### Conditions pour les niveaux de droit + +Un des rôles du *graphe organique des groupes* est de définir le niveau de droit des users pour chaque groupe. + +D'abord, petit détail de terminologie : les cinq niveaux de droits sont inclus les uns dans les autres (un speaker est aussi un viewer, par ex.) (sauf pour les permissions héritées) + +Plus précisément, on a les inclusions suivantes : admin strict > speaker > membre strict > membre hérité > viewer > authenticated. +Il n'y a que admin hérité qui n'est pas nécessairement inclus dans les autres niveaux de droits. + +Dans la BDD sous-jacente, il faut que pour chaque groupe, on ait admin > speaker > member. + +Détaillons ici les conditions exactes pour avoir un niveau de droit donné. + +#### Pour les groupes simples +- Member : + - Un user est membre strict du groupe G s'il est member de G selon la BDD sous-jacente. + - Un user est membre hérité du groupe G s'il est membre strict d'un de ses descendants. +- Speaker : un user est speaker du groupe G s'il est speaker de G selon la BDD. Pas de notion d'héritage de speaker. +- Admin : + - Un user est admin strict du groupe G s'il est admin de G selon la BDD. + - Un user est admin hérité du groupe G s'il est admin strict d'un de ses ascendants. +- Viewer : un user est viewer du groupe G + - s'il est membre hérité de G. + - s'il est membre hérité d'un groupe immédiatement parent de G (one-edge-down visibility), ou + - s'il est membre hérité d'un groupe faisant partie du champ "visibilityEdge" de G + - s'il est membre d'un métagroupe dont G est membre (implicit visibility-edges). +- Dans tous les autres cas, le user a le niveau de droits "none" ou "authenticated", selon le cas de figure. + +#### Pour les méta-groupes +- Un user est membre d'un méta-groupe G s'il est membre (hérité) d'un groupe simple dans G. +- Un user est speaker d'un méta-groupe G s'il est speaker d'un groupe simple dans G. +- Un user est admin d'un méta-groupe G s'il est admin (hérité) d'un groupe simple dans G. +- Un user est viewer d'un méta-groupe G s'il est viewer d'un groupe simple dans G. + +L'autre rôle du *graphe organique des groupes* est de permettre l'administration "en cascade" des groupes enfants. + +Si un groupe est le parent d'un autre, alors les admins du groupe parent sont admins (hérités) du groupe enfant. Exemples : +- BR est parent de Chocapix. L'admin de Chocapix est parti en vacances. L'admin de BR peut, en tant qu'admin (hérité) de Chocapix, faire ce qu'il a à faire, sans attendre le retour du respo Chocapix. +- Cotisants-Kès est parent de Troll'X. Troll'X fait n'importe quoi (en floodant de Messages par ex). Les admins de Cotisants-Kès (les kessiers) peuvent, comme ils sont admins hérités de Troll'X, stopper les dégâts. + +Remarque sur speaker : +Il s'agit d'un nouveau niveau de droit par rapport à Frankiz 3.0 ; qui est a présent implémenté sur le LDAP bloaziadur. + +## Dans l'implémentation + +Le système GraphQL est pensé comme l'interface par laquelle les utilisateurs interagissent avec sigma, les graphismes en moins. Le client peut envoyer tout type de requête. C'est au niveau des resolvers que les permissions sont gérées. D'où le @rights + +### Dans les resolvers GraphQL : le tag @rights +Utilise par JSDoc +Le tag @rights est la gestion des autorisations. +Utilise dans resolvers.ts + +Certaines fonctions de connectors effectuent des vérifications d'authorizations avant de renvoyer une réponse, d'autres non. Pour être sur qu'on ne renvoie jamais de réponse sans avoir au préalable effectué les bonnes vérifications, chaque fonction possède dans sa description un attribut droit, qui décrit les droits que requiert cette fonction. + +La valeur de @rights peut être : +- `super` - la fonction n'effectue aucune vérification, et renvoie le resultat demandé +- `admin( groupID )` - la fonction ne fait que ce qu'un admin du groupe indiqué aurait le droit de faire +- `speaker( groupUID )`, `member( groupUID )`, `viewer( groupUID )` - même chose +- `user` - la fonction ne fait que ce que l'utiliateur a le droit de faire (vérifications via l'argument user) + +La procédure a suivre est la suivante : quand une fonction possède un certain niveau de droit, elle ne peut appeler une fonction possédant un niveau de droit plus large que si : +- 1- on a au préalable vérifié que l'utilisateur possédait effectivement ces droits. +*ou* +- 2- on s'est assuré que l'opération effectuée par cet appel particulier de la fonction était dans les droits de l'utilisateur + +D'un point de vue pratique : +- les **resolvers** doivent **vérifier** que le user possede les droits énoncés dans le tag @rights, avant de renvoyer un résultat / modifier la BDD. Ils vérifient aussi que le user possede les droits nécessaires pour appeler des fonctions dans les models. +- les fonctions dans les **models** peuvent **supposer** que les droits du tag @rights sont acquis, ie. qu'ils ont été vérifiés par la fonction appelante au préalable. + +#### Quel @rights donner a quels resolvers ? + +Les resolvers de base de mutation et query ont des droits user. + +Les fonctions qui ne modifient pas la BDD et ne renvoient pas de données sur la BDD n'ont pas de rights. + +### Le cas des Requests +cf `objects.graphql` + +Les Mutations concernant les *Requests* suivent à peu près toutes le schéma suivant : +- \<typeAuteur>Request\<NatureDeLaRequest>(auteur, destinataire, comment): Request +- accept\<NatureDeLaRequest>Request(request: ID!, comment: String): Boolean +- refuse\<NatureDeLaRequest>Request(request: ID!, comment: String): Boolean + - le paramètre est le rid de la Request à accepter ou refuser + - **seul les admins du groupe destinataire peuvent accepter ou refuser une Request** + +Les Mutations concernant les *Messages* suivent à peu près toutes le schéma suivant : +- create\<TypeDeMessage>(auteur, destinataire, title, content, etc.): \<TypeDeMessage> +- edit\<TypeDeMessage>(\<typeDeMessage>ToEdit: ID!): \<TypeDeMessage> +- remove\<TypeDeMessage>(\<typeDeMessage>ToRemove: ID!): Boolean + - = l'auteur supprime le message + - **pour les Messages où l'auteur est un utilisateur, seul l'auteur a le droit de remove son Message** + - **pour les Messages où l'auteur est un groupe, n'importe quel admin du groupe (ou speaker selon le cas) a le droit de remove le Message** +- censor\<TypeDeMessage>(\<typeDeMessage>ToCensor: ID!): Boolean + - = le groupe destinataire supprime le message + - **n'importe quel admin du groupe a le droit de censurer un Message qui lui est adressé** + - (le destinataire est un Group pour tous les Messages) diff --git a/notes/memo_jsdoc.json b/notes/memo_jsdoc.json index fc059053cd902176e1fa0a1e40aa52282e034375..0aefcd8dc1bcd6a07381c95944b4ac886d6b95fa 100644 --- a/notes/memo_jsdoc.json +++ b/notes/memo_jsdoc.json @@ -1,4 +1,4 @@ { - "title": "Memo JSDoc", + "title": "Memo JSDoc, le meilleur ami du newbie", "children": [] } \ No newline at end of file diff --git a/notes/memo_jsdoc.md b/notes/memo_jsdoc.md index 547eadb3011566674f921674e1e9946a0033aab0..e9ac628c289d2a2faa567fb9a017025a3e5e7ae8 100644 --- a/notes/memo_jsdoc.md +++ b/notes/memo_jsdoc.md @@ -1,4 +1,4 @@ -JSDoc, c'est l'outil de génération automatique de documentation. Il transforme des commentaires et des fichiers Markdown comme celui-ci en une masse de pages web lisibles même par un autiste semi-aveugle à quiil manquerait un module de sémantique. +JSDoc, c'est l'outil de génération automatique de documentation. Il transforme des commentaires et des fichiers Markdown comme celui-ci en une masse de pages web lisibles même par un autiste semi-aveugle à qui il manquerait un module de sémantique. La doc de JSDoc, paradoxalement un peu aride : [`Use JSDoc`](http://usejsdoc.org/) @@ -41,4 +41,6 @@ La factorisation de code dans des classes étant en soit une bonne pratique et p ### Les fichiers. md -JSDoc a deux façons simples d'intégrer des fichiers Mardown dans la doc ; un README en page d'accueil, ou un tutoriel comme celui-ci. Tous les tutoriels doivent être mis dans le même dossier avec des fichiers de config .json pour définir une arborescence de tutoriels propres. \ No newline at end of file +JSDoc a deux façons simples d'intégrer des fichiers Mardown dans la doc ; un README en page d'accueil, ou un tutoriel comme celui-ci. Tous les tutoriels doivent être mis dans le même dossier avec des fichiers de config .json pour définir une arborescence de tutoriels propres. + +N'hésitez pas à enrichir la documentation à votre tour, par des fichiers .md ou directement dans votre code ! \ No newline at end of file diff --git a/notes/memo_knexjs.json b/notes/memo_knexjs.json index 887d74bb75b48c0b7860316a35d9489ce39a1f51..e375581b497e4a0f1d9e1d528fc69d714ead8991 100644 --- a/notes/memo_knexjs.json +++ b/notes/memo_knexjs.json @@ -1,4 +1,4 @@ { - "title": "Memo knew.js", + "title": "Memo knew.js ou quand on a la felmme de faire du SQL", "children": [] } \ No newline at end of file diff --git a/notes/memo_knexjs.md b/notes/memo_knexjs.md index d15ec00acf6ad5658382b9eb1c9f3c8a700d0d26..cff213567e7bfb11d394a331402f9c69a68eb8b4 100644 --- a/notes/memo_knexjs.md +++ b/notes/memo_knexjs.md @@ -72,4 +72,4 @@ Solution : spécifier dans le schéma (fichiers migrations) ce qu'il faut faire On a défini les migrations (`./db/migrations/*`) en se basant sur le schéma GraphQL (`typeDefs.js`) (et pas l'inverse), ce qui se voit bien puisqu'on suit presque exactement ce dernier. **[spécifique à shitpost :]** -Un point particulier cependant : comme expliqué en commentaires du migration-file `./db/migrations/[timestamp]_create_comments.js`, on n'a pas déclaré le champ "forMessage" de la table "comments" comme ayant "messages.id" comme foreign key, car ce n'est pas possible avec PostgreSQL v10. +Un point particulier cependant : comme expliqué en commentaires du migration-file `./db/migrations/[timestamp]_create_comments.js`, on n'a pas déclaré le champ "forMessage" de la table "comments" comme ayant "messages.id" comme foreign key, car ce n'est pas possible avec PostgreSQL v10. \ No newline at end of file diff --git a/notes/memo_ldap.json b/notes/memo_ldap.json index e36839dfd17d86106cfb15eee97e1c1eb52c7e9e..a0627ac10cb6d0878bbc835eaaccbc1780875725 100644 --- a/notes/memo_ldap.json +++ b/notes/memo_ldap.json @@ -1,4 +1,4 @@ { - "title": "Memo LDAP", + "title": "Memo LDAP, ni BDD ni annuaire", "children": [] } \ No newline at end of file diff --git a/notes/memo_ldap.md b/notes/memo_ldap.md index a91b3ae7eec309fa9c3d4d31e621435f3df7d0ba..8d5179bebed5c8fe3af2965b948f90e4ae93d31b 100644 --- a/notes/memo_ldap.md +++ b/notes/memo_ldap.md @@ -2,12 +2,20 @@ LDAP signifie Lightweight Directory Access Protocol ; c'est donc un protocole, comme http, et pas une structure de données à proprement parler. Comme http, il fonctionne par chaîne de caractères appelés URI. La structure d'un LDAP est cependant forcément celle d'un arbre, avec une racine à la fin de l'URI et le noeud recherché à la fin. Par exemple "uid=louis.vaneau,ou=eleves,dc=frankiz,dc=net", qui permet d'accéder à la feuille associée à Louis Vaneau dans le LDAP de frankiz. -Il s'agit d'une structure particulièrement rigide mais efficace en lecture. Chaque noeud contient un certain nombre de champs qui ne sont pas nécessairement tous rempli, et qui n'ont pas forcément une seule variable par champ. +Il s'agit d'une structure particulièrement rigide mais efficace en lecture. Chaque noeud contient un certain nombre de champs qui ne sont pas nécessairement tous remplis, et qui n'ont pas forcément une seule variable par champ. Un LDAP est une structure parfaitement adapté à la réalisation d'un annuaire car pensé pour cela dès l'origine ; très efficace en lecture, il brille moins en écriture. -## Sur le LDAP Frankiz +La technologie est ancienne et bien connue. Le LDAP de Frankiz, OpenLDAP, contient beaucoup de fonctionnalités sympathique comme le hashage inclus des mots de passe avec salt conformément à l'état de l'art. -Une documentation vieillissante est disponible sur le [`wikix`](https://wikibr.binets.fr/Admin:LDAP). +### Un wrapper sympathique... -## Un wrapper sympathique +On accède sur un LDAP par des requêtes LDAP, d'où l'intérêt d'une bibliothèque comme [`ldap.js`](http://ldapjs.org/) qui fait office de traducteur javascript/LDAP, un peu comme knex et SQL. On s'intéressera particulièrement à la partie [`client`](http://ldapjs.org/client.html) qui est celle qui permet d'agir sur le LDAP. -On accède sur un LDAP¨par des requêtes LDAP, d'où l'intérêt d'une bibliothèque comme [`ldap.js`](http://ldapjs.org/) qui fait office de traducteur javascript/LDAP, un peu comme knex et SQL. On s'intéressera particulièrement à la partie [`client`](http://ldapjs.org/client.html) qui est celle qui permet d'agir sur le LDAP. \ No newline at end of file +Cette bibliothèque est reprise et re-wrappée dans la classe [`Basics`](../src/ldap/internal/basics.ts). + +### Pas complètement dépourvu de dangers ! + +Comme tous les protocoles, LDAP a ses failles. En particulier, il est possible d'injecter des commandes via un nom de domaine (Domain Name ou DN) ou un filtre (filter). Ces dangers sont adressés par sigma en utilisant la bibliothèque [`ldap-escape`](https://www.npmjs.com/package/ldap-escape). + +### Une interface graphique agréable + +Pour explorer un LDAP, vous pouvez utiliser [`JXplorer`](http://jxplorer.org/). Il s'agit d'un logiciel OpenSource en Java très imparfait mais qui permet de rapidement parcourir les champs d'un LDAP et de mener des petites recherches dessus. \ No newline at end of file diff --git a/notes/memo_postgresql.json b/notes/memo_postgresql.json index 5854303fa10a833546c5fe97ea09c1a1805ddb0b..7634a09c2fdd835ffeabd0d6677adeb6b3ae653b 100644 --- a/notes/memo_postgresql.json +++ b/notes/memo_postgresql.json @@ -1,4 +1,4 @@ { - "title": "Memo PostgreSQL", + "title": "Memo PostgreSQL, ou une technologie de base de données simple", "children": [] } \ No newline at end of file diff --git a/notes/memos.md b/notes/memos.md index 1f51b82463da51955169047ac4880058f5f2f2c7..8aab15325d1aeb03e41543b18dab7ee04a6ea0a3 100644 --- a/notes/memos.md +++ b/notes/memos.md @@ -1,4 +1,4 @@ Mémos === -Le projet sigma était assez large et comportant pas mal de facettes avec des technologies pas forcément toujours intuitives ou bien documentées, les mémos de cetten section sont là pour permettre au dev perdu de s'y retrouver rapidement face à une technologie qu'il ne maîtrise pas à fond. \ No newline at end of file +Le projet sigma était assez large et comportant pas mal de facettes avec des technologies pas forcément toujours intuitives ou bien documentées, les mémos de cette section sont là pour permettre au dev perdu de s'y retrouver rapidement face à une technologie qu'il ne maîtrise pas à fond. \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9d91e80e21ccf75f15b93ecc5481635b6b762357..a97021310686abed5e22a5ca386ee6d65a1b5d75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,22 +5,22 @@ "requires": true, "dependencies": { "@apollographql/apollo-tools": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.2.9.tgz", - "integrity": "sha1-HiCZnRFyjvR/j4EvK+BCa13eGlE=", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.3.3.tgz", + "integrity": "sha512-/vLzZjloWB4xzgw2MRs9TUDIdCzS+No1hEClkEKqcnH86c2EgE/W0Dv2nkCTH9WxDrfryziJWbNMurYYkm61Zw==", "requires": { - "apollo-env": "0.2.5" + "apollo-env": "0.3.3" } }, "@apollographql/graphql-playground-html": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.6.tgz", - "integrity": "sha1-AiIJ4oorVH3N4VshnwxQ9HqlvrM=" + "integrity": "sha512-lqK94b+caNtmKFs5oUVXlSpN3sm5IXZ+KfhMxOtr0LR2SqErzkoJilitjDvJ1WbjHlxLI7WtCjRmOLdOGJqtMQ==" }, "@babel/cli": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.2.0.tgz", - "integrity": "sha1-UF7Y01Ha7mqIkY2gLARsGMjFok8=", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.2.3.tgz", + "integrity": "sha512-bfna97nmJV6nDJhXNPeEfxyMjWnt6+IjUAaDPiYRTBlm8L41n8nvw6UAqUCbvpFfU246gHPxW7sfWwqtF4FcYA==", "dev": true, "requires": { "chokidar": "^2.0.3", @@ -36,31 +36,31 @@ } }, "@babel/code-frame": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", - "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", "dev": true, "requires": { - "@babel/highlight": "7.0.0-beta.44" + "@babel/highlight": "^7.0.0" } }, "@babel/core": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.2.0.tgz", - "integrity": "sha1-pN04FJAZmOkzQPAIbphn/voWOto=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.3.4.tgz", + "integrity": "sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.2.0", + "@babel/generator": "^7.3.4", "@babel/helpers": "^7.2.0", - "@babel/parser": "^7.2.0", - "@babel/template": "^7.1.2", - "@babel/traverse": "^7.1.6", - "@babel/types": "^7.2.0", + "@babel/parser": "^7.3.4", + "@babel/template": "^7.2.2", + "@babel/traverse": "^7.3.4", + "@babel/types": "^7.3.4", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" @@ -76,14 +76,14 @@ } }, "@babel/generator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", - "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz", + "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==", "dev": true, "requires": { - "@babel/types": "^7.2.0", + "@babel/types": "^7.3.4", "jsesc": "^2.5.1", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -129,48 +129,48 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/traverse": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", - "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz", + "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", + "@babel/generator": "^7.3.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.6", - "@babel/types": "^7.1.6", + "@babel/parser": "^7.3.4", + "@babel/types": "^7.3.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -206,14 +206,14 @@ } }, "@babel/generator": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz", - "integrity": "sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz", + "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==", "dev": true, "requires": { - "@babel/types": "7.0.0-beta.44", + "@babel/types": "^7.3.4", "jsesc": "^2.5.1", - "lodash": "^4.2.0", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -221,20 +221,20 @@ "@babel/helper-annotate-as-pure": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha1-Mj053QtQ4Qx8Bsp9djjmhk2MXDI=", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", "dev": true, "requires": { "@babel/types": "^7.0.0" }, "dependencies": { "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } } @@ -243,7 +243,7 @@ "@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha1-a2lijf5Ah3mODE7Zjj1Kay+9L18=", + "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", "dev": true, "requires": { "@babel/helper-explode-assignable-expression": "^7.1.0", @@ -251,13 +251,13 @@ }, "dependencies": { "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } } @@ -266,7 +266,7 @@ "@babel/helper-call-delegate": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz", - "integrity": "sha1-apV/EF83dV6GRTQ9MDiiLhRJzEo=", + "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.0.0", @@ -284,14 +284,14 @@ } }, "@babel/generator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", - "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz", + "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==", "dev": true, "requires": { - "@babel/types": "^7.2.0", + "@babel/types": "^7.3.4", "jsesc": "^2.5.1", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -337,48 +337,48 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/traverse": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", - "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz", + "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", + "@babel/generator": "^7.3.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.6", - "@babel/types": "^7.1.6", + "@babel/parser": "^7.3.4", + "@babel/types": "^7.3.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -399,16 +399,17 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.2.1.tgz", - "integrity": "sha1-9ugCcpFmnvZEMyINyDJ1MSM/EWE=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.3.4.tgz", + "integrity": "sha512-uFpzw6L2omjibjxa8VGZsJUPL5wJH0zzGKpoz0ccBkzIa6C8kWNUbiBmQ0rgOKWlHJ6qzmfa6lTiGchiV8SC+g==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", "@babel/helper-member-expression-to-functions": "^7.0.0", "@babel/helper-optimise-call-expression": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0" + "@babel/helper-replace-supers": "^7.3.4", + "@babel/helper-split-export-declaration": "^7.0.0" }, "dependencies": { "@babel/code-frame": { @@ -440,6 +441,15 @@ "@babel/types": "^7.0.0" } }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, "@babel/highlight": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", @@ -452,24 +462,24 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -484,7 +494,7 @@ "@babel/helper-define-map": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz", - "integrity": "sha1-O3TK7DKbPIDBFikIh8DdmuRowgw=", + "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", @@ -533,24 +543,24 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -565,7 +575,7 @@ "@babel/helper-explode-assignable-expression": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha1-U3+hP28WdN90WwwA7I/k6ZaByPY=", + "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", @@ -582,14 +592,14 @@ } }, "@babel/generator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", - "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz", + "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==", "dev": true, "requires": { - "@babel/types": "^7.2.0", + "@babel/types": "^7.3.4", "jsesc": "^2.5.1", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -635,48 +645,48 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/traverse": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", - "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz", + "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", + "@babel/generator": "^7.3.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.6", - "@babel/types": "^7.1.6", + "@babel/parser": "^7.3.4", + "@babel/types": "^7.3.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -697,42 +707,42 @@ } }, "@babel/helper-function-name": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz", - "integrity": "sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.44", - "@babel/template": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44" + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" } }, "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz", - "integrity": "sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", "dev": true, "requires": { - "@babel/types": "7.0.0-beta.44" + "@babel/types": "^7.0.0" } }, "@babel/helper-hoist-variables": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz", - "integrity": "sha1-Rq3ExedYZFrnpF3rkrqwkYwju4g=", + "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", "dev": true, "requires": { "@babel/types": "^7.0.0" }, "dependencies": { "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } } @@ -741,20 +751,20 @@ "@babel/helper-member-expression-to-functions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha1-jNFLCg33/wDwCefXpDaUX0fHoW8=", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", "dev": true, "requires": { "@babel/types": "^7.0.0" }, "dependencies": { "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } } @@ -763,36 +773,36 @@ "@babel/helper-module-imports": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha1-lggbcRHkhtpNLNlxrRpP4hbMLj0=", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", "dev": true, "requires": { "@babel/types": "^7.0.0" }, "dependencies": { "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } } } }, "@babel/helper-module-transforms": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz", - "integrity": "sha1-Rw1PlnbZ+tULMkzczl+6u8PaV4c=", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.2.2.tgz", + "integrity": "sha512-YRD7I6Wsv+IHuTPkAmAS4HhY0dkPobgLftHp0cRGZSdrRvmZY8rFvae/GVu3bD00qscuvK3WPHB3YdNpBXUqrA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-simple-access": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0", + "@babel/template": "^7.2.2", + "@babel/types": "^7.2.2", "lodash": "^4.17.10" }, "dependencies": { @@ -826,24 +836,24 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -858,20 +868,20 @@ "@babel/helper-optimise-call-expression": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha1-opIMVwKwc8Fd5REGIAqoytIEl9U=", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", "dev": true, "requires": { "@babel/types": "^7.0.0" }, "dependencies": { "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } } @@ -880,13 +890,13 @@ "@babel/helper-plugin-utils": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha1-u7P77phmHFaQNCN8wDlnupm08lA=", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", "dev": true }, "@babel/helper-regex": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0.tgz", - "integrity": "sha1-LBcYkjtX+bvmRwX/5WQKxk2b2yc=", + "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", "dev": true, "requires": { "lodash": "^4.17.10" @@ -895,7 +905,7 @@ "@babel/helper-remap-async-to-generator": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha1-Nh2AghtvONp1vT8HheziCojF/n8=", + "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -915,14 +925,14 @@ } }, "@babel/generator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", - "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz", + "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==", "dev": true, "requires": { - "@babel/types": "^7.2.0", + "@babel/types": "^7.3.4", "jsesc": "^2.5.1", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -968,48 +978,48 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/traverse": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", - "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz", + "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", + "@babel/generator": "^7.3.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.6", - "@babel/types": "^7.1.6", + "@babel/parser": "^7.3.4", + "@babel/types": "^7.3.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1030,15 +1040,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz", - "integrity": "sha1-X8Md5SLsDvCJncmz589qXdZV82I=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.3.4.tgz", + "integrity": "sha512-pvObL9WVf2ADs+ePg0jrqlhHoxRXlOa+SHRHzAXIz2xkYuOHfGl+fKxPMaS4Fq+uje8JQPobnertBBvyrWnQ1A==", "dev": true, "requires": { "@babel/helper-member-expression-to-functions": "^7.0.0", "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/traverse": "^7.3.4", + "@babel/types": "^7.3.4" }, "dependencies": { "@babel/code-frame": { @@ -1051,14 +1061,14 @@ } }, "@babel/generator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", - "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz", + "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==", "dev": true, "requires": { - "@babel/types": "^7.2.0", + "@babel/types": "^7.3.4", "jsesc": "^2.5.1", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -1104,48 +1114,48 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/traverse": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", - "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz", + "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", + "@babel/generator": "^7.3.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.6", - "@babel/types": "^7.1.6", + "@babel/parser": "^7.3.4", + "@babel/types": "^7.3.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1168,7 +1178,7 @@ "@babel/helper-simple-access": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha1-Ze65VMjCRb6qToWdphiPOdceWFw=", + "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", "dev": true, "requires": { "@babel/template": "^7.1.0", @@ -1196,24 +1206,24 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -1226,18 +1236,18 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz", - "integrity": "sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", "dev": true, "requires": { - "@babel/types": "7.0.0-beta.44" + "@babel/types": "^7.0.0" } }, "@babel/helper-wrap-function": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", - "integrity": "sha1-xOABJEV2nigVtVKW6tQ6lYVJ9vo=", + "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", @@ -1256,14 +1266,14 @@ } }, "@babel/generator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", - "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz", + "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==", "dev": true, "requires": { - "@babel/types": "^7.2.0", + "@babel/types": "^7.3.4", "jsesc": "^2.5.1", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -1309,48 +1319,48 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/traverse": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", - "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz", + "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", + "@babel/generator": "^7.3.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.6", - "@babel/types": "^7.1.6", + "@babel/parser": "^7.3.4", + "@babel/types": "^7.3.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1371,14 +1381,14 @@ } }, "@babel/helpers": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.2.0.tgz", - "integrity": "sha1-gzXzFA8xRCcNxjxHMqT4sKULeiE=", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.3.1.tgz", + "integrity": "sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA==", "dev": true, "requires": { "@babel/template": "^7.1.2", "@babel/traverse": "^7.1.5", - "@babel/types": "^7.2.0" + "@babel/types": "^7.3.0" }, "dependencies": { "@babel/code-frame": { @@ -1391,14 +1401,14 @@ } }, "@babel/generator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", - "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz", + "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==", "dev": true, "requires": { - "@babel/types": "^7.2.0", + "@babel/types": "^7.3.4", "jsesc": "^2.5.1", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "source-map": "^0.5.0", "trim-right": "^1.0.1" } @@ -1406,7 +1416,7 @@ "@babel/helper-function-name": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha1-oM6wFoX3M1XUNgwSR/WCv6/I/1M=", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.0.0", @@ -1417,7 +1427,7 @@ "@babel/helper-get-function-arity": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha1-g1ctQyDipGVyY3NBE8QoaLZOScM=", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -1426,7 +1436,7 @@ "@babel/helper-split-export-declaration": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", - "integrity": "sha1-Oq4oXAMRwqsJXZl7jJqUytVH2BM=", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -1444,48 +1454,48 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/traverse": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", - "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz", + "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", + "@babel/generator": "^7.3.4", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.6", - "@babel/types": "^7.1.6", + "@babel/parser": "^7.3.4", + "@babel/types": "^7.3.4", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1500,32 +1510,40 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true } } }, "@babel/highlight": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz", - "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { "chalk": "^2.0.0", "esutils": "^2.0.2", - "js-tokens": "^3.0.0" + "js-tokens": "^4.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + } } }, "@babel/parser": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", - "integrity": "sha1-AtAdvDMLbL82t2rJPFB1LGkCcGU=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.4.tgz", + "integrity": "sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", - "integrity": "sha1-somzBmadzkrSCwJSiJoVdoydQX4=", + "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1534,19 +1552,19 @@ } }, "@babel/plugin-proposal-class-properties": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.2.1.tgz", - "integrity": "sha1-xzSlPgoexA/lwi7lBp0m2jsYfQU=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.4.tgz", + "integrity": "sha512-lUf8D3HLs4yYlAo8zjuneLvfxN7qfKv1Yzbj5vjqaqMJxgJA3Ipwp4VUJ+OrOdz53Wbww6ahwB8UhB2HQyLotA==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.2.1", + "@babel/helper-create-class-features-plugin": "^7.3.4", "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-proposal-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", - "integrity": "sha1-Vo7MRGxhSK5rJn8CVREwiR4p8xc=", + "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1554,9 +1572,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.2.0.tgz", - "integrity": "sha1-iPX+w+etAZAUyX9+48mS8K2/f7g=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.4.tgz", + "integrity": "sha512-j7VQmbbkA+qrzNqbKHrBsW3ddFnOeva6wzSe/zB7T+xaxGc+RCpwo44wCmRixAIGRoIpmVgvzFzNJqQcO3/9RA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1566,7 +1584,7 @@ "@babel/plugin-proposal-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", - "integrity": "sha1-E12B7baKCB5V5W7EhUHs6AZcOPU=", + "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1576,7 +1594,7 @@ "@babel/plugin-proposal-unicode-property-regex": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz", - "integrity": "sha1-q+coH+Rsld3BQ6ZeU1hkd5IDlSA=", + "integrity": "sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1587,7 +1605,7 @@ "@babel/plugin-syntax-async-generators": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", - "integrity": "sha1-aeHw2zTG9aDPfiszI78VmnbIy38=", + "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1596,7 +1614,7 @@ "@babel/plugin-syntax-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", - "integrity": "sha1-cr0T9v/h0lk4Ep0qGGsR/WKVFHA=", + "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1605,7 +1623,7 @@ "@babel/plugin-syntax-object-rest-spread": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", - "integrity": "sha1-O3o+czUQxX6CC5FCpleayLDfrS4=", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1614,16 +1632,16 @@ "@babel/plugin-syntax-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", - "integrity": "sha1-qUAT1u2okI3+akd+f57ahWVuz1w=", + "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-typescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.0.0.tgz", - "integrity": "sha512-5fxmdqiAQVQTIS+KSvYeZuTt91wKtBTYi6JlIkvbQ6hmO+9fZE81ezxmMiFMIsxE7CdRSgzn7nQ1BChcvK9OpA==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz", + "integrity": "sha512-dGwbSMA1YhVS8+31CnPR7LB4pcbrzcV99wQzby4uAfrkZPYZlQ7ImwdpzLqi6Z6IL02b8IAL379CaMwo0x5Lag==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1632,16 +1650,16 @@ "@babel/plugin-transform-arrow-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", - "integrity": "sha1-mur75Nb/xlY7+Pg3IJFijwB3lVA=", + "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.2.0.tgz", - "integrity": "sha1-aLikOGY+iFGeZbd2+JOPNEWxov8=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.3.4.tgz", + "integrity": "sha512-Y7nCzv2fw/jEZ9f678MuKdMo99MFDJMT/PvD9LisrR5JDFcJH6vYeH6RnjVt3p5tceyGRvTtEN0VOlU+rgHZjA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -1652,26 +1670,26 @@ "@babel/plugin-transform-block-scoped-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", - "integrity": "sha1-XTzBHo1d3XUqpkyRSNDbbLef0ZA=", + "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.2.0.tgz", - "integrity": "sha1-8XxJ2R7tvN9d1QWX0W9fL3cBMtQ=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.3.4.tgz", + "integrity": "sha512-blRr2O8IOZLAOJklXLV4WhcEzpYafYQKSGT3+R26lWG41u/FODJuBggehtOwilVAcFu393v3OFj+HmaE6tVjhA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "@babel/plugin-transform-classes": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.2.0.tgz", - "integrity": "sha1-N0+IdgddfSH+pVrrXFNWElkWP5Y=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.3.4.tgz", + "integrity": "sha512-J9fAvCFBkXEvBimgYxCjvaVDzL6thk0j0dBvCeZmIUDBwyt+nv6HfbImsSrWsYXfDNDivyANgJlFXDUWRTZBuA==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -1679,7 +1697,7 @@ "@babel/helper-function-name": "^7.1.0", "@babel/helper-optimise-call-expression": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.1.0", + "@babel/helper-replace-supers": "^7.3.4", "@babel/helper-split-export-declaration": "^7.0.0", "globals": "^11.1.0" }, @@ -1734,24 +1752,24 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -1766,16 +1784,16 @@ "@babel/plugin-transform-computed-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", - "integrity": "sha1-g6ffamWIZbHI9kHVEMbzryICFto=", + "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-destructuring": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.2.0.tgz", - "integrity": "sha1-51JptLeInsOjMs0NDIz/j+0NxvM=", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.3.2.tgz", + "integrity": "sha512-Lrj/u53Ufqxl/sGxyjsJ2XNtNuEjDyjpqdhMNh5aZ+XFOdThL46KBj27Uem4ggoezSYBxKWAil6Hu8HtwqesYw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1784,7 +1802,7 @@ "@babel/plugin-transform-dotall-regex": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz", - "integrity": "sha1-8Kq7k9EgqKxh6SXqC6RAgS2+Dkk=", + "integrity": "sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1795,7 +1813,7 @@ "@babel/plugin-transform-duplicate-keys": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", - "integrity": "sha1-2VLEkw8xKk2//xjwspFOYMNVMLM=", + "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1804,7 +1822,7 @@ "@babel/plugin-transform-exponentiation-operator": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", - "integrity": "sha1-pjhoKJ5bQAf3BU1GSRr1FDV2YAg=", + "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", "dev": true, "requires": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", @@ -1814,7 +1832,7 @@ "@babel/plugin-transform-for-of": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz", - "integrity": "sha1-q3RovvqA92S7A9PLXu+MyZjhytk=", + "integrity": "sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1823,7 +1841,7 @@ "@babel/plugin-transform-function-name": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz", - "integrity": "sha1-95MDYoKf+ZoxdMOfCvzAJO9Zcxo=", + "integrity": "sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", @@ -1871,24 +1889,24 @@ } }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -1903,7 +1921,7 @@ "@babel/plugin-transform-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", - "integrity": "sha1-aQNT6B+SZ9rU/Yz9d+r6hqulPqE=", + "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1912,7 +1930,7 @@ "@babel/plugin-transform-modules-amd": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", - "integrity": "sha1-gqm85FuVRB9heiQBHcidEtp/TuY=", + "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.1.0", @@ -1922,7 +1940,7 @@ "@babel/plugin-transform-modules-commonjs": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz", - "integrity": "sha1-xPGTP1mR1RRenPrR39hI6hcn9AQ=", + "integrity": "sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.1.0", @@ -1931,9 +1949,9 @@ } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.2.0.tgz", - "integrity": "sha1-kSv+nl/5gpJMgdCTfJLSSZS7kGg=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.3.4.tgz", + "integrity": "sha512-VZ4+jlGOF36S7TjKs8g4ojp4MEI+ebCQZdswWb/T9I4X84j8OtFAyjXjt/M16iIm5RIZn0UMQgg/VgIwo/87vw==", "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.0.0", @@ -1943,17 +1961,26 @@ "@babel/plugin-transform-modules-umd": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", - "integrity": "sha1-dnjOdRafCHe46yI1U4wHQmjdAa4=", + "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.1.0", "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz", + "integrity": "sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw==", + "dev": true, + "requires": { + "regexp-tree": "^0.1.0" + } + }, "@babel/plugin-transform-new-target": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz", - "integrity": "sha1-ro+9iVF/p4ktIOZWTmQeh3DDqko=", + "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1962,7 +1989,7 @@ "@babel/plugin-transform-object-super": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", - "integrity": "sha1-s11MEPVrq11lAEfa0PHY6IFLZZg=", + "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1970,9 +1997,9 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.2.0.tgz", - "integrity": "sha1-DVrRXcgF4uqGbfTdZoK/520UCMI=", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.3.3.tgz", + "integrity": "sha512-IrIP25VvXWu/VlBWTpsjGptpomtIkYrN/3aDp4UKm7xK6UxZY88kcJ1UwETbzHAlwN21MnNfwlar0u8y3KpiXw==", "dev": true, "requires": { "@babel/helper-call-delegate": "^7.1.0", @@ -1990,40 +2017,40 @@ } }, "@babel/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", - "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } } } }, "@babel/plugin-transform-regenerator": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz", - "integrity": "sha1-W0Foa07UC++HTX7WqEvdhJwT4ME=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.3.4.tgz", + "integrity": "sha512-hvJg8EReQvXT6G9H2MvNPXkv9zK36Vxa1+csAVTpE1J3j0zlHplw76uudEbJxgvqZzAq9Yh45FLD4pk5mKRFQA==", "dev": true, "requires": { - "regenerator-transform": "^0.13.3" + "regenerator-transform": "^0.13.4" } }, "@babel/plugin-transform-shorthand-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", - "integrity": "sha1-YzOu4vjW7n4oYVRXKYk0o7RhmPA=", + "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.0.tgz", - "integrity": "sha1-DHbBKjtYJhMAeO6OyEp6jkr9ecQ=", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", + "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -2032,7 +2059,7 @@ "@babel/plugin-transform-sticky-regex": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", - "integrity": "sha1-oeRUtZlVYKnB4NU338FQYf0mh+E=", + "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -2042,7 +2069,7 @@ "@babel/plugin-transform-template-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz", - "integrity": "sha1-2H7QG46qx6kkc/YIyXwIneK6Hls=", + "integrity": "sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -2052,26 +2079,26 @@ "@babel/plugin-transform-typeof-symbol": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", - "integrity": "sha1-EX0rzsL79ktLWdH5gZiUaC0p8rI=", + "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-typescript": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.1.0.tgz", - "integrity": "sha512-TOTtVeT+fekAesiCHnPz+PSkYSdOSLyLn42DI45nxg6iCdlQY6LIj/tYqpMB0y+YicoTUiYiXqF8rG6SKfhw6Q==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.3.2.tgz", + "integrity": "sha512-Pvco0x0ZSCnexJnshMfaibQ5hnK8aUHSvjCQhC1JR8eeg+iBwt0AtCO7gWxJ358zZevuf9wPSO5rv+WJcbHPXQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-typescript": "^7.0.0" + "@babel/plugin-syntax-typescript": "^7.2.0" } }, "@babel/plugin-transform-unicode-regex": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz", - "integrity": "sha1-TrjbFvly+Ku1BiwWG4sRVUat4Is=", + "integrity": "sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -2079,27 +2106,49 @@ "regexpu-core": "^4.1.3" } }, + "@babel/polyfill": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.2.5.tgz", + "integrity": "sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug==", + "requires": { + "core-js": "^2.5.7", + "regenerator-runtime": "^0.12.0" + }, + "dependencies": { + "core-js": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.3.tgz", + "integrity": "sha512-l00tmFFZOBHtYhN4Cz7k32VM7vTn3rE2ANjQDxdEN6zmXZ/xq1jQuutnmHvMG1ZJ7xd72+TA5YpUK8wz3rWsfQ==" + }, + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" + } + } + }, "@babel/preset-env": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.2.0.tgz", - "integrity": "sha1-pQMOfkMGr1opXdXXx43FRkrz/uI=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.3.4.tgz", + "integrity": "sha512-2mwqfYMK8weA0g0uBKOt4FE3iEodiHy9/CW0b+nWXcbL+pGzLx8ESYc+j9IIxr6LTDHWKgPm71i9smo02bw+gA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-async-generator-functions": "^7.2.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.3.4", "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", "@babel/plugin-proposal-unicode-property-regex": "^7.2.0", "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", "@babel/plugin-syntax-object-rest-spread": "^7.2.0", "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.3.4", "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.2.0", - "@babel/plugin-transform-classes": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.3.4", + "@babel/plugin-transform-classes": "^7.3.4", "@babel/plugin-transform-computed-properties": "^7.2.0", "@babel/plugin-transform-destructuring": "^7.2.0", "@babel/plugin-transform-dotall-regex": "^7.2.0", @@ -2110,12 +2159,13 @@ "@babel/plugin-transform-literals": "^7.2.0", "@babel/plugin-transform-modules-amd": "^7.2.0", "@babel/plugin-transform-modules-commonjs": "^7.2.0", - "@babel/plugin-transform-modules-systemjs": "^7.2.0", + "@babel/plugin-transform-modules-systemjs": "^7.3.4", "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.3.0", "@babel/plugin-transform-new-target": "^7.0.0", "@babel/plugin-transform-object-super": "^7.2.0", "@babel/plugin-transform-parameters": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.3.4", "@babel/plugin-transform-shorthand-properties": "^7.2.0", "@babel/plugin-transform-spread": "^7.2.0", "@babel/plugin-transform-sticky-regex": "^7.2.0", @@ -2129,13 +2179,13 @@ } }, "@babel/preset-typescript": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.1.0.tgz", - "integrity": "sha1-Sa1uIIT/C/tfH3+ztedsQ01ELH8=", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.3.3.tgz", + "integrity": "sha512-mzMVuIP4lqtn4du2ynEfdO0+RYcslwrZiJHXu4MGaC1ctJiW2fyaeDrtjJGs7R/KebZ1sgowcIoWf4uRpEfKEg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-transform-typescript": "^7.1.0" + "@babel/plugin-transform-typescript": "^7.3.2" } }, "@babel/runtime": { @@ -2154,43 +2204,58 @@ } }, "@babel/template": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz", - "integrity": "sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { - "@babel/code-frame": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44", - "babylon": "7.0.0-beta.44", - "lodash": "^4.2.0" + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/traverse": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz", - "integrity": "sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz", + "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==", "dev": true, "requires": { - "@babel/code-frame": "7.0.0-beta.44", - "@babel/generator": "7.0.0-beta.44", - "@babel/helper-function-name": "7.0.0-beta.44", - "@babel/helper-split-export-declaration": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44", - "babylon": "7.0.0-beta.44", - "debug": "^3.1.0", + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.3.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.3.4", + "@babel/types": "^7.3.4", + "debug": "^4.1.0", "globals": "^11.1.0", - "invariant": "^2.2.0", - "lodash": "^4.2.0" + "lodash": "^4.17.11" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } } }, "@babel/types": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz", - "integrity": "sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", "dev": true, "requires": { "esutils": "^2.0.2", - "lodash": "^4.2.0", + "lodash": "^4.17.11", "to-fast-properties": "^2.0.0" } }, @@ -2277,12 +2342,12 @@ "@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha1-TIVzDlm5ofHzSQR9vyQpYDS7JzU=" + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" }, "@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha1-fvN/DQEPsCitGtWXIuUG2SYoFcs=" + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" }, "@protobufjs/eventemitter": { "version": "1.1.0", @@ -2325,7 +2390,7 @@ }, "@types/accepts": { "version": "1.3.5", - "resolved": "http://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", + "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", "requires": { "@types/node": "*" @@ -2345,9 +2410,9 @@ } }, "@types/bluebird": { - "version": "3.5.24", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.24.tgz", - "integrity": "sha512-YeQoDpq4Lm8ppSBqAnAeF/xy1cYp/dMTif2JFcvmAbETMRlvKHT2iLcWu+WyYiJO3b3Ivokwo7EQca/xfLVJmg==", + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.26.tgz", + "integrity": "sha512-aj2mrBLn5ky0GmAg6IPXrQjnN0iB/ulozuJ+oZdrHRAzRbXjGmu4UXsNCjFvPbSaaPZmniocdOzsM392qLOlmQ==", "dev": true }, "@types/body-parser": { @@ -2359,10 +2424,16 @@ "@types/node": "*" } }, + "@types/chai": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", + "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", + "dev": true + }, "@types/connect": { "version": "3.4.32", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", - "integrity": "sha1-qg6WFrlDXMrQK8UrW0VP/Cxwuig=", + "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", "requires": { "@types/node": "*" } @@ -2388,7 +2459,7 @@ "@types/cors": { "version": "2.8.4", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.4.tgz", - "integrity": "sha1-UJkadZopwLiUknUQCMavenyCZ7A=", + "integrity": "sha512-ipZjBVsm2tF/n8qFGOuGBkUij9X9ZswVi9G3bx/6dz7POpVa6gVHcj1wsX/LVEn9MMF41fxK/PnZPPoTD1UFPw==", "requires": { "@types/express": "*" } @@ -2396,7 +2467,7 @@ "@types/events": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", - "integrity": "sha1-gaZzHOTfQ2GeXIyUU4Oz5iqJ6oY=" + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" }, "@types/express": { "version": "4.11.1", @@ -2418,9 +2489,9 @@ } }, "@types/graphql": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.13.4.tgz", - "integrity": "sha512-B4yel4ro2nTb3v0pYO8vO6SjgvFJSrwUY+IO6TUSLdOSB+gQFslylrhRCHxvXMIhxB71mv5PEE9dAX+24S8sew==", + "version": "14.0.7", + "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-14.0.7.tgz", + "integrity": "sha512-BoLDjdvLQsXPZLJux3lEZANwGr3Xag56Ngy0U3y8uoRSDdeLcn43H3oBcgZlnd++iOQElBpaRVDHPzEDekyvXQ==", "dev": true }, "@types/jss": { @@ -2433,9 +2504,9 @@ } }, "@types/knex": { - "version": "0.14.26", - "resolved": "https://registry.npmjs.org/@types/knex/-/knex-0.14.26.tgz", - "integrity": "sha512-BhtEH5PbB2kxuAwZ1w+KDNyL5NZXjTfoT6JtwnD3P/l3bqJJISCOAfPeH8O2aY66auscNIaCvIij/eONvlM4Cw==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@types/knex/-/knex-0.15.2.tgz", + "integrity": "sha512-mw8OT8v+FK0SsgDdmio2XSkEM/yLD7ybFtiqW7I65EDTlr2aZtG+p9FhryErpNJDJ2FEXgQhe3JVBG0Gh7YbvQ==", "dev": true, "requires": { "@types/bluebird": "*", @@ -2454,22 +2525,28 @@ "@types/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", - "integrity": "sha1-cZVR0jUtMBrIuB23Mqy2vcKNve8=" + "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==" }, "@types/mime": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz", - "integrity": "sha1-WnMG42fFObn2VDSZ3o3VGfrDeos=" + "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==" + }, + "@types/mocha": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.6.tgz", + "integrity": "sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw==", + "dev": true }, "@types/node": { - "version": "10.12.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.14.tgz", - "integrity": "sha512-0rVcFRhM93kRGAU88ASCjX9Y3FWDCh+33G5Z5evpKOea4xcpLqDGwmo64+DjgaSezTN5j9KdnUzvxhOw7fNciQ==" + "version": "11.9.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.9.5.tgz", + "integrity": "sha512-vVjM0SVzgaOUpflq4GYBvCpozes8OgIIS5gVXVka+OfK3hvnkC1i93U8WiY2OtNE4XUWyyy/86Kf6e0IHTQw1Q==" }, "@types/passport": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-0.4.7.tgz", - "integrity": "sha1-K38pv2Hfkc93Ajs3d+lAthPUtNg=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.0.tgz", + "integrity": "sha512-R2FXqM+AgsMIym0PuKj08Ybx+GR6d2rU3b1/8OcHolJ+4ga2pRPX105wboV6hq1AJvMo2frQzYKdqXS5+4cyMw==", "requires": { "@types/express": "*" } @@ -2508,200 +2585,204 @@ "@types/ws": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.1.tgz", - "integrity": "sha1-yno/N1aqEvYqCmIUXtFMbbJdWig=", + "integrity": "sha512-EzH8k1gyZ4xih/MaZTXwT2xOkPiIMSrhQ9b8wrlX88L0T02eYsddatQlwVFlEPyEqV0ChpdpNnE51QPH6NVT4Q==", "requires": { "@types/events": "*", "@types/node": "*" } }, "@webassemblyjs/ast": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", - "integrity": "sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.3.tgz", + "integrity": "sha512-xy3m06+Iu4D32+6soz6zLnwznigXJRuFNTovBX2M4GqVqLb0dnyWLbPnpcXvUSdEN+9DVyDeaq2jyH1eIL2LZQ==", "dev": true, "requires": { - "@webassemblyjs/helper-module-context": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/wast-parser": "1.7.11" + "@webassemblyjs/helper-module-context": "1.8.3", + "@webassemblyjs/helper-wasm-bytecode": "1.8.3", + "@webassemblyjs/wast-parser": "1.8.3" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz", - "integrity": "sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.3.tgz", + "integrity": "sha512-vq1TISG4sts4f0lDwMUM0f3kpe0on+G3YyV5P0IySHFeaLKRYZ++n2fCFfG4TcCMYkqFeTUYFxm75L3ddlk2xA==", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz", - "integrity": "sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.3.tgz", + "integrity": "sha512-BmWEynI4FnZbjk8CaYZXwcv9a6gIiu+rllRRouQUo73hglanXD3AGFJE7Q4JZCoVE0p5/jeX6kf5eKa3D4JxwQ==", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz", - "integrity": "sha1-MSLUjcxslFbtmC3r4WyPNxAd85s=", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.3.tgz", + "integrity": "sha512-iVIMhWnNHoFB94+/2l7LpswfCsXeMRnWfExKtqsZ/E2NxZyUx9nTeKK/MEMKTQNEpyfznIUX06OchBHQ+VKi/Q==", "dev": true }, "@webassemblyjs/helper-code-frame": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz", - "integrity": "sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.3.tgz", + "integrity": "sha512-K1UxoJML7GKr1QXR+BG7eXqQkvu+eEeTjlSl5wUFQ6W6vaOc5OwSxTcb3oE9x/3+w4NHhrIKD4JXXCZmLdL2cg==", "dev": true, "requires": { - "@webassemblyjs/wast-printer": "1.7.11" + "@webassemblyjs/wast-printer": "1.8.3" } }, "@webassemblyjs/helper-fsm": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz", - "integrity": "sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.3.tgz", + "integrity": "sha512-387zipfrGyO77/qm7/SDUiZBjQ5KGk4qkrVIyuoubmRNIiqn3g+6ijY8BhnlGqsCCQX5bYKOnttJobT5xoyviA==", "dev": true }, "@webassemblyjs/helper-module-context": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz", - "integrity": "sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==", - "dev": true + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.3.tgz", + "integrity": "sha512-lPLFdQfaRssfnGEJit5Sk785kbBPPPK4ZS6rR5W/8hlUO/5v3F+rN8XuUcMj/Ny9iZiyKhhuinWGTUuYL4VKeQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.3", + "mamacro": "^0.0.3" + } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz", - "integrity": "sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.3.tgz", + "integrity": "sha512-R1nJW7bjyJLjsJQR5t3K/9LJ0QWuZezl8fGa49DZq4IVaejgvkbNlKEQxLYTC579zgT4IIIVHb5JA59uBPHXyw==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz", - "integrity": "sha1-nJrEHs+fvP/8lvbSZ14t4zgR5oo=", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.3.tgz", + "integrity": "sha512-P6F7D61SJY73Yz+fs49Q3+OzlYAZP86OfSpaSY448KzUy65NdfzDmo2NPVte+Rw4562MxEAacvq/mnDuvRWOcg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11" + "@webassemblyjs/ast": "1.8.3", + "@webassemblyjs/helper-buffer": "1.8.3", + "@webassemblyjs/helper-wasm-bytecode": "1.8.3", + "@webassemblyjs/wasm-gen": "1.8.3" } }, "@webassemblyjs/ieee754": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz", - "integrity": "sha1-yVg562N1ejGICq7HtlEtQZGsZAs=", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.3.tgz", + "integrity": "sha512-UD4HuLU99hjIvWz1pD68b52qsepWQlYCxDYVFJQfHh3BHyeAyAlBJ+QzLR1nnS5J6hAzjki3I3AoJeobNNSZlg==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz", - "integrity": "sha1-1yZ6HunEWU/T9+NymIGOxlaH22M=", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.3.tgz", + "integrity": "sha512-XXd3s1BmkC1gpGABuCRLqCGOD6D2L+Ma2BpwpjrQEHeQATKWAQtxAyU9Z14/z8Ryx6IG+L4/NDkIGHrccEhRUg==", "dev": true, "requires": { - "@xtuc/long": "4.2.1" + "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz", - "integrity": "sha1-Btchjqn9yUpnk6qSIIFg2z0m7oI=", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.3.tgz", + "integrity": "sha512-Wv/WH9Zo5h5ZMyfCNpUrjFsLZ3X1amdfEuwdb7MLdG3cPAjRS6yc6ElULlpjLiiBTuzvmLhr3ENsuGyJ3wyCgg==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz", - "integrity": "sha1-jHTKR01PlR0B266b1wgU7iKoIAU=", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.3.tgz", + "integrity": "sha512-nB19eUx3Yhi1Vvv3yev5r+bqQixZprMtaoCs1brg9Efyl8Hto3tGaUoZ0Yb4Umn/gQCyoEGFfUxPLp1/8+Jvnw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/helper-wasm-section": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11", - "@webassemblyjs/wasm-opt": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11", - "@webassemblyjs/wast-printer": "1.7.11" + "@webassemblyjs/ast": "1.8.3", + "@webassemblyjs/helper-buffer": "1.8.3", + "@webassemblyjs/helper-wasm-bytecode": "1.8.3", + "@webassemblyjs/helper-wasm-section": "1.8.3", + "@webassemblyjs/wasm-gen": "1.8.3", + "@webassemblyjs/wasm-opt": "1.8.3", + "@webassemblyjs/wasm-parser": "1.8.3", + "@webassemblyjs/wast-printer": "1.8.3" } }, "@webassemblyjs/wasm-gen": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz", - "integrity": "sha1-m7upQvIjdWhqb7dZr816ycRdoag=", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.3.tgz", + "integrity": "sha512-sDNmu2nLBJZ/huSzlJvd9IK8B1EjCsOl7VeMV9VJPmxKYgTJ47lbkSP+KAXMgZWGcArxmcrznqm7FrAPQ7vVGg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/ieee754": "1.7.11", - "@webassemblyjs/leb128": "1.7.11", - "@webassemblyjs/utf8": "1.7.11" + "@webassemblyjs/ast": "1.8.3", + "@webassemblyjs/helper-wasm-bytecode": "1.8.3", + "@webassemblyjs/ieee754": "1.8.3", + "@webassemblyjs/leb128": "1.8.3", + "@webassemblyjs/utf8": "1.8.3" } }, "@webassemblyjs/wasm-opt": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz", - "integrity": "sha1-szHo5874+OLwB9QsOjagWAp9bKc=", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.3.tgz", + "integrity": "sha512-j8lmQVFR+FR4/645VNgV4R/Jz8i50eaPAj93GZyd3EIJondVshE/D9pivpSDIXyaZt+IkCodlzOoZUE4LnQbeA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11" + "@webassemblyjs/ast": "1.8.3", + "@webassemblyjs/helper-buffer": "1.8.3", + "@webassemblyjs/wasm-gen": "1.8.3", + "@webassemblyjs/wasm-parser": "1.8.3" } }, "@webassemblyjs/wasm-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz", - "integrity": "sha1-bj0g+mo1GfawhO+Tka1YIR77Cho=", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.3.tgz", + "integrity": "sha512-NBI3SNNtRoy4T/KBsRZCAWUzE9lI94RH2nneLwa1KKIrt/2zzcTavWg6oY05ArCbb/PZDk3OUi63CD1RYtN65w==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-api-error": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/ieee754": "1.7.11", - "@webassemblyjs/leb128": "1.7.11", - "@webassemblyjs/utf8": "1.7.11" + "@webassemblyjs/ast": "1.8.3", + "@webassemblyjs/helper-api-error": "1.8.3", + "@webassemblyjs/helper-wasm-bytecode": "1.8.3", + "@webassemblyjs/ieee754": "1.8.3", + "@webassemblyjs/leb128": "1.8.3", + "@webassemblyjs/utf8": "1.8.3" } }, "@webassemblyjs/wast-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz", - "integrity": "sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.3.tgz", + "integrity": "sha512-gZPst4CNcmGtKC1eYQmgCx6gwQvxk4h/nPjfPBbRoD+Raw3Hs+BS3yhrfgyRKtlYP+BJ8LcY9iFODEQofl2qbg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/floating-point-hex-parser": "1.7.11", - "@webassemblyjs/helper-api-error": "1.7.11", - "@webassemblyjs/helper-code-frame": "1.7.11", - "@webassemblyjs/helper-fsm": "1.7.11", - "@xtuc/long": "4.2.1" + "@webassemblyjs/ast": "1.8.3", + "@webassemblyjs/floating-point-hex-parser": "1.8.3", + "@webassemblyjs/helper-api-error": "1.8.3", + "@webassemblyjs/helper-code-frame": "1.8.3", + "@webassemblyjs/helper-fsm": "1.8.3", + "@xtuc/long": "4.2.2" } }, "@webassemblyjs/wast-printer": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz", - "integrity": "sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.3.tgz", + "integrity": "sha512-DTA6kpXuHK4PHu16yAD9QVuT1WZQRT7079oIFFmFSjqjLWGXS909I/7kiLTn931mcj7wGsaUNungjwNQ2lGQ3Q==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/wast-parser": "1.7.11", - "@xtuc/long": "4.2.1" + "@webassemblyjs/ast": "1.8.3", + "@webassemblyjs/wast-parser": "1.8.3", + "@xtuc/long": "4.2.2" } }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha1-7vAUoxRa5Hehy8AM0eVSM23Ot5A=", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true }, "@xtuc/long": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", - "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, "accepts": { @@ -2714,19 +2795,16 @@ } }, "acorn": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", - "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", "dev": true }, "acorn-dynamic-import": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", - "integrity": "sha1-kBzu5Mf6rvfgetKkfokGddpQong=", - "dev": true, - "requires": { - "acorn": "^5.0.0" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "dev": true }, "acorn-globals": { "version": "3.1.0", @@ -2744,21 +2822,10 @@ } }, "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "dev": true }, "ajv": { "version": "6.2.1", @@ -2773,8 +2840,7 @@ "ajv-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha1-81mGrOuRr63sQQL72FAUlQzvpk0=", - "dev": true + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" }, "ajv-keywords": { "version": "3.1.0", @@ -2810,6 +2876,11 @@ "string-width": "^2.0.0" } }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==" + }, "ansi-escape-sequences": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.0.0.tgz", @@ -2820,9 +2891,9 @@ } }, "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true }, "ansi-regex": { @@ -2842,7 +2913,7 @@ "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { "micromatch": "^3.1.4", @@ -2850,20 +2921,20 @@ } }, "apollo-cache-control": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.4.0.tgz", - "integrity": "sha512-WuriaNQIugTE8gYwfBWWCbbQTSKul/cV4JMi5UgqNIUvjHvnKZQLKbt5uYWow6QQNMkLT9hey8QPYkWpogkeSA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.5.2.tgz", + "integrity": "sha512-uehXDUrd3Qim+nzxqqN7XT1YTbNSyumW3/FY5BxbKZTI8d4oPG4eyVQKqaggooSjswKQnOoIQVes3+qg9tGAkw==", "requires": { "apollo-server-env": "2.2.0", - "graphql-extensions": "0.4.0" + "graphql-extensions": "0.5.4" }, "dependencies": { "graphql-extensions": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.4.0.tgz", - "integrity": "sha512-8TUgIIUVpXWOcqq9RdmTSHUrhc3a/s+saKv9cCl8TYWHK9vyJIdea7ZaSKHGDthZNcsN+C3LulZYRL3Ah8ukoA==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.5.4.tgz", + "integrity": "sha512-qLThJGVMqcItE7GDf/xX/E40m/aeqFheEKiR5bfra4q5eHxQKGjnIc20P9CVqjOn9I0FkEiU9ypOobfmIf7t6g==", "requires": { - "@apollographql/apollo-tools": "^0.2.6" + "@apollographql/apollo-tools": "^0.3.3" } } } @@ -3030,57 +3101,48 @@ } }, "apollo-datasource": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.2.1.tgz", - "integrity": "sha1-Ps707+ZPegSkOGLzICfTisCeFCw=", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.3.1.tgz", + "integrity": "sha512-qdEUeonc9pPZvYwXK36h2NZoT7Pddmy0HYOzdV0ON5pcG1YtNmUyyYi83Q60V5wTWjuaCjyJ9hOY6wr0BMvQuA==", "requires": { - "apollo-server-caching": "0.2.1", + "apollo-server-caching": "0.3.1", "apollo-server-env": "2.2.0" } }, "apollo-engine-reporting": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-0.2.0.tgz", - "integrity": "sha512-Q6FfVb10v/nrv8FaFsPjIYlWh62jaYav3LuMgM9PsHWGK/zRQFXOEwLxcY2UCvG7O1moxF3XGmfBhMgo54py+Q==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-1.0.7.tgz", + "integrity": "sha512-mFsXvd+1/o5jSa9tI2RoXYGcvCLcwwcfLwchjSTxqUd4ViB8RbqYKynzEZ+Omji7PBRM0azioBm43f7PSsQPqA==", "requires": { - "apollo-engine-reporting-protobuf": "0.2.0", + "apollo-engine-reporting-protobuf": "0.2.1", + "apollo-graphql": "^0.1.0", + "apollo-server-core": "2.4.8", "apollo-server-env": "2.2.0", "async-retry": "^1.2.1", - "graphql-extensions": "0.4.0", - "lodash": "^4.17.10" - }, - "dependencies": { - "graphql-extensions": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.4.0.tgz", - "integrity": "sha512-8TUgIIUVpXWOcqq9RdmTSHUrhc3a/s+saKv9cCl8TYWHK9vyJIdea7ZaSKHGDthZNcsN+C3LulZYRL3Ah8ukoA==", - "requires": { - "@apollographql/apollo-tools": "^0.2.6" - } - } + "graphql-extensions": "0.5.7" } }, "apollo-engine-reporting-protobuf": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.2.0.tgz", - "integrity": "sha512-qI+GJKN78UMJ9Aq/ORdiM2qymZ5yswem+/VDdVFocq+/e1QqxjnpKjQWISkswci5+WtpJl9SpHBNxG98uHDKkA==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.2.1.tgz", + "integrity": "sha512-5pYR84uWeylRS2OJowtkTczT3bWTwOErWtfnkRKccUi/wZ/AZJBP+D5HKNzM7xoFcz9XvrJyS+wBTz1oBi0Jiw==", "requires": { "protobufjs": "^6.8.6" } }, "apollo-env": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/apollo-env/-/apollo-env-0.2.5.tgz", - "integrity": "sha1-Fix4W8zSrqaTUKdgD6tLcUf8naU=", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/apollo-env/-/apollo-env-0.3.3.tgz", + "integrity": "sha512-VsUX14bfQCJpKmTyYNBTeLrdeFabjmpSPVQ2y4IKnwqaxVqZuRca3WFE8ercszO1tLwS6HMM7mFw+IIbtQXo/w==", "requires": { - "core-js": "^3.0.0-beta.3", + "core-js": "3.0.0-beta.13", "node-fetch": "^2.2.0" }, "dependencies": { "core-js": { - "version": "3.0.0-beta.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.0-beta.5.tgz", - "integrity": "sha512-lv/UPXe8QIvAX4XEgz3u9gpSbYr0Et6gaVhwMEH6SN9Uk+aIhk9IMwQUa35pymUiA4t2THPOaqysDJtX4jcm3w==" + "version": "3.0.0-beta.13", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.0-beta.13.tgz", + "integrity": "sha512-16Q43c/3LT9NyePUJKL8nRIQgYWjcBhjJSMWg96PVSxoS0PeE0NHitPI3opBrs9MGGHjte1KoEVr9W63YKlTXQ==" }, "node-fetch": { "version": "2.3.0", @@ -3089,27 +3151,27 @@ } } }, + "apollo-graphql": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.1.1.tgz", + "integrity": "sha512-UImgDIeB0n0fryYqtdz0CwJ9uDtXwg/3Q6rXzRAqgqBYz46VkmWa7nu2LX9GmDtiXB5VUOVCtyMEnvFwC3o27g==", + "requires": { + "lodash.sortby": "^4.7.0" + } + }, "apollo-link": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.2.tgz", - "integrity": "sha512-Uk/BC09dm61DZRDSu52nGq0nFhq7mcBPTjy5EEH1eunJndtCaNXQhQz/BjkI2NdrfGI+B+i5he6YSoRBhYizdw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.6.tgz", + "integrity": "sha512-sUNlA20nqIF3gG3F8eyMD+mO80fmf3dPZX+GUOs3MI9oZR8ug09H3F0UsWJMcpEg6h55Yy5wZ+BMmAjrbenF/Q==", "requires": { - "@types/graphql": "0.12.6", "apollo-utilities": "^1.0.0", - "zen-observable-ts": "^0.8.9" - }, - "dependencies": { - "@types/graphql": { - "version": "0.12.6", - "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.12.6.tgz", - "integrity": "sha512-wXAVyLfkG1UMkKOdMijVWFky39+OD/41KftzqfX1Oejd0Gm6dOIKjCihSVECg6X7PHjftxXmfOKA/d1H79ZfvQ==" - } + "zen-observable-ts": "^0.8.13" } }, "apollo-server-caching": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.2.1.tgz", - "integrity": "sha1-fmf4yMrIKeYis5Tw+4JXnKu+rf0=", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.3.1.tgz", + "integrity": "sha512-mfxzikYXbB/OoEms77AGYwRh7FF3Oim5v5XWAL+VL49FrkbZt5lopVa4bABi7Mz8Nt3Htl9EBJN8765s/yh8IA==", "requires": { "lru-cache": "^5.0.0" }, @@ -3117,7 +3179,7 @@ "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "requires": { "yallist": "^3.0.2" } @@ -3130,96 +3192,58 @@ } }, "apollo-server-core": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.3.1.tgz", - "integrity": "sha512-8jMWYOQIZi9mDJlHe2rXg8Cp4xKYogeRu23jkcNy+k5UjZL+eO+kHXbNFiTaP4HLYYEpe2XE3asxp6q5YUEQeQ==", + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.4.8.tgz", + "integrity": "sha512-N+5UOzHhMOnHizEiArJtNvEe/cGhSHQyTn5tlU4RJ36FDBJ/WlYZfPbGDMLISSUCJ6t+aP8GLL4Mnudt9d2PDQ==", "requires": { - "@apollographql/apollo-tools": "^0.2.6", + "@apollographql/apollo-tools": "^0.3.3", "@apollographql/graphql-playground-html": "^1.6.6", "@types/ws": "^6.0.0", - "apollo-cache-control": "0.4.0", - "apollo-datasource": "0.2.1", - "apollo-engine-reporting": "0.2.0", - "apollo-server-caching": "0.2.1", + "apollo-cache-control": "0.5.2", + "apollo-datasource": "0.3.1", + "apollo-engine-reporting": "1.0.7", + "apollo-server-caching": "0.3.1", "apollo-server-env": "2.2.0", - "apollo-server-errors": "2.2.0", - "apollo-server-plugin-base": "0.2.1", - "apollo-tracing": "0.4.0", - "graphql-extensions": "0.4.1", + "apollo-server-errors": "2.2.1", + "apollo-server-plugin-base": "0.3.7", + "apollo-tracing": "0.5.2", + "fast-json-stable-stringify": "^2.0.0", + "graphql-extensions": "0.5.7", "graphql-subscriptions": "^1.0.0", "graphql-tag": "^2.9.2", "graphql-tools": "^4.0.0", "graphql-upload": "^8.0.2", - "json-stable-stringify": "^1.0.1", - "lodash": "^4.17.10", + "sha.js": "^2.4.11", "subscriptions-transport-ws": "^0.9.11", "ws": "^6.0.0" - }, - "dependencies": { - "apollo-link": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.4.tgz", - "integrity": "sha1-q00h0uQo24SOiLXo9K3HF7GclUs=", - "requires": { - "apollo-utilities": "^1.0.0", - "zen-observable-ts": "^0.8.11" - } - }, - "graphql-tools": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.3.tgz", - "integrity": "sha512-NNZM0WSnVLX1zIMUxu7SjzLZ4prCp15N5L2T2ro02OVyydZ0fuCnZYRnx/yK9xjGWbZA0Q58yEO//Bv/psJWrg==", - "requires": { - "apollo-link": "^1.2.3", - "apollo-utilities": "^1.0.1", - "deprecated-decorator": "^0.1.6", - "iterall": "^1.1.3", - "uuid": "^3.1.0" - } - }, - "zen-observable-ts": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.11.tgz", - "integrity": "sha1-1UonzRfcS0u2vQCOXAlq9/ywaKk=", - "requires": { - "zen-observable": "^0.8.0" - } - } } }, "apollo-server-env": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.2.0.tgz", - "integrity": "sha1-Xuxdv0ZYH2Y/1mkrLgXH6K5tYDQ=", + "integrity": "sha512-wjJiI5nQWPBpNmpiLP389Ezpstp71szS6DHAeTgYLb/ulCw3CTuuA+0/E1bsThVWiQaDeHZE0sE3yI8q2zrYiA==", "requires": { "node-fetch": "^2.1.2", "util.promisify": "^1.0.0" - }, - "dependencies": { - "node-fetch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", - "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==" - } } }, "apollo-server-errors": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.2.0.tgz", - "integrity": "sha1-W0UqHW/3ZEDrDxJ1EdxYAxqPPLU=" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.2.1.tgz", + "integrity": "sha512-wY/YE3iJVMYC+WYIf8QODBjIP4jhI+oc7kiYo9mrz7LdYPKAgxr/he+NteGcqn/0Ea9K5/ZFTGJDbEstSMeP8g==" }, "apollo-server-express": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.3.1.tgz", - "integrity": "sha512-J+rObr4GdT/5j6qTByUJoSvZSjTAX/7VqIkr2t+GxwcVUFGet2MdOHuV6rtWKc8CRgvVKfKN6iBrb2EOFcp2LQ==", + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.4.8.tgz", + "integrity": "sha512-i60l32mfVe33jnKDPNYgUKUKu4Al0xEm2HLOSMgtJ9Wbpe/MbOx5X8M5F27fnHYdM+G5XfAErsakAyRGnQJ48Q==", "requires": { "@apollographql/graphql-playground-html": "^1.6.6", "@types/accepts": "^1.3.5", "@types/body-parser": "1.17.0", "@types/cors": "^2.8.4", - "@types/express": "4.16.0", + "@types/express": "4.16.1", "accepts": "^1.3.5", - "apollo-server-core": "2.3.1", + "apollo-server-core": "2.4.8", "body-parser": "^1.18.3", "cors": "^2.8.4", "graphql-subscriptions": "^1.0.0", @@ -3230,73 +3254,53 @@ "@types/body-parser": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", - "integrity": "sha1-n1ydm9BLtUvjLV65/A2Ml05s9Yw=", + "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==", "requires": { "@types/connect": "*", "@types/node": "*" } }, "@types/express": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.0.tgz", - "integrity": "sha1-bYvELMqm81zymit8MzPLR7WjKhk=", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.1.tgz", + "integrity": "sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg==", "requires": { "@types/body-parser": "*", "@types/express-serve-static-core": "*", "@types/serve-static": "*" } - }, - "apollo-link": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.4.tgz", - "integrity": "sha512-B1z+9H2nTyWEhMXRFSnoZ1vSuAYP+V/EdUJvRx9uZ8yuIBZMm6reyVtr1n0BWlKeSFyPieKJy2RLzmITAAQAMQ==", - "requires": { - "apollo-utilities": "^1.0.0", - "zen-observable-ts": "^0.8.11" - } - }, - "graphql-tools": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.3.tgz", - "integrity": "sha1-I7XLUsUZISsbLkYwo2FGQ5atJks=", - "requires": { - "apollo-link": "^1.2.3", - "apollo-utilities": "^1.0.1", - "deprecated-decorator": "^0.1.6", - "iterall": "^1.1.3", - "uuid": "^3.1.0" - } - }, - "zen-observable-ts": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.11.tgz", - "integrity": "sha512-8bs7rgGV4kz5iTb9isudkuQjtWwPnQ8lXq6/T76vrepYZVMsDEv6BXaEA+DHdJSK3KVLduagi9jSpSAJ5NgKHw==", - "requires": { - "zen-observable": "^0.8.0" - } } } }, "apollo-server-plugin-base": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.2.1.tgz", - "integrity": "sha512-497NIY9VWRYCrMSkgR11IrIUO4Fsy6aGgnpOJoTdLQAnkDD9SJDSRzwKj4gypUoTT2unfKDng4eMxXVZlHvjOw==" + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.3.7.tgz", + "integrity": "sha512-hW1jaLKf9qNOxMTwRq2CSqz3eqXsZuEiCc8/mmEtOciiVBq1GMtxFf19oIYM9HQuPvQU2RWpns1VrYN59L3vbg==" + }, + "apollo-server-testing": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/apollo-server-testing/-/apollo-server-testing-2.4.8.tgz", + "integrity": "sha512-AmNn5pDn9FJ9AJbmc7gwsUFaUt4uf44IFHaCfZow/jkAeY2JZnIozt8LYC8Koidy+Lfb+i/HsjkgbBodElbGMQ==", + "dev": true, + "requires": { + "apollo-server-core": "2.4.8" + } }, "apollo-tracing": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.4.0.tgz", - "integrity": "sha512-BlM8iQUQva4fm0xD/pLwkcz0degfB9a/aAn4k4cK36eLVD8XUkl7ptEB0c+cwcj7tOYpV1r5QX1XwdayBzlHSg==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.5.2.tgz", + "integrity": "sha512-2FdwRvPIq9uuF6OzONroXep6VBGqzHOkP6LlcFQe7SdwxfRP+SD/ycHNSC1acVg2b8d+am9Kzqg2vV54UpOIKA==", "requires": { "apollo-server-env": "2.2.0", - "graphql-extensions": "0.4.0" + "graphql-extensions": "0.5.4" }, "dependencies": { "graphql-extensions": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.4.0.tgz", - "integrity": "sha512-8TUgIIUVpXWOcqq9RdmTSHUrhc3a/s+saKv9cCl8TYWHK9vyJIdea7ZaSKHGDthZNcsN+C3LulZYRL3Ah8ukoA==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.5.4.tgz", + "integrity": "sha512-qLThJGVMqcItE7GDf/xX/E40m/aeqFheEKiR5bfra4q5eHxQKGjnIc20P9CVqjOn9I0FkEiU9ypOobfmIf7t6g==", "requires": { - "@apollographql/apollo-tools": "^0.2.6" + "@apollographql/apollo-tools": "^0.3.3" } } } @@ -3312,7 +3316,13 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=" + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "arg": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", + "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==", + "dev": true }, "argparse": { "version": "1.0.10", @@ -3390,11 +3400,6 @@ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" - }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -3408,7 +3413,7 @@ "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dev": true, "requires": { "bn.js": "^4.0.0", @@ -3433,7 +3438,7 @@ }, "util": { "version": "0.10.3", - "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -3450,7 +3455,7 @@ "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs=", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, "assign-symbols": { @@ -3458,6 +3463,12 @@ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -3472,12 +3483,12 @@ "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=" + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" }, "async-retry": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.2.3.tgz", - "integrity": "sha1-plIfM4NY0yKxoAEreQMMb0EdHOA=", + "integrity": "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==", "requires": { "retry": "0.12.0" } @@ -3540,15 +3551,15 @@ } }, "babel-eslint": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.6.tgz", - "integrity": "sha512-aCdHjhzcILdP8c9lej7hvXKvQieyRt20SF102SIGyY4cUIiw6UaAtK4j2o3dXX74jEmy0TJ0CEhv4fTIM3SzcA==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.1.tgz", + "integrity": "sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ==", "dev": true, "requires": { - "@babel/code-frame": "7.0.0-beta.44", - "@babel/traverse": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44", - "babylon": "7.0.0-beta.44", + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", "eslint-scope": "3.7.1", "eslint-visitor-keys": "^1.0.0" } @@ -3580,12 +3591,6 @@ } } }, - "babylon": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", - "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", - "dev": true - }, "backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", @@ -3657,7 +3662,7 @@ "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha1-yrHmEY8FEJXli1KBrqjBzSK/wOM=", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", "dev": true }, "basic-auth": { @@ -3688,18 +3693,19 @@ "binary-extensions": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", - "integrity": "sha1-wteA9T1Fu6gxeokC1M7q86Y4WxQ=", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", "dev": true }, "bluebird": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true }, "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, "body-parser": { @@ -3772,7 +3778,7 @@ "boxen": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha1-VcbDmouljZxhrSLNh3Uy3rZlogs=", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", "dev": true, "requires": { "ansi-align": "^2.0.0", @@ -3834,7 +3840,7 @@ "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA=", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, "browserify-aes": { @@ -3854,7 +3860,7 @@ "browserify-cipher": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", "dev": true, "requires": { "browserify-aes": "^1.0.4", @@ -3865,7 +3871,7 @@ "browserify-des": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", "dev": true, "requires": { "cipher-base": "^1.0.1", @@ -3884,7 +3890,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { @@ -3910,26 +3916,26 @@ "browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "dev": true, "requires": { "pako": "~1.0.5" } }, "browserslist": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.5.tgz", - "integrity": "sha1-GpF2eKzAe1VgZ0jqGt+YRuqJIPc=", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.2.tgz", + "integrity": "sha512-ISS/AIAiHERJ3d45Fz0AVYKkgcy+F/eJHzKEvv1j0wwKGKD9T3BrwKr/5g45L+Y4XIK5PlTqefHciRFcfE1Jxg==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000912", - "electron-to-chromium": "^1.3.86", - "node-releases": "^1.0.5" + "caniuse-lite": "^1.0.30000939", + "electron-to-chromium": "^1.3.113", + "node-releases": "^1.1.8" } }, "buffer": { "version": "4.9.1", - "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { @@ -3952,7 +3958,7 @@ "buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha1-zn64Gjj3gp2wnIc/L7t5LAyY7AQ=" + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" }, "buffer-xor": { "version": "1.0.3", @@ -3984,35 +3990,11 @@ } }, "busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.0.tgz", + "integrity": "sha512-e+kzZRAbbvJPLjQz2z+zAyr78BSi9IFeBTyLwF76g78Q2zRt/RZ1NtS3MS17v2yLqYfLz69zHdC+1L4ja8PwqQ==", "requires": { - "dicer": "0.2.5", - "readable-stream": "1.1.x" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } + "dicer": "0.3.0" } }, "bytes": { @@ -4021,23 +4003,62 @@ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "cacache": { - "version": "10.0.4", - "resolved": "http://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", - "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", + "requires": { + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" + }, + "dependencies": { + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "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" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + } } }, "cache-base": { @@ -4067,19 +4088,10 @@ "mkdirp2": "^1.0.3" } }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", + "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", "dev": true }, "camel-case": { @@ -4099,15 +4111,15 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30000918", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000918.tgz", - "integrity": "sha1-Yoj3naPFyLReUC9HrY8+uR8Teak=", + "version": "1.0.30000939", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000939.tgz", + "integrity": "sha512-oXB23ImDJOgQpGjRv1tCtzAvJr4/OvrHi5SO2vUgB0g0xpdZZoA/BxfImiWfdwoYdUTtQrPsXsvYU/dmCSM8gg==", "dev": true }, "capture-stack-trace": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", - "integrity": "sha1-psC74fOPOqC5Ijjstv9Cw0TUE10=", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", "dev": true }, "catharsis": { @@ -4131,7 +4143,7 @@ "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha1-dgqnLPION5XoSxKHfODoNzeqKeU=", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", "dev": true, "requires": { "assertion-error": "^1.1.0", @@ -4146,7 +4158,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -4193,9 +4204,9 @@ } }, "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, "check-error": { @@ -4207,7 +4218,7 @@ "chokidar": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha1-NW/04rDo5D4yLRijckYLvPOszSY=", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -4233,7 +4244,7 @@ "chrome-trace-event": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", - "integrity": "sha1-Rakb0sIMlBHwljtarrmhuV4JzEg=", + "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -4242,25 +4253,19 @@ "ci-info": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha1-LKINu5zrMtRSSmgzAzE/AwSx5Jc=", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", "dev": true }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -4343,11 +4348,6 @@ } } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -4389,7 +4389,7 @@ "colors": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha1-OeAF1Uav4B4B+cTKj6UPaGoBIF0=" + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" }, "command-line-args": { "version": "5.0.2", @@ -4509,7 +4509,7 @@ "configstore": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", - "integrity": "sha1-xvJd767vJt8S3TNBSwAf6BpUP48=", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", "dev": true, "requires": { "dot-prop": "^4.1.0", @@ -4604,9 +4604,9 @@ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, "cookie-parser": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz", - "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.4.tgz", + "integrity": "sha512-lo13tqF3JEtFO7FyA49CqbhaFkskRJ0u/UAiINgrIXeRCY41c88/zxtrECl8AKH3B0hj9q10+h3Kt8I7KlW4tw==", "requires": { "cookie": "0.3.1", "cookie-signature": "1.0.6" @@ -4620,7 +4620,7 @@ "copy-concurrently": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", "requires": { "aproba": "^1.1.1", "fs-write-stream-atomic": "^1.0.8", @@ -4636,18 +4636,40 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "copy-webpack-plugin": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz", - "integrity": "sha1-5/QN2KaEd9QF3Rt6hUquMksVi64=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.0.tgz", + "integrity": "sha512-iiDj+8nnZeW/i8vYJ3+ABSZkOefJnDYIGLojiZKKFDvf1wcEInABXH1+hN7axQMn04qvJxKjgVOee0e14XPtCg==", "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", + "cacache": "^11.3.1", + "find-cache-dir": "^2.0.0", "globby": "^7.1.1", "is-glob": "^4.0.0", "loader-utils": "^1.1.0", "minimatch": "^3.0.4", - "p-limit": "^1.0.0", - "serialize-javascript": "^1.4.0" + "normalize-path": "^3.0.0", + "p-limit": "^2.1.0", + "serialize-javascript": "^1.4.0", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==" + } } }, "core-js": { @@ -4663,7 +4685,7 @@ "cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha1-6sEdpRWS3Ya58G9uesKTs9+HXSk=", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "requires": { "object-assign": "^4", "vary": "^1" @@ -4677,7 +4699,7 @@ "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", "dev": true, "requires": { "bn.js": "^4.1.0", @@ -4752,7 +4774,7 @@ "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dev": true, "requires": { "browserify-cipher": "^1.0.0", @@ -4815,6 +4837,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -4832,7 +4855,7 @@ "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha1-38lARACtHI/gI+faHfHBR8S0RN8=", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "requires": { "type-detect": "^4.0.0" @@ -4858,7 +4881,7 @@ "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "requires": { "object-keys": "^1.0.12" } @@ -4900,43 +4923,6 @@ } } }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" - }, - "dependencies": { - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, "delegate": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", @@ -4973,41 +4959,17 @@ "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" }, "dicer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", + "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", "requires": { - "readable-stream": "1.1.x", "streamsearch": "0.1.2" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } } }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI=", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "diffie-hellman": { @@ -5022,11 +4984,10 @@ } }, "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha1-CyBdK2rvmCOMooZZioIE0p0KADQ=", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", "requires": { - "arrify": "^1.0.1", "path-type": "^3.0.0" } }, @@ -5051,9 +5012,9 @@ } }, "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { "esutils": "^2.0.2" @@ -5072,7 +5033,7 @@ "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, "dot-case": { @@ -5087,7 +5048,7 @@ "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "dev": true, "requires": { "is-obj": "^1.0.0" @@ -5096,7 +5057,7 @@ "dotenv": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", - "integrity": "sha1-lBwEEFNdlCyL7PKNPzV9vZ1HYGQ=" + "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==" }, "dtrace-provider": { "version": "0.8.6", @@ -5125,9 +5086,9 @@ } }, "ecdsa-sig-formatter": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", - "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "requires": { "safe-buffer": "^5.0.1" } @@ -5138,15 +5099,15 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.90", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.90.tgz", - "integrity": "sha1-tMUbgwO+/xjyt0gXQCv0iY4JVYo=", + "version": "1.3.113", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz", + "integrity": "sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g==", "dev": true }, "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha1-wtC3d2kRuGcixjLDwGxg8vgZk5o=", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -5158,6 +5119,12 @@ "minimalistic-crypto-utils": "^1.0.0" } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", @@ -5179,7 +5146,7 @@ "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "requires": { "once": "^1.4.0" } @@ -5219,21 +5186,32 @@ } }, "es-abstract": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", - "integrity": "sha1-nbvdJ8aFbwABQhyhh4LXhr+KYWU=", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", "requires": { - "es-to-primitive": "^1.1.1", + "es-to-primitive": "^1.2.0", "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + }, + "dependencies": { + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + } } }, "es-to-primitive": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha1-7fckeAM0VujdqO8J4ArZZQcH83c=", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -5251,75 +5229,165 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", - "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "version": "5.14.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.14.1.tgz", + "integrity": "sha512-CyUMbmsjxedx8B0mr79mNOqetvkbij/zrXnFeK2zc3pGRn3/tibjiNAv/3UxFEyfMDjh+ZqTrJrEGBFiGfD5Og==", "dev": true, "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.0", + "eslint-utils": "^1.3.1", "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.4", - "esquery": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", + "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", + "inquirer": "^6.2.2", + "js-yaml": "^3.12.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", "optionator": "^0.8.2", "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", "progress": "^2.0.0", - "regexpp": "^1.0.1", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" }, "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.2.tgz", + "integrity": "sha512-4UFy0/LgDo7Oa/+wOAlj44tp9K78u38E5/359eSrqEp1Z5PdVfimCcs7SluXMP755RUQu6d2b4AvF0R1C9RZjg==", "dev": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "globals": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.2.tgz", + "integrity": "sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true } } }, "eslint-config-standard": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz", - "integrity": "sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz", + "integrity": "sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ==", "dev": true }, "eslint-import-resolver-node": { @@ -5344,9 +5412,9 @@ } }, "eslint-loader": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-2.1.1.tgz", - "integrity": "sha512-1GrJFfSevQdYpoDzx8mEE2TDWsb/zmFuY09l6hURg1AeFIKQOvZ+vH0UPjzmd1CZIbfTV5HUkMeBmFiDBkgIsQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-2.1.2.tgz", + "integrity": "sha512-rA9XiXEOilLYPOIInvVH5S/hYfyTPyxag6DZhoQOduM+3TkghAEQ3VcFO8VnX4J4qg/UIBzp72aOf/xvYmpmsg==", "dev": true, "requires": { "loader-fs-cache": "^1.0.0", @@ -5357,13 +5425,13 @@ } }, "eslint-module-utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", - "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz", + "integrity": "sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==", "dev": true, "requires": { "debug": "^2.6.8", - "pkg-dir": "^1.0.0" + "pkg-dir": "^2.0.0" }, "dependencies": { "debug": { @@ -5374,53 +5442,35 @@ "requires": { "ms": "2.0.0" } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } } } }, + "eslint-plugin-es": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz", + "integrity": "sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw==", + "dev": true, + "requires": { + "eslint-utils": "^1.3.0", + "regexpp": "^2.0.1" + } + }, "eslint-plugin-import": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", - "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz", + "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==", "dev": true, "requires": { "contains-path": "^0.1.0", - "debug": "^2.6.8", + "debug": "^2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.2.0", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.3.0", + "has": "^1.0.3", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", "read-pkg-up": "^2.0.0", - "resolve": "^1.6.0" + "resolve": "^1.9.0" }, "dependencies": { "debug": { @@ -5442,47 +5492,79 @@ "isarray": "^1.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "^1.0.6" } } } }, "eslint-plugin-node": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz", - "integrity": "sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-8.0.1.tgz", + "integrity": "sha512-ZjOjbjEi6jd82rIpFSgagv4CHWzG9xsQAVp1ZPlhRnnYxcTgENUVBvhYmkQ7GvT1QFijUSo69RaiOJKhMu6i8w==", "dev": true, "requires": { - "ignore": "^3.3.6", + "eslint-plugin-es": "^1.3.1", + "eslint-utils": "^1.3.1", + "ignore": "^5.0.2", "minimatch": "^3.0.4", - "resolve": "^1.3.3", - "semver": "^5.4.1" + "resolve": "^1.8.1", + "semver": "^5.5.0" }, "dependencies": { - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "ignore": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.0.5.tgz", + "integrity": "sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA==", "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } } } }, "eslint-plugin-promise": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", - "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz", + "integrity": "sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==", "dev": true }, "eslint-plugin-standard": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz", - "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz", + "integrity": "sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==", "dev": true }, "eslint-scope": { @@ -5495,6 +5577,12 @@ "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -5502,13 +5590,14 @@ "dev": true }, "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", "dev": true, "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" } }, "esprima": { @@ -5529,7 +5618,7 @@ "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { "estraverse": "^4.1.0" @@ -5554,18 +5643,18 @@ "eventemitter3": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha1-CQtNbNvWRe0Qv3UNS1QHlC17oWM=" + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==" }, "events": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", + "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", "dev": true }, "evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "requires": { "md5.js": "^1.3.4", @@ -5675,7 +5764,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { "ms": "2.0.0" } @@ -5754,14 +5843,25 @@ } }, "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", "dev": true, "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } } }, "extglob": { @@ -5868,8 +5968,7 @@ "figgy-pudding": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha1-hiRwESkBxyeg5JWoB0S9W6odZ5A=", - "dev": true + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==" }, "figures": { "version": "2.0.0", @@ -5881,22 +5980,21 @@ } }, "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "^2.0.1" } }, "file-loader": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", - "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", + "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", "requires": { "loader-utils": "^1.0.2", - "schema-utils": "^0.4.5" + "schema-utils": "^1.0.0" } }, "file-set": { @@ -5949,7 +6047,7 @@ "finalhandler": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha1-7r9O2EAHnIP0JJA4ydcDAIMBsQU=", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -5971,13 +6069,61 @@ } }, "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", + "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", "requires": { "commondir": "^1.0.1", "make-dir": "^1.0.0", - "pkg-dir": "^2.0.0" + "pkg-dir": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==" + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + } + } } }, "find-replace": { @@ -5994,6 +6140,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, "requires": { "locate-path": "^2.0.0" } @@ -6020,9 +6167,9 @@ } }, "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz", + "integrity": "sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==", "requires": { "expand-tilde": "^2.0.2", "is-plain-object": "^2.0.3", @@ -6032,37 +6179,84 @@ } }, "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + } + } }, "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", "dev": true, "requires": { - "circular-json": "^0.3.1", - "del": "^2.0.2", - "graceful-fs": "^4.1.2", - "write": "^0.2.1" + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "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" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "dev": true + }, "flush-write-stream": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha1-xdWG7zivYJdlC0m8QbVfq7GfNb0=", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.4" } }, "fmtr": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fmtr/-/fmtr-1.1.0.tgz", - "integrity": "sha1-R1RcTNo3rWkbDSDiaHbQdexz/mg=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fmtr/-/fmtr-1.1.1.tgz", + "integrity": "sha512-nb0b2t9fKK7/Xxh3cv5MNnqaLbT6N67anBsPy0eOwTErTXtz12diKDzDoeqXTN8Ie8/qg2xJEXNBW3Nb2Dd0lQ==", "requires": { - "lodash": "^4.17.4" + "lodash": "^4.17.11" } }, "for-in": { @@ -6111,9 +6305,9 @@ "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" }, "fs-capacitor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-1.0.1.tgz", - "integrity": "sha512-XdZK0Q78WP29Vm3FGgJRhRhrBm51PagovzWtW2kJ3Q6cYJbGtZqWSGTSPwvtEkyjIirFd7b8Yes/dpOYjt4RRQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-2.0.1.tgz", + "integrity": "sha512-kyV2oaG1/pu9NPosfGACmBym6okgzyg6hEtA5LSUq0dGpGLe278MVfMwVnSHDA/OBcTCHkPNqWL9eIwbPN6dDg==" }, "fs-readdir-recursive": { "version": "1.1.0", @@ -6144,9 +6338,9 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", "dev": true, "optional": true, "requires": { @@ -6163,7 +6357,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6172,7 +6367,7 @@ "optional": true }, "are-we-there-yet": { - "version": "1.1.4", + "version": "1.1.5", "bundled": true, "dev": true, "optional": true, @@ -6196,7 +6391,7 @@ } }, "chownr": { - "version": "1.0.1", + "version": "1.1.1", "bundled": true, "dev": true, "optional": true @@ -6204,7 +6399,8 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", @@ -6214,7 +6410,8 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6232,7 +6429,7 @@ } }, "deep-extend": { - "version": "0.5.1", + "version": "0.6.0", "bundled": true, "dev": true, "optional": true @@ -6281,7 +6478,7 @@ } }, "glob": { - "version": "7.1.2", + "version": "7.1.3", "bundled": true, "dev": true, "optional": true, @@ -6301,12 +6498,12 @@ "optional": true }, "iconv-lite": { - "version": "0.4.21", + "version": "0.4.24", "bundled": true, "dev": true, "optional": true, "requires": { - "safer-buffer": "^2.1.0" + "safer-buffer": ">= 2.1.2 < 3" } }, "ignore-walk": { @@ -6331,7 +6528,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6343,6 +6541,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6367,16 +6566,17 @@ "dev": true }, "minipass": { - "version": "2.2.4", + "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { - "safe-buffer": "^5.1.1", + "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "minizlib": { - "version": "1.1.0", + "version": "1.2.1", "bundled": true, "dev": true, "optional": true, @@ -6388,6 +6588,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6399,7 +6600,7 @@ "optional": true }, "needle": { - "version": "2.2.0", + "version": "2.2.4", "bundled": true, "dev": true, "optional": true, @@ -6410,18 +6611,18 @@ } }, "node-pre-gyp": { - "version": "0.10.0", + "version": "0.10.3", "bundled": true, "dev": true, "optional": true, "requires": { "detect-libc": "^1.0.2", "mkdirp": "^0.5.1", - "needle": "^2.2.0", + "needle": "^2.2.1", "nopt": "^4.0.1", "npm-packlist": "^1.1.6", "npmlog": "^4.0.2", - "rc": "^1.1.7", + "rc": "^1.2.7", "rimraf": "^2.6.1", "semver": "^5.3.0", "tar": "^4" @@ -6438,13 +6639,13 @@ } }, "npm-bundled": { - "version": "1.0.3", + "version": "1.0.5", "bundled": true, "dev": true, "optional": true }, "npm-packlist": { - "version": "1.1.10", + "version": "1.2.0", "bundled": true, "dev": true, "optional": true, @@ -6480,6 +6681,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6519,12 +6721,12 @@ "optional": true }, "rc": { - "version": "1.2.7", + "version": "1.2.8", "bundled": true, "dev": true, "optional": true, "requires": { - "deep-extend": "^0.5.1", + "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" @@ -6554,18 +6756,19 @@ } }, "rimraf": { - "version": "2.6.2", + "version": "2.6.3", "bundled": true, "dev": true, "optional": true, "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" } }, "safe-buffer": { - "version": "5.1.1", + "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6580,7 +6783,7 @@ "optional": true }, "semver": { - "version": "5.5.0", + "version": "5.6.0", "bundled": true, "dev": true, "optional": true @@ -6601,6 +6804,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6620,6 +6824,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6631,17 +6836,17 @@ "optional": true }, "tar": { - "version": "4.4.1", + "version": "4.4.8", "bundled": true, "dev": true, "optional": true, "requires": { - "chownr": "^1.0.1", + "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", + "safe-buffer": "^5.1.2", "yallist": "^3.0.2" } }, @@ -6652,23 +6857,25 @@ "optional": true }, "wide-align": { - "version": "1.1.2", + "version": "1.1.3", "bundled": true, "dev": true, "optional": true, "requires": { - "string-width": "^1.0.2" + "string-width": "^1.0.2 || 2" } }, "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { - "version": "3.0.2", + "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -6684,9 +6891,9 @@ "dev": true }, "fuse.js": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.3.0.tgz", - "integrity": "sha1-Hk/hcqYGhyMPtUpcskfrluLn6IU=" + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.4.2.tgz", + "integrity": "sha512-WVbrm+cAxPtyMqdtL7cYhR7aZJPhtOfjNClPya8GKMVukKDYs7pEnPINeRVX1C9WmWgU8MdYGYbUPAP2AJXdoQ==" }, "get-caller-file": { "version": "1.0.3", @@ -6764,12 +6971,6 @@ "resolve-dir": "^1.0.0" } }, - "global-modules-path": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.0.tgz", - "integrity": "sha512-HchvMJNYh9dGSCy8pOQ2O8u/hoXaL+0XhnrwH0RyLiSXMMTl9W3N6KUU73+JFOg5PGjtzl6VZzUQsnrpm7Szag==", - "dev": true - }, "global-prefix": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", @@ -6818,7 +7019,7 @@ }, "got": { "version": "6.7.1", - "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", "dev": true, "requires": { @@ -6841,19 +7042,19 @@ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "graphql": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz", - "integrity": "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.1.1.tgz", + "integrity": "sha512-C5zDzLqvfPAgTtP8AUPIt9keDabrdRAqSWjj2OPRKrKxI9Fb65I36s1uCs1UUBFnSWTdO7hyHi7z1ZbwKMKF6Q==", "requires": { "iterall": "^1.2.2" } }, "graphql-extensions": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.4.1.tgz", - "integrity": "sha512-Xei4rBxbsTHU6dYiq9y1xxbpRMU3+Os7yD3vXV5W4HbTaxRMizDmu6LAvV4oBEi0ttwICHARQjYTjDTDhHnxrQ==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.5.7.tgz", + "integrity": "sha512-HrU6APE1PiehZ46scMB3S5DezSeCATd8v+e4mmg2bqszMyCFkmAnmK6hR1b5VjHxhzt5/FX21x1WsXfqF4FwdQ==", "requires": { - "@apollographql/apollo-tools": "^0.2.6" + "@apollographql/apollo-tools": "^0.3.3" } }, "graphql-import": { @@ -6868,7 +7069,7 @@ "graphql-request": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-1.8.2.tgz", - "integrity": "sha1-OY0QrhXFhWdnQb3j/AHVypSPj74=", + "integrity": "sha512-dDX2M+VMsxXFCmUX0Vo0TopIZIX4ggzOtiCsThgtrKR4niiaagsGTDIHj3fsOMFETpa064vzovI+4YV4QnMbcg==", "dev": true, "requires": { "cross-fetch": "2.2.2" @@ -6877,22 +7078,22 @@ "graphql-subscriptions": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-1.0.0.tgz", - "integrity": "sha1-R1JnaUs71GWvZHfbq0Jjo/YnArg=", + "integrity": "sha512-+ytmryoHF1LVf58NKEaNPRUzYyXplm120ntxfPcgOBC7TnK7Tv/4VRHeh4FAR9iL+O1bqhZs4nkibxQ+OA5cDQ==", "requires": { "iterall": "^1.2.1" } }, "graphql-tag": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.0.tgz", - "integrity": "sha1-h9oCS+hj41dVGyuHAOSW7i1DU64=" + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.1.tgz", + "integrity": "sha512-jApXqWBzNXQ8jYa/HLkZJaVw9jgwNqZkywa2zfFn16Iv1Zb7ELNHkJaXHR7Quvd5SIGsy6Ny7SUKATgnu05uEg==" }, "graphql-tools": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-3.1.1.tgz", - "integrity": "sha512-yHvPkweUB0+Q/GWH5wIG60bpt8CTwBklCSzQdEHmRUgAdEQKxw+9B7zB3dG7wB3Ym7M7lfrS4Ej+jtDZfA2UXg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.4.tgz", + "integrity": "sha512-chF12etTIGVVGy3fCTJ1ivJX2KB7OSG4c6UOJQuqOHCmBQwTyNgCDuejZKvpYxNZiEx7bwIjrodDgDe9RIkjlw==", "requires": { - "apollo-link": "^1.2.2", + "apollo-link": "^1.2.3", "apollo-utilities": "^1.0.1", "deprecated-decorator": "^0.1.6", "iterall": "^1.1.3", @@ -6900,28 +7101,33 @@ } }, "graphql-upload": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-8.0.2.tgz", - "integrity": "sha512-u8a5tKPfJ0rU4MY+B3skabL8pEjMkm3tUzq25KBx6nT0yEWmqUO7Z5tdwvwYLFpkLwew94Gue0ARbZtar3gLTw==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-8.0.4.tgz", + "integrity": "sha512-jsTfVYXJ5mU6BXiiJ20CUCAcf41ICCQJ2ltwQFUuaFKiY4JhlG99uZZp5S3hbpQ/oA1kS7hz4pRtsnxPCa7Yfg==", "requires": { - "busboy": "^0.2.14", - "fs-capacitor": "^1.0.0", + "busboy": "^0.3.0", + "fs-capacitor": "^2.0.0", "http-errors": "^1.7.1", "object-path": "^0.11.4" }, "dependencies": { "http-errors": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.1.tgz", - "integrity": "sha512-jWEUgtZWGSMba9I1N3gc1HmvpBUaNC9vDdA46yScAdp+C5rdEuKWUBLWTQpW9FwSWSbYYs++b6SDCxf9UEJzfw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "requires": { "depd": "~1.1.2", "inherits": "2.0.3", - "setprototypeof": "1.1.0", + "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" } }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -6951,13 +7157,13 @@ "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha1-8nNdwig2dPpnR4sQGBBZNVw2nl4=", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, "handlebars": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", - "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz", + "integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==", "dev": true, "requires": { "async": "^2.5.0", @@ -6967,12 +7173,12 @@ }, "dependencies": { "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "source-map": { @@ -7063,7 +7269,7 @@ "hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I=", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -7071,9 +7277,9 @@ } }, "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, "header-case": { @@ -7146,7 +7352,7 @@ "ieee754": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha1-UL8k5bnIu5ivSWTJQc2wkY2ntgs=", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", "dev": true }, "iferr": { @@ -7155,9 +7361,9 @@ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" }, "ignore": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==" + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" }, "ignore-by-default": { "version": "1.0.1", @@ -7165,6 +7371,16 @@ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, + "import-fresh": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", + "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, "import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -7201,9 +7417,9 @@ } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -7287,25 +7503,52 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", + "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "external-editor": "^2.0.4", + "external-editor": "^3.0.3", "figures": "^2.0.0", - "lodash": "^4.3.0", + "lodash": "^4.17.11", "mute-stream": "0.0.7", "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", + "rxjs": "^6.4.0", "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", + "strip-ansi": "^5.0.0", "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } } }, "interpret": { @@ -7379,24 +7622,15 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=" + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" }, "is-ci": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha1-43ecjuF/zPQoSI9uKBGH8uYyhBw=", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", "dev": true, "requires": { "ci-info": "^1.5.0" @@ -7537,7 +7771,7 @@ }, "is-obj": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, @@ -7556,21 +7790,6 @@ } } }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true, - "requires": { - "is-path-inside": "^1.0.0" - } - }, "is-path-inside": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", @@ -7621,12 +7840,6 @@ "is-unc-path": "^1.0.0" } }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", @@ -7641,7 +7854,7 @@ "is-symbol": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg=", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "requires": { "has-symbols": "^1.0.0" } @@ -7709,9 +7922,9 @@ "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==" }, "js-levenshtein": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.4.tgz", - "integrity": "sha1-Olbjy/WJygCB6yLNm6CxKQoW0m4=", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", "dev": true }, "js-stringify": { @@ -7791,7 +8004,7 @@ "jsdoc-babel": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsdoc-babel/-/jsdoc-babel-0.5.0.tgz", - "integrity": "sha1-che4ggRp/mANzP3uiVZIxqDdSi4=", + "integrity": "sha512-PYfTbc3LNTeR8TpZs2M94NLDWqARq0r9gx3SvuziJfmJS7/AeMKvtj0xjzOX0R/4MOVA7/FqQQK7d6U0iEoztQ==", "dev": true, "requires": { "jsdoc-regex": "^1.0.1", @@ -7842,7 +8055,7 @@ "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, "json-schema-traverse": { @@ -7850,14 +8063,6 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "requires": { - "jsonify": "~0.0.0" - } - }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -7869,17 +8074,12 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" - }, "jsonwebtoken": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz", - "integrity": "sha1-h1f3tMt0QNhtXi877O+nBTbI5Go=", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz", + "integrity": "sha512-IqEycp0znWHNA11TpYi77bVgyBO/pGESDh7Ajhas+u0ttkGkKYIIAjniL4Bw5+oVejVF+SYkaI7XKfwCCyeTuA==", "requires": { - "jws": "^3.1.5", + "jws": "^3.2.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", @@ -7887,7 +8087,8 @@ "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", - "ms": "^2.1.1" + "ms": "^2.1.1", + "semver": "^5.6.0" }, "dependencies": { "ms": { @@ -8052,21 +8253,21 @@ } }, "jwa": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz", - "integrity": "sha1-hyQOdsmAjb3hh4PPImTvSSnuUOY=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.3.0.tgz", + "integrity": "sha512-SxObIyzv9a6MYuZYaSN6DhSm9j3+qkokwvCB0/OTSV5ylPq1wUQiygZQcHT5Qlux0I5kmISx3J86TxKhuefItg==", "requires": { "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.10", + "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "jws": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz", - "integrity": "sha1-gNEtBbKT0ehB58uLTmnlYa3Pg08=", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz", + "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==", "requires": { - "jwa": "^1.1.5", + "jwa": "^1.2.0", "safe-buffer": "^5.0.1" } }, @@ -8090,19 +8291,20 @@ } }, "knex": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/knex/-/knex-0.15.2.tgz", - "integrity": "sha1-YFm4dIlgX0zIdZmm0qnSZXCek0A=", - "requires": { - "babel-runtime": "^6.26.0", - "bluebird": "^3.5.1", - "chalk": "2.3.2", - "commander": "^2.16.0", - "debug": "3.1.0", + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/knex/-/knex-0.16.3.tgz", + "integrity": "sha512-jGTOBW8b7exaBPfCKJSlv5q320IvWw9hEdtnURtbb0k3HusfZrR4UYiEewem8Nl7VqJILoCj99SjCK3W54UNPg==", + "requires": { + "@babel/polyfill": "^7.0.0", + "@types/bluebird": "^3.5.25", + "bluebird": "^3.5.3", + "chalk": "2.4.1", + "commander": "^2.19.0", + "debug": "4.1.0", "inherits": "~2.0.3", "interpret": "^1.1.0", "liftoff": "2.5.0", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "minimist": "1.2.0", "mkdirp": "^0.5.1", "pg-connection-string": "2.0.0", @@ -8112,14 +8314,27 @@ "v8flags": "^3.1.1" }, "dependencies": { - "chalk": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", - "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "@types/bluebird": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.25.tgz", + "integrity": "sha512-yfhIBix+AIFTmYGtkC0Bi+XGjSkOINykqKvO/Wqdz/DuXlAKK7HmhLAXdPIGsV4xzKcL3ev/zYc4yLNo+OvGaw==" + }, + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ms": "^2.1.1" } }, "minimist": { @@ -8127,6 +8342,11 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", @@ -8182,18 +8402,22 @@ } }, "ldapauth-fork": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ldapauth-fork/-/ldapauth-fork-4.1.0.tgz", - "integrity": "sha1-WdpiYC417bOuPYoU7LE+ipOJk9I=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ldapauth-fork/-/ldapauth-fork-4.2.0.tgz", + "integrity": "sha512-DFYhOO9UPX/fIUnwAjJ4zCq2osR3pyS9TK24oBRLHj7+iw9OAbckHLcdDkgI//IajUEsF6Ngz0uXod6A88L2HA==", "requires": { "@types/ldapjs": "^1.0.0", "@types/node": "^10.12.12", "bcryptjs": "^2.4.0", "ldapjs": "^1.0.2", - "lru-cache": "^5.1.1", - "moment": "^2.22.2" + "lru-cache": "^5.1.1" }, "dependencies": { + "@types/node": { + "version": "10.12.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.27.tgz", + "integrity": "sha512-e9wgeY6gaY21on3ve0xAjgBVjGDWq/xUteK0ujsE53bUoxycMkqfnkUgMt6ffZtykZ5X12Mg3T7Pw4TRCObDKg==" + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -8202,11 +8426,6 @@ "yallist": "^3.0.2" } }, - "moment": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.23.0.tgz", - "integrity": "sha512-3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA==" - }, "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", @@ -8328,9 +8547,9 @@ } }, "loader-runner": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", - "integrity": "sha1-Am8S/nwxFZkolqwCugIrqSlxuXk=", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", "dev": true }, "loader-utils": { @@ -8347,6 +8566,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -8432,10 +8652,24 @@ "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, "long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha1-mntxz7fTYaGU6lVSQckvdGjVvyg=" + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, "longest": { "version": "1.0.1", @@ -8468,13 +8702,14 @@ "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha1-b54wtHCE2XGnyCD/FabFFnt0wm8=", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, "lru-cache": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", + "dev": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -8483,11 +8718,17 @@ "make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "requires": { "pify": "^3.0.0" } }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -8496,10 +8737,16 @@ "kind-of": "^6.0.2" } }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "dev": true + }, "map-age-cleaner": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz", - "integrity": "sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", "dev": true, "requires": { "p-defer": "^1.0.0" @@ -8527,7 +8774,7 @@ "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, "requires": { "hash-base": "^3.0.0", @@ -8538,7 +8785,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true } } @@ -8605,7 +8852,7 @@ "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, "requires": { "bn.js": "^4.0.0", @@ -8639,7 +8886,7 @@ "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, "minimalistic-crypto-utils": { @@ -8662,9 +8909,9 @@ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mississippi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", - "integrity": "sha1-NEKlCPr8KFAEhv7qmUCWduTuWm8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", "requires": { "concat-stream": "^1.5.0", "duplexify": "^3.4.2", @@ -8672,10 +8919,21 @@ "flush-write-stream": "^1.0.0", "from2": "^2.1.0", "parallel-transform": "^1.1.0", - "pump": "^2.0.1", + "pump": "^3.0.0", "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } } }, "mixin-deep": { @@ -8712,32 +8970,259 @@ "dev": true }, "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha1-bYrlCPWRZ/lA8rWzxKYSrlDJCuY=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.0.2.tgz", + "integrity": "sha512-RtTJsmmToGyeTznSOMoM6TPEk1A84FQaHIciKrRqARZx+B5ccJ5tXlmJzEKGBxZdqk9UjpRsesZTUkZmR5YnuQ==", "dev": true, "requires": { + "ansi-colors": "3.2.3", "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", + "debug": "3.2.6", "diff": "3.5.0", "escape-string-regexp": "1.0.5", - "glob": "7.1.2", + "findup-sync": "2.0.0", + "glob": "7.1.3", "growl": "1.10.5", - "he": "1.1.1", + "he": "1.2.0", + "js-yaml": "3.12.0", + "log-symbols": "2.2.0", "minimatch": "3.0.4", "mkdirp": "0.5.1", - "supports-color": "5.4.0" + "ms": "2.1.1", + "node-environment-flags": "1.0.4", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "12.0.5", + "yargs-parser": "11.1.1", + "yargs-unparser": "1.5.0" }, "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "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" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "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==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz", + "integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^2.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } } } }, + "mocha-graphql-register": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mocha-graphql-register/-/mocha-graphql-register-1.0.0.tgz", + "integrity": "sha1-FALzIKxAFLxoya196htZsLe4pp8=", + "dev": true + }, "moment": { "version": "2.21.0", "resolved": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz", @@ -8888,16 +9373,24 @@ "lower-case": "^1.1.1" } }, + "node-environment-flags": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.4.tgz", + "integrity": "sha512-M9rwCnWVLW7PX+NUWe3ejEdiLYinRpsEre9hMkU/6NS4h+EEulYaDH1gCEZ2gyXsmw+RXYDaV2JkkTNcsPDJ0Q==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3" + } + }, "node-fetch": { "version": "2.1.2", "resolved": "http://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", - "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", - "dev": true + "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=" }, "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha1-X5QmPUBPbkR2fXJpAf/wVHjWAN8=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", + "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", "dev": true, "requires": { "assert": "^1.1.1", @@ -8907,7 +9400,7 @@ "constants-browserify": "^1.0.0", "crypto-browserify": "^3.11.0", "domain-browser": "^1.1.1", - "events": "^1.0.0", + "events": "^3.0.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", "path-browserify": "0.0.0", @@ -8921,35 +9414,80 @@ "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", "url": "^0.11.0", - "util": "^0.10.3", + "util": "^0.11.0", "vm-browserify": "0.0.4" - } - }, - "node-releases": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.1.tgz", - "integrity": "sha1-j/+K6hz8rR+0IF+AUUkFT79zyv0=", - "dev": true, - "requires": { + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + } + } + }, + "node-releases": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.8.tgz", + "integrity": "sha512-gQm+K9mGCiT/NXHy+V/ZZS1N/LOaGGqRAAJJs3X9Ah1g+CIbRcBgNyoNYQ+SEtcyAtB9KqDruu+fF7nWjsqRaA==", + "dev": true, + "requires": { "semver": "^5.3.0" } }, "nodemon": { - "version": "1.18.8", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.18.8.tgz", - "integrity": "sha1-60wAUtyBOVvcUD88iuPLqGynFGo=", + "version": "1.18.10", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.18.10.tgz", + "integrity": "sha512-we51yBb1TfEvZamFchRgcfLbVYgg0xlGbyXmOtbBzDwxwgewYS/YbZ5tnlnsH51+AoSTTsT3A2E/FloUbtH8cQ==", "dev": true, "requires": { - "chokidar": "^2.0.4", + "chokidar": "^2.1.0", "debug": "^3.1.0", "ignore-by-default": "^1.0.1", "minimatch": "^3.0.4", - "pstree.remy": "^1.1.3", + "pstree.remy": "^1.1.6", "semver": "^5.5.0", "supports-color": "^5.2.0", "touch": "^3.1.0", "undefsafe": "^2.0.2", "update-notifier": "^2.5.0" + }, + "dependencies": { + "chokidar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.2.tgz", + "integrity": "sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.0" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } } }, "nopt": { @@ -8962,15 +9500,32 @@ } }, "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", + "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } } }, "normalize-path": { @@ -9042,15 +9597,15 @@ "dev": true }, "object-hash": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.0.tgz", - "integrity": "sha512-05KzQ70lSeGSrZJQXE5wNDiTkBJDlUT/myi6RX9dVIvz7a7Qh4oH93BQdiPMn27nldYvVQCKMUaM83AfizZlsQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", + "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", "dev": true }, "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha1-CcU4VTd1dTEMymL1W7M0q/97PtI=" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==" }, "object-path": { "version": "0.11.4", @@ -9071,6 +9626,18 @@ "isobject": "^3.0.0" } }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, "object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", @@ -9201,7 +9768,7 @@ "output-file-sync": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz", - "integrity": "sha1-9TEYKC9fVTwnmVQXkrcjpMcUMMA=", + "integrity": "sha512-mDho4qm7WgIXIGf4eYU1RHN2UU5tPfVYVSRwDJw0uTmj35DQUt/eNp19N7v6T3SrR0ESTEf2up2CGO73qI35zQ==", "dev": true, "requires": { "graceful-fs": "^4.1.11", @@ -9222,15 +9789,16 @@ "dev": true }, "p-is-promise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", + "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==", "dev": true }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, "requires": { "p-try": "^1.0.0" } @@ -9239,6 +9807,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, "requires": { "p-limit": "^1.1.0" } @@ -9246,7 +9815,8 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true }, "package-json": { "version": "4.0.1", @@ -9273,14 +9843,14 @@ } }, "packet-reader": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", - "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" }, "pako": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz", - "integrity": "sha1-JHNDkCG1fxUWyC9YvnJ1rY7xuyc=", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.8.tgz", + "integrity": "sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA==", "dev": true }, "parallel-transform": { @@ -9302,17 +9872,27 @@ "no-case": "^2.2.0" } }, + "parent-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.0.tgz", + "integrity": "sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parse-asn1": { - "version": "5.1.1", - "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", + "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", "dev": true, "requires": { "asn1.js": "^4.0.0", "browserify-aes": "^1.0.0", "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" } }, "parse-filepath": { @@ -9369,14 +9949,21 @@ } }, "passport-ldapauth": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/passport-ldapauth/-/passport-ldapauth-2.1.1.tgz", - "integrity": "sha1-S0R4zSg8gt6JYGmj5CfvjPopX+E=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/passport-ldapauth/-/passport-ldapauth-2.1.2.tgz", + "integrity": "sha512-V+oYNhJwW/ncYHS1IX3eVN9TUH38OsD15Cwo8w+FIV+GXKFJRtUhZyt5nNwExyU0ujMya8Rtzm04+4d8BjvBUg==", "requires": { - "@types/node": "^10.12.12", - "@types/passport": "^0.4.7", - "ldapauth-fork": "^4.1.0", + "@types/node": "^10.12.26", + "@types/passport": "^1.0.0", + "ldapauth-fork": "^4.2.0", "passport-strategy": "^1.0.0" + }, + "dependencies": { + "@types/node": { + "version": "10.12.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.27.tgz", + "integrity": "sha512-e9wgeY6gaY21on3ve0xAjgBVjGDWq/xUteK0ujsE53bUoxycMkqfnkUgMt6ffZtykZ5X12Mg3T7Pw4TRCObDKg==" + } } }, "passport-strategy": { @@ -9395,7 +9982,7 @@ }, "path-browserify": { "version": "0.0.0", - "resolved": "http://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, @@ -9462,7 +10049,7 @@ "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "requires": { "pify": "^3.0.0" } @@ -9481,7 +10068,7 @@ "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha1-l2wgZTBhexTrsyEUI597CTNuk6Y=", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", "dev": true, "requires": { "create-hash": "^1.1.2", @@ -9492,15 +10079,15 @@ } }, "pg": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-7.7.1.tgz", - "integrity": "sha1-VGsZL/SEMitpaJOR+IXeO6kaMNQ=", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-7.8.1.tgz", + "integrity": "sha512-m9aIrOV4mgfo+1Ze+eNoJwaWZDvpeBz8Kzwi0zzqLC+tQBsQgIuu+FGPqzyRv9HFlS7tHO1I33LKp9gP5g7U4Q==", "requires": { "buffer-writer": "2.0.0", - "packet-reader": "0.3.1", + "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", "pg-pool": "^2.0.4", - "pg-types": "~1.12.1", + "pg-types": "~2.0.0", "pgpass": "1.x", "semver": "4.3.2" }, @@ -9522,17 +10109,23 @@ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.0.0.tgz", "integrity": "sha1-Pu/lmX4G2Ugh5NUC5CtqHHP434I=" }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, "pg-pool": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.4.tgz", - "integrity": "sha1-Ba0PLZQ32JyUzMT00KRKxlrehls=" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.6.tgz", + "integrity": "sha512-hod2zYQxM8Gt482q+qONGTYcg/qVcV32VHVPtktbBJs0us3Dj7xibISw0BAAXVMCzt8A/jhfJvpZaxUlqtqs0g==" }, "pg-types": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.12.1.tgz", - "integrity": "sha1-1kCH45A7WP+q0nnnWVxSIIoUw9I=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.0.0.tgz", + "integrity": "sha512-THUD7gQll5tys+5eQ8Rvs7DjHiIC3bLqixk3gMN9Hu8UrCBAOjf35FoI39rTGGc3lM2HU/R+Knpxvd11mCwOMA==", "requires": { - "postgres-array": "~1.0.0", + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.0", "postgres-interval": "^1.1.0" @@ -9570,16 +10163,11 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, "requires": { "find-up": "^2.1.0" } }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true - }, "popper.js": { "version": "1.14.4", "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.4.tgz", @@ -9591,9 +10179,9 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postgres-array": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.3.tgz", - "integrity": "sha1-xWH8OyZrIUUfxlVThPSYbXjsgPU=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" }, "postgres-bytea": { "version": "1.0.0", @@ -9606,9 +10194,9 @@ "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=" }, "postgres-interval": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.2.tgz", - "integrity": "sha1-v3H/kCY18hyyQaAT/EIdgdHbFak=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", "requires": { "xtend": "^4.0.0" } @@ -9644,12 +10232,12 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=" + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, "promise": { @@ -9677,7 +10265,7 @@ "protobufjs": { "version": "6.8.8", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", - "integrity": "sha1-yLTxKC/XqQ5vWxCe0RyEr4KQjnw=", + "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -9692,6 +10280,13 @@ "@types/long": "^4.0.0", "@types/node": "^10.1.0", "long": "^4.0.0" + }, + "dependencies": { + "@types/node": { + "version": "10.12.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.27.tgz", + "integrity": "sha512-e9wgeY6gaY21on3ve0xAjgBVjGDWq/xUteK0ujsE53bUoxycMkqfnkUgMt6ffZtykZ5X12Mg3T7Pw4TRCObDKg==" + } } }, "proxy-addr": { @@ -9712,18 +10307,19 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true }, "pstree.remy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.4.tgz", - "integrity": "sha1-oD1dvAa6Y5+23Uh0ZExLrZiC7CE=", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.6.tgz", + "integrity": "sha512-NdF35+QsqD7EgNEI5mkI/X+UwaxVEbQaz9f4IooEmMUv6ZPmlTQYGjBPJGgrlzNdjSvIy4MWMg6Q6vCgBO2K+w==", "dev": true }, "public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dev": true, "requires": { "bn.js": "^4.1.0", @@ -9859,7 +10455,7 @@ "pump": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -9868,7 +10464,7 @@ "pumpify": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "requires": { "duplexify": "^3.6.0", "inherits": "^2.0.3", @@ -9876,9 +10472,9 @@ } }, "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, "qs": { @@ -9904,9 +10500,9 @@ "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" }, "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha1-0wLFIpSFiISKjTAMkytEwkIx2oA=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { "safe-buffer": "^5.1.0" @@ -9915,7 +10511,7 @@ "randomfill": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, "requires": { "randombytes": "^2.0.5", @@ -9930,7 +10526,7 @@ "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "requires": { "deep-extend": "^0.6.0", @@ -9941,32 +10537,32 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } } }, "react": { - "version": "16.6.3", - "resolved": "https://registry.npmjs.org/react/-/react-16.6.3.tgz", - "integrity": "sha1-Jdd8kZEda73SPbQecPsJTMHghxw=", + "version": "16.8.3", + "resolved": "https://registry.npmjs.org/react/-/react-16.8.3.tgz", + "integrity": "sha512-3UoSIsEq8yTJuSu0luO1QQWYbgGEILm+eJl2QN/VLDi7hL+EN18M3q3oVZwmVzzBJ3DkM7RMdRwBmZZ+b4IzSA==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "scheduler": "^0.11.2" + "scheduler": "^0.13.3" } }, "react-dom": { - "version": "16.6.3", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.6.3.tgz", - "integrity": "sha1-j6e6aIPIUhG42i0O/v/J04JczMA=", + "version": "16.8.3", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.3.tgz", + "integrity": "sha512-ttMem9yJL4/lpItZAQ2NTFAbV7frotHk5DZEHXUOws2rMmrsvh1Na7ThGT0dTzUIl6pqTOi5tYREfL8AEna3lA==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "scheduler": "^0.11.2" + "scheduler": "^0.13.3" } }, "react-event-listener": { @@ -10075,7 +10671,7 @@ "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { "graceful-fs": "^4.1.11", @@ -10188,13 +10784,13 @@ "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha1-SoVuxLVuQHfFV1icroXnpMiGmhE=", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", "dev": true }, "regenerate-unicode-properties": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz", - "integrity": "sha1-EHQFr8xKGQ7F7UUOyqAO0Mr6ekw=", + "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", "dev": true, "requires": { "regenerate": "^1.4.0" @@ -10206,9 +10802,9 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz", - "integrity": "sha1-JkvZ/zioziSwbgY2SWsshWtXvLs=", + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.4.tgz", + "integrity": "sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==", "dev": true, "requires": { "private": "^0.1.6" @@ -10223,16 +10819,22 @@ "safe-regex": "^1.1.0" } }, + "regexp-tree": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.5.tgz", + "integrity": "sha512-nUmxvfJyAODw+0B13hj8CFVAxhe7fDEAgJgaotBu3nnR+IgGgZq59YedJP5VYTlkEfqjuK6TuRpnymKdatLZfQ==", + "dev": true + }, "regexpp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, "regexpu-core": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", - "integrity": "sha1-jUPg0SZog5aXIDRecMJ17grsDTI=", + "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", "dev": true, "requires": { "regenerate": "^1.4.0", @@ -10246,7 +10848,7 @@ "registry-auth-token": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", - "integrity": "sha1-hR/UkDjuy1hpERFa+EUmDuyYPyA=", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", "dev": true, "requires": { "rc": "^1.1.6", @@ -10265,13 +10867,13 @@ "regjsgen": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha1-p2NNwI+JIJwgSa3aNSVxH7lyZd0=", + "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", "dev": true }, "regjsparser": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha1-8eaui32iuulsmTmbhozWyTOiupw=", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -10279,7 +10881,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } @@ -10313,16 +10915,6 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, "requizzle": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", @@ -10380,9 +10972,9 @@ } }, "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "resolve-url": { @@ -10429,7 +11021,7 @@ "ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { "hash-base": "^3.0.0", @@ -10453,19 +11045,13 @@ "aproba": "^1.1.1" } }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", "dev": true, "requires": { - "rx-lite": "*" + "tslib": "^1.9.0" } }, "safe-buffer": { @@ -10493,20 +11079,21 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "scheduler": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.11.2.tgz", - "integrity": "sha512-+WCP3s3wOaW4S7C1tl3TEXp4l9lJn0ZK8G3W3WKRWmw77Z2cIFUW2MiNTMHn5sCjxN+t7N43HAOOgMjyAg5hlg==", + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.3.tgz", + "integrity": "sha512-UxN5QRYWtpR1egNWzJcVLk8jlegxAugswQc984lD3kU7NuobsO37/sRfbpTdBjtnD5TBNFA2Q2oLV5+UmPSmEQ==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } }, "schema-utils": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", - "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "requires": { "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", "ajv-keywords": "^3.1.0" } }, @@ -10516,10 +11103,9 @@ "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" }, "semver-diff": { "version": "2.1.0", @@ -10533,7 +11119,7 @@ "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha1-bsyh4PjBVtFBWXVZhI32RzCmu8E=", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "requires": { "debug": "2.6.9", "depd": "~1.1.2", @@ -10573,7 +11159,7 @@ "serialize-javascript": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", - "integrity": "sha1-GqM2FiyIqJDdrVOEuuvJOmVRYf4=" + "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==" }, "serve-favicon": { "version": "2.5.0", @@ -10597,7 +11183,7 @@ "serve-static": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha1-CV6Ecv1bRiN9tQzkhqQ/S4bGzsE=", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -10646,7 +11232,6 @@ "version": "2.4.11", "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -10680,11 +11265,13 @@ "dev": true }, "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", "dev": true, "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", "is-fullwidth-code-point": "^2.0.0" } }, @@ -10848,9 +11435,9 @@ } }, "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", + "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -10871,9 +11458,9 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -10881,9 +11468,9 @@ } }, "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "spdx-expression-parse": { @@ -10897,15 +11484,15 @@ } }, "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", "dev": true }, "split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha1-YFvZvjA6pZ+zX5Ip++oN3snqB9k=", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "requires": { "through": "2" } @@ -10925,11 +11512,11 @@ "dev": true }, "ssri": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", - "integrity": "sha1-ujhyycbTOgcEp9cf8EXl7EiZnQY=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "requires": { - "safe-buffer": "^5.1.1" + "figgy-pudding": "^3.5.1" } }, "static-extend": { @@ -10957,9 +11544,9 @@ "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" }, "stream-browserify": { - "version": "2.0.1", - "resolved": "http://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", "dev": true, "requires": { "inherits": "~2.0.1", @@ -10998,7 +11585,7 @@ "stream-http": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "dev": true, "requires": { "builtin-status-codes": "^3.0.0", @@ -11025,7 +11612,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { @@ -11111,7 +11698,7 @@ "subscriptions-transport-ws": { "version": "0.9.15", "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.15.tgz", - "integrity": "sha1-aKi3ugA32MSJ+y9aEC0UlNspfQ0=", + "integrity": "sha512-f9eBfWdHsePQV67QIX+VRhf++dn1adyC/PZHP6XI5AfKnZ4n0FW+v5omxwdHVpd4xq2ZijaHEcmlQrhBY79ZWQ==", "requires": { "backo2": "^1.0.2", "eventemitter3": "^3.1.0", @@ -11123,7 +11710,7 @@ "ws": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha1-3/7xSGa46NyRM1glFNG++vlumA8=", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", "requires": { "async-limiter": "~1.0.0" } @@ -11159,36 +11746,66 @@ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" }, "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", "dev": true, "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" + "ajv": "^6.9.1", + "lodash": "^4.17.11", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" }, "dependencies": { "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.2.tgz", + "integrity": "sha512-4UFy0/LgDo7Oa/+wOAlj44tp9K78u38E5/359eSrqEp1Z5PdVfimCcs7SluXMP755RUQu6d2b4AvF0R1C9RZjg==", "dev": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true + }, + "string-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.0.0.tgz", + "integrity": "sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } } } }, @@ -11212,9 +11829,9 @@ "dev": true }, "tapable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", + "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==", "dev": true }, "tarn": { @@ -11238,14 +11855,14 @@ } }, "terser": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.11.0.tgz", - "integrity": "sha1-YHgok+H01niKzGljUfQGNtDjevA=", + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.16.1.tgz", + "integrity": "sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow==", "dev": true, "requires": { "commander": "~2.17.1", "source-map": "~0.6.1", - "source-map-support": "~0.5.6" + "source-map-support": "~0.5.9" }, "dependencies": { "source-map": { @@ -11257,9 +11874,9 @@ } }, "terser-webpack-plugin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.1.0.tgz", - "integrity": "sha1-z3wloe7iW/Eh9KWHu54ATj+A5Sg=", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz", + "integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==", "dev": true, "requires": { "cacache": "^11.0.2", @@ -11267,37 +11884,43 @@ "schema-utils": "^1.0.0", "serialize-javascript": "^1.4.0", "source-map": "^0.6.1", - "terser": "^3.8.1", + "terser": "^3.16.1", "webpack-sources": "^1.1.0", "worker-farm": "^1.5.2" }, "dependencies": { + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "dev": true + }, "cacache": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.1.tgz", - "integrity": "sha1-0J0l9sSsp6bTBdFBrjMmE6odUV8=", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", "dev": true, "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" } }, "find-cache-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", - "integrity": "sha1-TB+u1Z9FGEUw+51/oSOk0EqYRy0=", + "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", "dev": true, "requires": { "commondir": "^1.0.1", @@ -11308,16 +11931,36 @@ "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { "locate-path": "^3.0.0" } }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "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" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { "p-locate": "^3.0.0", @@ -11325,19 +11968,18 @@ } }, "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "yallist": "^3.0.2" } }, "mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha1-6goykfl+C16HdrNj1fChLZTGcCI=", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", "dev": true, "requires": { "concat-stream": "^1.5.0", @@ -11353,9 +11995,9 @@ } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha1-5iTtVO6MRgp3izyfNnBJb/ileuw=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -11364,7 +12006,7 @@ "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { "p-limit": "^2.0.0" @@ -11373,13 +12015,13 @@ "p-try": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha1-hQgLuHxkaI+keZb+j3376CEXYLE=", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", "dev": true }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM=", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, "requires": { "find-up": "^3.0.0" @@ -11388,7 +12030,7 @@ "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -11398,7 +12040,7 @@ "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { "ajv": "^6.1.0", @@ -11409,17 +12051,23 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha1-KjxBso3UW2K2Nnbst0ABJlrp7dg=", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "dev": true, "requires": { "figgy-pudding": "^3.5.1" } + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true } } }, @@ -11458,7 +12106,7 @@ "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0=", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" @@ -11481,7 +12129,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" } @@ -11505,7 +12153,7 @@ "timers-browserify": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha1-HSjj0qrfHVpZlsTp+VYBzQU0gK4=", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", "dev": true, "requires": { "setimmediate": "^1.0.4" @@ -11598,7 +12246,7 @@ "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha1-/jZfX3XsntTlaCXgu3bSSrdK+Ds=", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", "dev": true, "requires": { "nopt": "~1.0.10" @@ -11616,9 +12264,9 @@ "dev": true }, "ts-loader": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.3.1.tgz", - "integrity": "sha1-cGFMjsQ1SpyLicn5eyvst6mKOYA=", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.3.3.tgz", + "integrity": "sha512-KwF1SplmOJepnoZ4eRIloH/zXL195F51skt7reEsS6jvDqzgc/YSbz9b8E07GxIUwLXdcD4ssrJu6v8CwaTafA==", "dev": true, "requires": { "chalk": "^2.3.0", @@ -11628,15 +12276,58 @@ "semver": "^5.0.1" } }, + "ts-node": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.0.2.tgz", + "integrity": "sha512-MosTrinKmaAcWgO8tqMjMJB22h+sp3Rd1i4fdoWY4mhBDekOwIAKI/bzmRi7IcbCmjquccYg2gcF6NBkLgr0Tw==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "^3.0.0" + } + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha1-1+TdeSRdhUKMTX5IIqeZF5VMooY=", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, + "tslint": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.13.0.tgz", + "integrity": "sha512-ECOOQRxXCYnUUePG5h/+Z1Zouobk3KFpIHA9aKBB/nnMxs97S1JJPDGt5J4cGm1y9U9VmVlfboOxA8n1kSNzGw==", + "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.27.2" + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "tty-browserify": { "version": "0.0.0", - "resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, @@ -11652,7 +12343,7 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw=", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, "type-is": { @@ -11670,9 +12361,9 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "typescript": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", - "integrity": "sha1-/oEBxGqhI/g1NSPr3PVzDCrkk+U=", + "version": "3.3.3333", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.3333.tgz", + "integrity": "sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw==", "dev": true }, "typical": { @@ -11727,7 +12418,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" @@ -11761,13 +12452,13 @@ "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha1-JhmADEyCWADv3YNDr33Zkzy+KBg=", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", "dev": true }, "unicode-match-property-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw=", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", "dev": true, "requires": { "unicode-canonical-property-names-ecmascript": "^1.0.4", @@ -11777,13 +12468,13 @@ "unicode-match-property-value-ecmascript": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz", - "integrity": "sha1-nx3HaSbWzPRSMQVk/YNKzgWWY9Q=", + "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==", "dev": true }, "unicode-property-aliases-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", - "integrity": "sha1-WlM/MbQxfqdvF9gH+g0RZUYRHdA=", + "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==", "dev": true }, "union-value": { @@ -11893,13 +12584,13 @@ "upath": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha1-NSVll+RqWB20eT0M5H+prr/J+r0=", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", "dev": true }, "update-notifier": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", - "integrity": "sha1-0HRFk+E/Fh5AassdlAi3LK0Ir/Y=", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", "dev": true, "requires": { "boxen": "^1.2.1", @@ -11929,6 +12620,15 @@ "upper-case": "^1.1.1" } }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -11953,33 +12653,19 @@ } }, "url-loader": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-0.6.2.tgz", - "integrity": "sha512-h3qf9TNn53BpuXTTcpC+UehiRrl0Cv45Yr/xWayApjw6G8Bg2dGke7rIwDQ39piciWCWrC+WiqLjOh3SUp9n0Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", + "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", "requires": { - "loader-utils": "^1.0.2", - "mime": "^1.4.1", - "schema-utils": "^0.3.0" + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" }, "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "schema-utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", - "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "requires": { - "ajv": "^5.0.0" - } + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==" } } }, @@ -12016,7 +12702,7 @@ "util.promisify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", "requires": { "define-properties": "^1.1.2", "object.getownpropertydescriptors": "^2.0.3" @@ -12039,17 +12725,17 @@ "dev": true }, "v8flags": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz", - "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", + "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==", "requires": { "homedir-polyfill": "^1.0.1" } }, "validate-npm-package-license": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { "spdx-correct": "^3.0.0", @@ -12096,7 +12782,7 @@ }, "vm-browserify": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", "dev": true, "requires": { @@ -12125,7 +12811,7 @@ "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha1-S8EsLr6KonenHx0/FNaFx7RGzQA=", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", "dev": true, "requires": { "chokidar": "^2.0.2", @@ -12134,17 +12820,17 @@ } }, "webpack": { - "version": "4.27.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.27.1.tgz", - "integrity": "sha1-Xy4ttEbSJmN2+hXX0id6GpwuErs=", + "version": "4.29.5", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.5.tgz", + "integrity": "sha512-DuWlYUT982c7XVHodrLO9quFbNpVq5FNxLrMUfYUTlgKW0+yPimynYf1kttSQpEneAL1FH3P3OLNgkyImx8qIQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-module-context": "1.7.11", - "@webassemblyjs/wasm-edit": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11", - "acorn": "^5.6.2", - "acorn-dynamic-import": "^3.0.0", + "@webassemblyjs/ast": "1.8.3", + "@webassemblyjs/helper-module-context": "1.8.3", + "@webassemblyjs/wasm-edit": "1.8.3", + "@webassemblyjs/wasm-parser": "1.8.3", + "acorn": "^6.0.5", + "acorn-dynamic-import": "^4.0.0", "ajv": "^6.1.0", "ajv-keywords": "^3.1.0", "chrome-trace-event": "^1.0.0", @@ -12158,19 +12844,13 @@ "mkdirp": "~0.5.0", "neo-async": "^2.5.0", "node-libs-browser": "^2.0.0", - "schema-utils": "^0.4.4", + "schema-utils": "^1.0.0", "tapable": "^1.1.0", "terser-webpack-plugin": "^1.1.0", "watchpack": "^1.5.0", "webpack-sources": "^1.3.0" }, "dependencies": { - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, "eslint-scope": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", @@ -12181,30 +12861,36 @@ "estraverse": "^4.1.1" } }, - "tapable": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", - "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==", - "dev": true + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } } } }, "webpack-cli": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.1.2.tgz", - "integrity": "sha512-Cnqo7CeqeSvC6PTdts+dywNi5CRlIPbLx1AoUPK2T6vC1YAugMG3IOoO9DmEscd+Dghw7uRlnzV1KwOe5IrtgQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.2.3.tgz", + "integrity": "sha512-Ik3SjV6uJtWIAN5jp5ZuBMWEAaP5E4V78XJ2nI+paFPh8v4HPSwo/myN0r29Xc/6ZKnd2IdrAlpSgNOu2CDQ6Q==", "dev": true, "requires": { "chalk": "^2.4.1", "cross-spawn": "^6.0.5", "enhanced-resolve": "^4.1.0", - "global-modules-path": "^2.3.0", + "findup-sync": "^2.0.0", + "global-modules": "^1.0.0", "import-local": "^2.0.0", "interpret": "^1.1.0", "loader-utils": "^1.1.0", "supports-color": "^5.5.0", "v8-compile-cache": "^2.0.2", - "yargs": "^12.0.2" + "yargs": "^12.0.4" }, "dependencies": { "cliui": { @@ -12231,23 +12917,14 @@ "which": "^1.2.9" } }, - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", - "dev": true, - "requires": { - "xregexp": "4.0.0" - } - }, "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { "cross-spawn": "^6.0.0", - "get-stream": "^3.0.0", + "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", @@ -12264,6 +12941,15 @@ "locate-path": "^3.0.0" } }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", @@ -12290,31 +12976,31 @@ } }, "mem": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", - "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz", + "integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==", "dev": true, "requires": { "map-age-cleaner": "^0.1.1", "mimic-fn": "^1.0.0", - "p-is-promise": "^1.1.0" + "p-is-promise": "^2.0.0" } }, "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.10.0", + "execa": "^1.0.0", "lcid": "^2.0.0", "mem": "^4.0.0" } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -12335,6 +13021,16 @@ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -12345,13 +13041,13 @@ } }, "yargs": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", - "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", "dev": true, "requires": { "cliui": "^4.0.0", - "decamelize": "^2.0.0", + "decamelize": "^1.2.0", "find-up": "^3.0.0", "get-caller-file": "^1.0.1", "os-locale": "^3.0.0", @@ -12361,7 +13057,7 @@ "string-width": "^2.0.0", "which-module": "^2.0.0", "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^10.1.0" + "yargs-parser": "^11.1.1" } } } @@ -12377,6 +13073,22 @@ "pify": "^3.0.0" } }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, "webpack-node-externals": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-1.7.2.tgz", @@ -12386,7 +13098,7 @@ "webpack-sources": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha1-KijcufH0X+lg2PFJMlK17mUw+oU=", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", "dev": true, "requires": { "source-list-map": "^2.0.0", @@ -12420,10 +13132,19 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, "widest-line": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha1-dDh2RzDsfvQ4HOTfgvuYpTFCo/w=", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", "dev": true, "requires": { "string-width": "^2.1.1" @@ -12469,7 +13190,7 @@ "worker-farm": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", - "integrity": "sha1-rsxAWXb6talVJhgIRvDboojzpKA=", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", "dev": true, "requires": { "errno": "~0.1.7" @@ -12522,18 +13243,18 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", "dev": true, "requires": { "mkdirp": "^0.5.1" } }, "write-file-atomic": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", - "integrity": "sha1-H/YVdcLipOjlENb6TiQ8zhg5mas=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.2.tgz", + "integrity": "sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g==", "dev": true, "requires": { "graceful-fs": "^4.1.11", @@ -12542,9 +13263,9 @@ } }, "ws": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.2.tgz", - "integrity": "sha1-PMdGLph5LwrGeUJBSJA97TucOtg=", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", "requires": { "async-limiter": "~1.0.0" } @@ -12561,12 +13282,6 @@ "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=", "dev": true }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true - }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", @@ -12580,7 +13295,8 @@ "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true }, "yargs": { "version": "3.10.0", @@ -12601,23 +13317,209 @@ } }, "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "dev": true + } + } + }, + "yargs-unparser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", + "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "flat": "^4.1.0", + "lodash": "^4.17.11", + "yargs": "^12.0.5" + }, + "dependencies": { + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz", + "integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^2.0.0" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + } } }, + "yn": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.0.0.tgz", + "integrity": "sha512-+Wo/p5VRfxUgBUGy2j/6KX2mj9AYJWOHuhMjMcbBFc3y54o9/4buK1ksBvuiK01C3kby8DH9lSmJdSxw+4G/2Q==", + "dev": true + }, "zen-observable": { "version": "0.8.9", "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.9.tgz", "integrity": "sha512-Y9kPzjGvIZ5jchSlqlCpBW3I82zBBL4z+ulXDRVA1NwsKzjt5kwAi+gOYIy0htNkfuehGZZtP5mRXHRV6TjDWw==" }, "zen-observable-ts": { - "version": "0.8.9", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.9.tgz", - "integrity": "sha512-KJz2O8FxbAdAU5CSc8qZ1K2WYEJb1HxS6XDRF+hOJ1rOYcg6eTMmS9xYHCXzqZZzKw6BbXWyF4UpwSsBQnHJeA==", + "version": "0.8.13", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.13.tgz", + "integrity": "sha512-WDb8SM0tHCb6c0l1k60qXWlm1ok3zN9U4VkLdnBKQwIYwUoB9psH7LIFgR+JVCCMmBxUgOjskIid8/N02k/2Bg==", "requires": { "zen-observable": "^0.8.0" } diff --git a/package.json b/package.json index d661aade5ee090f97f9d49955f5ffe0d5e29f3dc..79f87cb4d457fdf50473d7082131ee8e04011618 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,12 @@ "start": "nodemon --watch build ./build/bundle.js", "start_prod": "node ./build/bundle.js", "doc": "jsdoc --configure jsdoc_config.json", - "lint": "eslint --ext .js --ext .ts src/", - "test": "mocha --exit" + "lint": "echo 'Ambiguous! Use `npm run jslint` (lint .js files using ESLint) or `npm run tslint` (lint .ts and .js files using TSLint) instead'", + "eslint": "eslint --ext .js src/ db/", + "tslint": "tslint --project tsconfig.json", + "tsfix": "tslint --project tsconfig.json --fix", + "tsc": "tsc --project tsconfig.json", + "test": "mocha --require mocha-graphql-register --require ts-node/register test/**/*.test.ts --timeout 20000" }, "repository": { "type": "git", @@ -19,73 +23,79 @@ "author": "Binet Réseau", "license": "ISC", "dependencies": { - "apollo-server-express": "^2.3.1", + "apollo-server-express": "^2.4.8", "body-parser": "^1.18.3", "colors": "^1.3.3", "connect-ensure-login": "^0.1.1", "connect-flash": "^0.1.1", - "cookie-parser": "^1.4.3", - "copy-webpack-plugin": "^4.6.0", + "cookie-parser": "^1.4.4", + "copy-webpack-plugin": "^5.0.0", "cors": "^2.8.5", "dotenv": "^6.2.0", "express": "^4.16.4", "express-jwt": "^5.3.1", "express-session": "^1.15.6", - "file-loader": "^1.1.11", + "file-loader": "^3.0.1", "fs": "0.0.1-security", - "fuse.js": "^3.3.0", - "graphql": "^14.0.2", - "graphql-tools": "^3.1.1", + "fuse.js": "^3.4.2", + "graphql": "^14.1.1", + "graphql-tools": "^4.0.4", "graphql-voyager": "^1.0.0-rc.26", - "jsonwebtoken": "^8.4.0", - "knex": "^0.15.2", + "jsonwebtoken": "^8.5.0", + "knex": "^0.16.3", "ldap-escape": "^1.1.5", "ldapjs": "^1.0.2", "lodash": "^4.17.11", "morgan": "^1.9.1", "package-lock": "^1.0.0", "passport": "^0.4.0", - "passport-ldapauth": "^2.1.1", + "passport-ldapauth": "^2.1.2", "path": "^0.12.7", - "pg": "^7.7.1", + "pg": "^7.8.1", "pug": "^2.0.3", - "react": "^16.6.3", - "react-dom": "^16.6.3", + "react": "^16.8.3", + "react-dom": "^16.8.3", "serve-favicon": "^2.5.0", - "url-loader": "^0.6.2" + "url-loader": "^1.1.2" }, "devDependencies": { - "@babel/cli": "^7.2.0", - "@babel/core": "^7.2.0", - "@babel/plugin-proposal-class-properties": "^7.2.1", - "@babel/plugin-proposal-object-rest-spread": "^7.2.0", - "@babel/preset-env": "^7.2.0", - "@babel/preset-typescript": "^7.1.0", + "@babel/cli": "^7.2.3", + "@babel/core": "^7.3.4", + "@babel/plugin-proposal-class-properties": "^7.3.4", + "@babel/plugin-proposal-object-rest-spread": "^7.3.4", + "@babel/preset-env": "^7.3.4", + "@babel/preset-typescript": "^7.3.3", + "@types/chai": "^4.1.7", "@types/connect-ensure-login": "^0.1.4", "@types/connect-flash": "0.0.34", - "@types/graphql": "^0.13.4", - "@types/knex": "^0.14.26", - "@types/node": "^10.12.14", - "@types/passport": "^0.4.7", - "babel-eslint": "^8.2.6", + "@types/graphql": "^14.0.7", + "@types/knex": "^0.15.2", + "@types/mocha": "^5.2.6", + "@types/node": "^11.9.5", + "@types/passport": "^1.0.0", + "apollo-server-testing": "^2.4.8", + "babel-eslint": "^10.0.1", "chai": "^4.2.0", - "eslint": "^4.19.1", - "eslint-config-standard": "^11.0.0", - "eslint-loader": "^2.1.1", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-node": "^6.0.1", - "eslint-plugin-promise": "^3.8.0", - "eslint-plugin-standard": "^3.1.0", + "eslint": "^5.14.1", + "eslint-config-standard": "^12.0.0", + "eslint-loader": "^2.1.2", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-node": "^8.0.1", + "eslint-plugin-promise": "^4.0.1", + "eslint-plugin-standard": "^4.0.0", "graphql-request": "^1.8.2", "jsdoc": "^3.5.5", "jsdoc-babel": "^0.5.0", "jsdoc-to-markdown": "^4.0.1", - "nodemon": "^1.18.8", - "mocha": "^5.2.0", - "ts-loader": "^5.3.1", - "typescript": "^3.2.2", - "webpack": "^4.27.1", - "webpack-cli": "^3.1.2", + "mocha": "^6.0.2", + "mocha-graphql-register": "^1.0.0", + "nodemon": "^1.18.10", + "ts-loader": "^5.3.3", + "ts-node": "^8.0.2", + "tslint": "^5.13.0", + "typescript": "^3.3.3333", + "webpack": "^4.29.5", + "webpack-cli": "^3.2.3", "webpack-graphql-loader": "^1.0.0", "webpack-node-externals": "^1.7.2" } diff --git a/src/adminview/admin_router.ts b/src/adminview/admin_router.ts index a7c7ec837767f6d92232018b2d1a6bae29b3a541..c8b582ff8560365b8b6561a251062e9757ef773a 100644 --- a/src/adminview/admin_router.ts +++ b/src/adminview/admin_router.ts @@ -32,15 +32,23 @@ import flash from 'connect-flash'; // packages pour l'API REST et pour GraphQL Voyager import knex from '../../db/knex_router'; import { express as graphqlVoyager } from 'graphql-voyager/middleware'; +//loads environment variables from (hidden) .env file +import dotenv from 'dotenv'; +dotenv.config(); -let port = process.env.PORT || 3000; +let port = process.env.PORT; const whitelist = [ - "magi.karp", - "mew.two", - "lippou.tou", + "gregoire.grzeckowicz", + "anatole.romon", + "hadrien.renaud", + "wilson.jallet", + "quentin.chevalier", "guillaume.wang", - "oliver.facklam" + "oliver.facklam", + "octave.hazard", + "guilhem.roy", + "elia.azar" ]; /** * @function ensureIsAdmin @@ -54,6 +62,8 @@ function ensureIsAdmin(returnTo) { // lookup req.user against whitelist of admin users if (req.user && whitelist.includes(req.user.uid)) { console.log("is an admin"); + // go on + next(); } else { console.log("is NOT an admin"); req.flash('error: not an admin'); @@ -61,7 +71,7 @@ function ensureIsAdmin(returnTo) { res.redirect(returnTo); } // go on - next(); + //next(); }; } @@ -236,7 +246,8 @@ router.use((req, res, next) => { */ router.use((err, req, res, next) => { console.log("adminview: Entering error handler"); - console.log(err.message); + console.log(err); + //console.log(err.message); //res.status(err.status || 500); res.render('error', { diff --git a/src/app.ts b/src/app.ts index 3f940daf2604571a868fd4bd9bf418bf95faf85c..be35769c470f7c49083d0527be18e7cee0f74d1e 100644 --- a/src/app.ts +++ b/src/app.ts @@ -28,7 +28,9 @@ import morgan from 'morgan'; import path from 'path'; // config des paramètres de connexion au LDAP import { ldapConfig, credentialsLdapConfig } from './ldap/internal/config'; - +//loads environment variables from (hidden) .env file +import dotenv from 'dotenv'; +dotenv.config(); /** * @desc Création de l'application Express et setup de middlewares basiques @@ -45,7 +47,7 @@ app.disable('x-powered-by'); // use morgan (HTTP request logger middleware) app.use(morgan('dev')); -const FRONTEND_SERVER_URL = process.env.FRONTEND_SERVER_URL || 'http://localhost:8888'; +const FRONTEND_SERVER_URL = process.env.FRONTEND_SERVER_URL; // Options de configuration pour le _middleware_ `cors`. // CORS = Cross Origin Resource Sharing const corsOptions = { @@ -180,14 +182,14 @@ app.post('/login', (req, res, next) => { // Define GraphQL request's context object, through a callback, with authorization. // See: https://www.apollographql.com/docs/apollo-server/features/authentication.html import { Context } from './graphql/typeDefs/queries'; -import { AuthorisationModel } from './graphql/connectors/authorisationModel'; -import { UserModel } from './graphql/connectors/userModel'; -import { GroupModel } from './graphql/connectors/groupModel'; -import { MessageModel } from './graphql/connectors/messageModel'; -import { RequestModel } from './graphql/connectors/requestModel'; +import { AuthorizationModel } from './graphql/models/authorization'; +import { UserModel } from './graphql/models/userModel'; +import { GroupModel } from './graphql/models/groupModel'; +import { MessageModel } from './graphql/models/messageModel'; +import { RequestModel } from './graphql/models/requestModel'; const context = async ({ req }): Promise<Context> => { // set a special uid for non-authenticated requests - // /!\ FOR DEVELOPMENT ONLY: use the one in the ldap config .json file + // /!\ FOR DEVELOPMENT ONLY: use the one in the ldap_credentials.json file (imported by config.ts) // for production, replace with a "publicUser" or "notLoggedInUser" or something. let uid = credentialsLdapConfig.dn.split("=")[1].split(",")[0]; @@ -206,18 +208,20 @@ const context = async ({ req }): Promise<Context> => { console.log(err); } } - - return { + console.log(`Constructing context with uid = ${uid}`); + let c = { request: req, user: { uid: uid }, models: { - auth: await AuthorisationModel.create(uid), + auth: await AuthorizationModel.create(uid), user: new UserModel(uid), group: new GroupModel(uid), message: new MessageModel(uid), request: new RequestModel(uid) } }; + console.log("finished constructing context"); + return c; }; const server = new ApolloServer({ @@ -226,7 +230,8 @@ const server = new ApolloServer({ playground: { settings: { "editor.theme": "dark", - "editor.cursorShape": 'line' + "editor.cursorShape": 'line', + "request.credentials": 'include' } } }); diff --git a/src/config_passport.js b/src/config_passport.js index 33a86aac56a7afc9dd535b33959f27e80600fade..761ef5a45a273e9f59694d05a2e696a459124100 100644 --- a/src/config_passport.js +++ b/src/config_passport.js @@ -1,7 +1,7 @@ /** * @file Configuration de passport pour utiliser l'authentification LDAP * @author kadabra - * + * @desc * http://toon.io/on-passportjs-specific-use-cases/#howtosplituppassportjsconfigurationbetweenmultiplefiles * * On utilise passport avec la strategie 'ldapauth' pour transmettre une tentative d'authentification au LDAP. @@ -34,16 +34,19 @@ import passport from 'passport'; import LdapStrategy from 'passport-ldapauth'; import { ldapConfig } from './ldap/internal/config'; +console.log("Configuring passportjs... " + ldapConfig.server + " " + ldapConfig.dn.user); + // specifies options for 'ldapauth' strategy, to customize the behaviour of subsequent passport.authenticate('ldapauth') calls passport.use(new LdapStrategy({ server: { url: ldapConfig.server, //bindDn: '.............', //bindCredentials: '..........', - // searchBase: ldapConfig.searchBase, TODO: this cannot be left empty. - // searchFilter: ldapConfig.searchFilter, TODO: this cannot be left empty. - //searchAttributes: ['givenName', 'sn'], + searchBase: ldapConfig.dn.user, // this field cannot be left empty. + searchFilter: '(uid={{username}})', // this field cannot be left empty. + searchAttributes: ['uid', 'urlPhoto'], // only fetch the uid, no need for any other field //tlsOptions: '..........', + //https://www.npmjs.com/package/passport-ldapauth for more }, //usernameField: 'username', // Field name where the username is found, defaults to username //passwordField: 'password', // Field name where the password is found, defaults to password @@ -85,6 +88,6 @@ passport.serializeUser(function (user, done) { * > This user object is attached to the request as req.user making it accessible in our request handling. (available in all subsequent middleware) */ passport.deserializeUser(function (userUid, done) { - // console.log(`passport.deserializeUser(): deserializing user ${userUid}`); // DEBUG + console.log(`passport.deserializeUser(): deserializing user ${userUid}`); // DEBUG done(null, { uid: userUid }); }); diff --git a/src/graphql/connectors/authorisationModel.ts b/src/graphql/models/authorization.ts similarity index 72% rename from src/graphql/connectors/authorisationModel.ts rename to src/graphql/models/authorization.ts index 010ba6ead4dce52d5dade249162d9715bcbd8cdd..97a18d7fc2e0cca908d445eac4191fc6a88301f4 100644 --- a/src/graphql/connectors/authorisationModel.ts +++ b/src/graphql/models/authorization.ts @@ -8,21 +8,20 @@ import { Tools, GroupSet, GroupCollection } from "./tools"; import { User as UT } from '../../ldap/export/user' /* - * There are 7 levels of authorisation + * There are 6 levels of authorization * none : doesn't know the group / the user exists * connectedOrOnplatal : knows the group exists, can use TOL * viewer : can see the group * member : part of the group * speaker : allowed to speak for the group * admin : admin of the group - * supervisor : allowed to take control of the group */ -export class AuthorisationModel { +export class AuthorizationModel { /** * @memberof GraphQL - * @class AuthorisationModel + * @class AuthorizationModel * @summary Autorisation des utilisateurs. * @classdesc Cette classe contient les méthodes d'autorisation de l'utilisateur dans le 'context'. * @arg {string} uid - L'identifiant de l'utilisateur. @@ -33,19 +32,20 @@ export class AuthorisationModel { /** * @memberof GraphQL - * @summary Fonction qui crée une nouvelle instance de AuthorisationModel et charge les données + * @summary Fonction qui crée une nouvelle instance de AuthorizationModel et charge les données * @arg {string} uid - Identifiant de l'utilisateur. - * @returns {Promise(AuthorisationModel)} Renvoie un nouveau AuthorisationModel avec cet utilisateur + * @returns {Promise(AuthorizationModel)} Renvoie un nouveau AuthorizationModel avec cet utilisateur * @async * @static */ - static async create(uid: string): Promise<AuthorisationModel> { - let model = new AuthorisationModel(uid); - + static async create(uid: string): Promise<AuthorizationModel> { + let model = new AuthorizationModel(uid); + console.log("constructing AuthorizationModel..."); if(model.isAuthenticated()) { + console.log("model is authenticated. fetching data..."); await model.fetchData(); } - + console.log("finished constructing AuthorizationModel"); return model; } @@ -54,29 +54,31 @@ export class AuthorisationModel { protected memberOf: GroupCollection; protected speakerOf: GroupCollection; protected adminOf: GroupCollection; - protected supervisorOf: GroupCollection; static PUBLICUSER = "public_user"; static ONPLATALUSER = "public_onplatal_user"; /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function fetchData * @summary Fonction qui recupere toutes les données pour populer les champs a partir de l'uid. * @async */ async fetchData(): Promise<void> { + console.log("calling UT.peek from ldap connector (User Tool)...") let data = await UT.peek(this.uid); + console.log("UT.peek returned with data:"); + //console.log(data); - this.viewerOf = await Tools.viewerOf(data); this.memberOf = await Tools.memberOf(data); - this.speakerOf = await Tools.viewerOf(data); + this.speakerOf = await Tools.speakerOf(data); this.adminOf = await Tools.adminOf(data); - this.supervisorOf = await Tools.supervisorOf(data); + this.viewerOf = await Tools.viewerOf(this.memberOf); + //console.log(this.viewerOf); } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function getUid * @summary Fonction qui renvoit l'identifiant de l'utilisateur * @return {string} Renvoie l'uid de l'utilisateur du 'context' @@ -86,27 +88,28 @@ export class AuthorisationModel { } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function isConnectedOrOnplatal * @summary Fonction qui renvoit si l'utilisateur est connecté ou on-platal * @return {boolean} Renvoie true si l'utilisateur est connecté ou on-platal */ isConnectedOrOnplatal(): boolean { - return (this.uid != AuthorisationModel.PUBLICUSER); + return (this.uid != AuthorizationModel.PUBLICUSER); } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function isAuthenticated * @summary Fonction qui renvoit si l'utilisateur est authentifié * @return {boolean} Renvoie true si l'utilisateur est authentifié */ isAuthenticated(): boolean { - return (this.uid != AuthorisationModel.PUBLICUSER && this.uid != AuthorisationModel.ONPLATALUSER); + console.log("running model.isAuthenticated..."); + return (this.uid != AuthorizationModel.PUBLICUSER && this.uid != AuthorizationModel.ONPLATALUSER); } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function isViewer * @summary Fonction qui renvoit si l'utilisateur est viewer du groupe. * @arg {string} gid - Identifiant du groupe. @@ -122,7 +125,7 @@ export class AuthorisationModel { } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function groupsViewer * @summary Fonction qui renvoit les groupes dont l'utilisateur est viewer. * @return {GroupCollection} Renvoie la collection de groupes dont l'utilisateur est viewer. @@ -136,7 +139,7 @@ export class AuthorisationModel { } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function isMember * @summary Fonction qui renvoit si l'utilisateur est membre du groupe. * @arg {string} gid - Identifiant du groupe. @@ -152,7 +155,7 @@ export class AuthorisationModel { } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function isMemberOr * @summary Fonction qui renvoit si l'utilisateur est membre d'au moins un de ces groupes. * @arg {GroupSet} groups - Ensemble de groupes. @@ -173,7 +176,7 @@ export class AuthorisationModel { } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function groupsMember * @summary Fonction qui renvoit les groupes dont l'utilisateur est member. * @return {GroupCollection} Renvoie la collection de groupes dont l'utilisateur est member. @@ -187,7 +190,7 @@ export class AuthorisationModel { } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function isSpeaker * @summary Fonction qui renvoit si l'utilisateur est speaker du groupe. * @arg {string} gid - Identifiant du groupe. @@ -203,7 +206,7 @@ export class AuthorisationModel { } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function groupsSpeaker * @summary Fonction qui renvoit les groupes dont l'utilisateur est speaker. * @return {GroupCollection} Renvoie la collection de groupes dont l'utilisateur est speaker. @@ -217,7 +220,7 @@ export class AuthorisationModel { } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function isAdmin * @summary Fonction qui renvoit si l'utilisateur est admin du groupe. * @arg {string} gid - Identifiant du groupe. @@ -227,18 +230,13 @@ export class AuthorisationModel { //ensure uid is valid !!!!!!!! if (this.isAuthenticated()) { let groups = this.adminOf; - let is_admin = groups.simpleGroups.has(gid) || groups.metaGroups.has(gid); - - //TODO : Vérifier s'il a pris les droits d'admin en étant supervisor - let took_admin_rights = false; - - return (is_admin || took_admin_rights); + return (groups.simpleGroups.has(gid) || groups.metaGroups.has(gid)); } return false; } /** - * @memberof GraphQL.AuthorisationModel# + * @memberof GraphQL.AuthorizationModel# * @function groupsAdmin * @summary Fonction qui renvoit les groupes dont l'utilisateur est admin. * @return {GroupCollection} Renvoie la collection de groupes dont l'utilisateur est admin. @@ -251,34 +249,4 @@ export class AuthorisationModel { return null; } - /** - * @memberof GraphQL.AuthorisationModel# - * @function isSupervisor - * @summary Fonction qui renvoit si l'utilisateur est supervisor du groupe. - * @arg {string} gid - Identifiant du groupe. - * @return {boolean} Renvoie true si l'utilisateur est supervisor du groupe. - */ - isSupervisor(gid: string): boolean { - //ensure uid is valid !!!!!!!! - if (this.isAuthenticated()) { - let groups = this.supervisorOf; - return (groups.simpleGroups.has(gid) || groups.metaGroups.has(gid)); - } - return false; - } - - /** - * @memberof GraphQL.AuthorisationModel# - * @function groupsSupervisor - * @summary Fonction qui renvoit les groupes dont l'utilisateur est supervisor. - * @return {GroupCollection} Renvoie la collection de groupes dont l'utilisateur est supervisor. - */ - groupsSupervisor(): GroupCollection { - //ensure uid is valid !!!!!!!! - if (this.isAuthenticated()) { - return this.supervisorOf; - } - return null; - } - } \ No newline at end of file diff --git a/src/graphql/connectors/groupModel.ts b/src/graphql/models/groupModel.ts similarity index 90% rename from src/graphql/connectors/groupModel.ts rename to src/graphql/models/groupModel.ts index cccc616c1336a140905063a4dbd0157e8444a76f..fe5467bffbbb067e58103968ab70956167c6221b 100644 --- a/src/graphql/connectors/groupModel.ts +++ b/src/graphql/models/groupModel.ts @@ -4,9 +4,9 @@ * @memberof GraphQL */ -import { Group, SimpleGroup, MetaGroup } from "../resolvers/groups"; -import { Request } from "../resolvers/requests"; -import { User } from "../resolvers/users"; +import { Group, SimpleGroup, MetaGroup } from "../object_resolvers/groups"; +import { Request } from "../object_resolvers/requests"; +import { User } from "../object_resolvers/users"; import knex from "../../../db/knex_router" import { GroupCollection, GroupSet, Tools } from "./tools"; import { createSubgroupArgs, editGroupArgs } from "../typeDefs/queries"; @@ -146,6 +146,7 @@ export class GroupModel { * @rights viewer du groupe */ async likeGroup(gid: string): Promise<boolean> { + // Pour l'instant, ce n'est pas a implémenter... throw "Not implemented"; } @@ -159,6 +160,7 @@ export class GroupModel { * @rights viewer du groupe */ async unlikeGroup(gid: string): Promise<boolean> { + // Pour l'instant, ce n'est pas a implémenter... throw "Not implemented"; } @@ -323,6 +325,34 @@ export class GroupModel { throw "Not implemented"; } + /** + * @memberof GraphQL.GroupModel# + * @function addVisibilityEdge + * @summary Fonction pour ajouter une arete de visibilité. + * @arg {string} forGroup - Le groupe a rendre visible. + * @arg {string} visibleBy - Le groupe qui pourra voir. + * @return {Promise(boolean)} Renvoie true si modification réussie. + * @async + * @rights admin du groupe 'forGroup' + */ + async addVisibilityEdge(forGroup: string, visibleBy: string): Promise<boolean> { + throw "Not implemented"; + } + + /** + * @memberof GraphQL.GroupModel# + * @function removeVisibilityEdge + * @summary Fonction pour retirer une arete de visibilité. + * @arg {string} forGroup - Le groupe a rendre invisible. + * @arg {string} visibleBy - Le groupe qui ne pourra plus voir. + * @return {Promise(boolean)} Renvoie true si modification réussie. + * @async + * @rights admin du groupe 'forGroup' + */ + async removeVisibilityEdge(forGroup: string, visibleBy: string): Promise<boolean> { + throw "Not implemented"; + } + /** * @memberof GraphQL.GroupModel# * @function removeUser diff --git a/src/graphql/connectors/messageModel.ts b/src/graphql/models/messageModel.ts similarity index 94% rename from src/graphql/connectors/messageModel.ts rename to src/graphql/models/messageModel.ts index bfb9070ba7931ac8b75414461dd260d1fa2b9f74..cde6f59b54b3d6e671168675bd08614e338b0bc5 100644 --- a/src/graphql/connectors/messageModel.ts +++ b/src/graphql/models/messageModel.ts @@ -4,7 +4,7 @@ * @memberof GraphQL */ -import { Announcement, Event, PrivatePost, Question, Answer, Message } from "../resolvers/messages"; +import { Announcement, Event, PrivatePost, Question, Answer, Message } from "../object_resolvers/messages"; import knex from "../../../db/knex_router" import { GroupCollection, GroupSet } from "./tools"; @@ -189,6 +189,34 @@ export class MessageModel { throw "Not implemented"; } + /** + * @memberof GraphQL.MessageModel# + * @function groupParticipate + * @summary Fonction pour participer a un evenement. + * @arg {string} gid - Identifiant du groupe. + * @arg {number} forEvent - Identifiant de l'évenement. + * @return {Promise(boolean)} Renvoie true si modification réussie + * @async + * @rights member d'un groupe author ou recipient + */ + async groupParticipate(gid: string, forEvent: number): Promise<boolean> { + throw "Not implemented"; + } + + /** + * @memberof GraphQL.MessageModel# + * @function groupUnparticipate + * @summary Fonction pour ne plus participer a un evenement. + * @arg {string} gid - Identifiant du groupe. + * @arg {number} forEvent - Identifiant de l'évenement. + * @return {Promise(boolean)} Renvoie true si modification réussie + * @async + * @rights member d'un groupe author ou recipient + */ + async groupUnparticipate(gid: string, forEvent: number): Promise<boolean> { + throw "Not implemented"; + } + /** * @memberof GraphQL.MessageModel# * @function createQuestion diff --git a/src/graphql/connectors/requestModel.ts b/src/graphql/models/requestModel.ts similarity index 95% rename from src/graphql/connectors/requestModel.ts rename to src/graphql/models/requestModel.ts index 5435ae0584afc1891826edd600b52a0801ec1d91..8a2568e5f2e6c9b0d0b8caeef4a095ef75a9322a 100644 --- a/src/graphql/connectors/requestModel.ts +++ b/src/graphql/models/requestModel.ts @@ -4,9 +4,9 @@ * @memberof GraphQL */ -import { Group, SimpleGroup, MetaGroup } from "../resolvers/groups"; -import { Request, UserJoinGroup, GroupJoinMetagroup, GroupCoauthorEvent } from "../resolvers/requests"; -import { User } from "../resolvers/users"; +import { Group, SimpleGroup, MetaGroup } from "../object_resolvers/groups"; +import { Request, UserJoinGroup, GroupJoinMetagroup, GroupCoauthorEvent } from "../object_resolvers/requests"; +import { User } from "../object_resolvers/users"; import knex from "../../../db/knex_router" import { GroupCollection, GroupSet } from "./tools"; import { createSubgroupArgs, editGroupArgs } from "../typeDefs/queries"; @@ -202,6 +202,7 @@ export class RequestModel { * @rights admin du groupe destinataire */ async acceptUserJoinRequest(req: UserJoinGroup, comment: string): Promise<boolean> { + //"comment" a envoyer par mail automatique throw "Not implemented"; } @@ -216,6 +217,7 @@ export class RequestModel { * @rights admin du groupe destinataire */ async refuseUserJoinRequest(req: UserJoinGroup, comment: string): Promise<boolean> { + //"comment" a envoyer par mail automatique throw "Not implemented"; } @@ -230,6 +232,7 @@ export class RequestModel { * @rights admin du groupe destinataire */ async acceptGroupJoinRequest(req: GroupJoinMetagroup, comment: string): Promise<boolean> { + //"comment" a envoyer par mail automatique throw "Not implemented"; } @@ -244,6 +247,7 @@ export class RequestModel { * @rights admin du groupe destinataire */ async refuseGroupJoinRequest(req: GroupJoinMetagroup, comment: string): Promise<boolean> { + //"comment" a envoyer par mail automatique throw "Not implemented"; } @@ -258,6 +262,7 @@ export class RequestModel { * @rights admin du groupe destinataire */ async acceptGroupCoauthorEventRequest(req: GroupCoauthorEvent, comment: string): Promise<boolean> { + //"comment" a envoyer par mail automatique throw "Not implemented"; /*let request = await knex('group_join_event').select().where('id', requestID); @@ -286,6 +291,7 @@ export class RequestModel { * @rights admin du groupe destinataire */ async refuseGroupCoauthorEventRequest(req: GroupCoauthorEvent, comment: string): Promise<boolean> { + //"comment" a envoyer par mail automatique throw "Not implemented"; /*await knex('group_join_event').where('id', requestID).del(); diff --git a/src/graphql/connectors/tools.ts b/src/graphql/models/tools.ts similarity index 65% rename from src/graphql/connectors/tools.ts rename to src/graphql/models/tools.ts index 1e835056952612ed6306727fa32b60f4d391746b..26d0f8b9357507a2abd7c3edc7b7c763c13ecb43 100644 --- a/src/graphql/connectors/tools.ts +++ b/src/graphql/models/tools.ts @@ -4,19 +4,18 @@ */ /** - * @file Fonctions génériques de recherche dans la BDD et le LDAP réutilisables dans l'authorisation et/ou dans les resolvers + * @file Fonctions génériques de recherche dans la BDD et le LDAP réutilisables dans l'authorization et/ou dans les resolvers * @author ofacklam * @memberof GraphQL */ import { userData } from '../../ldap/export/user' +import { groupData, Group as GT } from '../../ldap/export/group'; import knex from '../../../db/knex_router'; export class GroupSet extends Set<string> { addList(l: string[]) { - for(let elt of l) { - this.add(elt); - } + for(let elt of l) this.add(elt); } } export interface GroupCollection { @@ -70,7 +69,11 @@ export class Tools { * @async */ static async memberOfSimple(data: userData): Promise<GroupSet> { - return new GroupSet(data.groups); + //Do a DFS from data.members to find all parents + //return Tools.DFS(data.members, 'parent'); + + //No need to do DFS + return new GroupSet(data.members); } /** @@ -82,7 +85,7 @@ export class Tools { * @async */ static async speakerOfSimple(data: userData): Promise<GroupSet> { - throw "Not implemented"; + return new GroupSet(data.speakers); } /** @@ -94,7 +97,11 @@ export class Tools { * @async */ static async adminOfSimple(data: userData): Promise<GroupSet> { - return new GroupSet(data.groupsIsAdmin); + //Do a DFS from data.admins to find all children + //return Tools.DFS(data.admins, 'child'); + + //No need to do DFS + return new GroupSet(data.admins); } /** @@ -106,7 +113,7 @@ export class Tools { * @async */ static async metaGroupsOfGroups(groups: GroupSet): Promise<GroupSet> { - let metas = await knex.select('meta_group_gid').from('metagroup_memberships').whereIn('simple_group_gid', groups); + let metas = await knex.select('meta_group_gid').from('metagroup_memberships').whereIn('simple_group_gid', [...groups]); return new GroupSet(metas.map( elt => { return elt.meta_group_gid; })); @@ -134,9 +141,8 @@ export class Tools { * @async */ static async speakerOf(data: userData): Promise<GroupCollection> { - let speaker = await Tools.speakerOfSimple(data); - let admin = await Tools.adminOfSimple(data); - return { simpleGroups: speaker, metaGroups: await Tools.metaGroupsOfGroups(admin) }; + let simple = await Tools.speakerOfSimple(data); + return { simpleGroups: simple, metaGroups: await Tools.metaGroupsOfGroups(simple) }; } /** @@ -154,19 +160,36 @@ export class Tools { /** * @memberof GraphQL - * @summary Fonction qui fait un parcours en profondeur de l'arbre de racine `gid` et renvoie la liste de tous les noeuds. - * @arg {string} gid - Identifiant du groupe, supposé valide. - * @return {Promise(string[])} Renvoie une liste contenant le nom des groupes dans cet arbre. + * @summary Fonction qui fait un parcours en profondeur du graphe a partir de 'roots' et renvoie la liste de tous les noeuds dans la direction donnée. + * @arg {string[]} roots - Identifiants des groupes racine, supposés valides. + * @arg {'parent'|'child'} direction - Direction de la recherche. 'parent' cherche tous les noeuds ascendants. 'child' cherche tous les noeuds descendants. + * @return {Promise(GroupSet)} Renvoie un ensemble contenant le nom des groupes dans cette direction. * @static * @async */ - static async DFS(gid: string): Promise<string[]> { - let res = [gid]; - let children = await knex.select('gid').from('groups').where('parent_gid', gid); - - for(let child of children) { - let sub_tree = await Tools.DFS(child.gid); - res = res.concat(sub_tree); + static async DFS(roots : string[], direction : 'parent'|'child'): Promise<GroupSet> { + let stack = roots.slice(); + let visited = {}; + let res = new GroupSet(); + + while(stack.length > 0) { + let gid = stack.pop(); + if(visited[gid] !== true) { + visited[gid] = true; + res.add(gid); + + //console.log(gid); + if(direction === 'child') { + let gd = new groupData(); + gd.parents = [gid]; //on cherche les enfants, ie tous les groupes qui ont `gid` comme parent + stack.push(...await GT.search(gd)); + } + else { + let data = await GT.peek(gid); + stack.push(...data.parents) + } + + } } return res; @@ -174,79 +197,47 @@ export class Tools { /** * @memberof GraphQL - * @summary Fonction qui fait un parcours a profondeur 1 de l'arbre de racine `gid` et renvoie la liste des noeuds. - * @arg {string} gid - Identifiant du groupe, supposé valide. - * @return {Promise(string[])} Renvoie une liste contenant le nom des groupes a profondeur 1. + * @summary Fonction qui renvoie la liste des enfants des noeuds de `roots`. + * @arg {GroupSet} roots - Identifiants des groupes racine, supposés valides. + * @return {Promise(string[])} Renvoie une liste contenant le nom des groupes enfants (!! doublons !!). * @static * @async */ - static async oneDownSearch(gid: string): Promise<string[]> { - let res = [gid]; - let children = await knex.select('gid').from('groups').where('parent_gid', gid); + static async oneDownSearch(roots: GroupSet): Promise<string[]> { + let res = []; - for (let child of children) { - res.push(child.gid); + for(let r of roots) { + let gd = new groupData(); + gd.parents = [r]; //on cherche les enfants, ie tous les groupes qui ont `r` comme parent + res.push(...await GT.search(gd)); } return res; } - /** - * @memberof GraphQL - * @summary Fonction qui renvoie tous les groupes dont l'utilisateur est supervisor. - * @desc Utilise {@link Tools.oneDownSearch} pour avoir la profondeur 1 des arbres enracinés en chacun des groupes dont il est admin. - * @arg {userData} data - Données du user. - * @return {Promise(GroupCollection)} Renvoie une GroupCollection contenant le nom des groupes. - * @static - * @async - */ - static async supervisorOf(data: userData): Promise<GroupCollection> { - let groups = await Tools.adminOf(data); - - let simple = new GroupSet(); - let meta = new GroupSet(); - - for(let g of groups.simpleGroups) { - simple.addList(await Tools.oneDownSearch(g)); - } - for(let g of groups.metaGroups) { - meta.addList(await Tools.oneDownSearch(g)); - } - - return { simpleGroups: simple, metaGroups: meta }; - } - /** * @memberof GraphQL * @summary Fonction qui renvoie tous les groupes dont l'utilisateur est viewer. * @desc Utilise {@link Tools.oneDownSearch} pour avoir la profondeur 1 des arbres enracinés en chacun des groupes dont il est membre. - * @arg {userData} data - Données du user. + * @arg {GroupCollection} groups - Groupes dont le user est membre hérité. * @return {Promise(GroupCollection)} Renvoie une GroupCollection contenant le nom des groupes. * @static * @async */ - static async viewerOf(data: userData): Promise<GroupCollection> { - let groups = await Tools.memberOf(data); + static async viewerOf(groups: GroupCollection): Promise<GroupCollection> { + let simple = groups.simpleGroups; - let simple = new GroupSet(); - let meta = new GroupSet(); - - //Ajouter les groupes dont il est membre + les fils a profondeur 1 - for(let g of groups.simpleGroups) { - simple.addList(await Tools.oneDownSearch(g)); - } - for(let g of groups.metaGroups) { - meta.addList(await Tools.oneDownSearch(g)); - } + //Ajouter les groupes enfants + simple.addList(await Tools.oneDownSearch(simple)); //Ajouter les groupes simples qui sont dans ses métagroupes - let s = await knex.select('simple_group_gid').from('metagroup_memberships').whereIn('meta_group_gid', groups.metaGroups); + let s = await knex.select('simple_group_gid').from('metagroup_memberships').whereIn('meta_group_gid', [...groups.metaGroups]); simple.addList(s.map( elt => { return elt.simple_group_gid; })); //TODO : rajouter les VisibilityEdges - return { simpleGroups: simple, metaGroups: meta }; + return { simpleGroups: simple, metaGroups: await Tools.metaGroupsOfGroups(simple) }; } } \ No newline at end of file diff --git a/src/graphql/connectors/userModel.ts b/src/graphql/models/userModel.ts similarity index 62% rename from src/graphql/connectors/userModel.ts rename to src/graphql/models/userModel.ts index 3d4149202d8ae8f2ac308c6a4f79666d7a94fd37..cad226216294b834df87910e00b5780554730217 100644 --- a/src/graphql/connectors/userModel.ts +++ b/src/graphql/models/userModel.ts @@ -4,7 +4,7 @@ * @memberof GraphQL */ -import { User } from "../resolvers/users"; +import { User } from "../object_resolvers/users"; import { User as UT, userData } from "../../ldap/export/user" import { searchTOLArgs, editProfileArgs } from "../typeDefs/queries"; import { ApolloError } from "apollo-server-core"; @@ -47,19 +47,18 @@ export class UserModel { * @rights connectedOrOnplatal */ async searchTOL(args: searchTOLArgs): Promise<User[]> { - const searchData: userData = { - givenName: args.givenName, - lastName: args.lastName, - nickname: args.nickname, - nationality: args.nationality, - promotion: args.promotion, - groups: args.groups, - sport: args.sport, - phone: args.phone, - mail: args.mail, - address: args.addresses[0], - ips: args.ips - } + //TODO : correctly handle groups (in LDAP, a member can be stored as member, speaker or admin...) + + const searchData = new userData(); + searchData.givenName = args.givenName; + searchData.lastName = args.lastName; + searchData.nickname = args.nickname; + searchData.nationality = args.nationality; + searchData.members = args.groups; + searchData.phone = args.phone; + searchData.mail = args.mail; + searchData.address = args.address; + const userList = await UT.search(searchData); return userList.map((uid) => new User(uid)); } @@ -77,29 +76,23 @@ export class UserModel { let data = await UT.peek(this.contextUser); //Modify some fields, keep the others - let editArgs: userData = { - uid: data.uid, - groups: data.groups, - groupsIsAdmin: data.groupsIsAdmin, - password: data.password, - givenName: data.givenName, - lastName: data.lastName, - nickname: args.nickname, // <- this field is modified by user - promotion: data.promotion, - photo: data.photo, - birthdate: data.birthdate, - nationality: data.nationality, - phone: args.phone, // <- this field is modified - address: data.address, // WTF why can't this be changed ???? - mail: args.mail, // <- this field is modified - ips: data.ips, - directory: data.directory, - login: data.login, - readPerm: data.readPerm, - writePerm: data.writePerm, - forlifes: data.forlifes, - sport: data.sport - }; + let editArgs = new userData(); + editArgs.uid = data.uid; + editArgs.password = data.password; + editArgs.givenName = data.givenName; + editArgs.lastName = data.lastName; + editArgs.nickname = args.nickname; // <- this field is modified by user + editArgs.gender = data.gender; + editArgs.photo = data.photo; + editArgs.phone = args.phone; // <- this field is modified + editArgs.address = data.address; // WTF why can't this be changed ???? + editArgs.mail = args.mail; // <- this field is modified + editArgs.birthdate = data.birthdate; + editArgs.nationality = data.nationality; + editArgs.admins = data.admins; + editArgs.speakers = data.speakers; + editArgs.members = data.members; + editArgs.followers = data.followers; if(await UT.edit(editArgs)) { return new User(data.uid); diff --git a/src/graphql/resolvers/groups.ts b/src/graphql/object_resolvers/groups.ts similarity index 90% rename from src/graphql/resolvers/groups.ts rename to src/graphql/object_resolvers/groups.ts index ad4287b083ee71c8c8e65e93660ace153d33d7a7..59e5511a6780984987bdb7ef2a86a023eb6c452c 100644 --- a/src/graphql/resolvers/groups.ts +++ b/src/graphql/object_resolvers/groups.ts @@ -9,6 +9,7 @@ import {Group as LDAP_Group} from '../../ldap/export/group'; import knex from '../../../db/knex_router'; import { Context } from '../typeDefs/queries'; import { ApolloError, AuthenticationError } from 'apollo-server-core'; +import { Request, UserJoinGroup, GroupJoinMetagroup, GroupCoauthorEvent } from './requests'; export abstract class Group { @@ -59,24 +60,7 @@ export abstract class Group { * Ci-dessous les resolvers a proprement parler. */ - /** - * @memberof GraphQL.Group# - * @function __resolveType - * @summary Renvoie si c'est un SimpleGroup ou un MetaGroup - * @return {string} - * @rights connectedOrOnplatal - */ - __resolveType(): string { - if(this instanceof SimpleGroup) { - return "SimpleGroup"; - } - else if(this instanceof MetaGroup) { - return "MetaGroup" - } - else { - throw new ApolloError("Bad group type"); - } - } + __typename : string = "Bad group type"; /** @rights connectedOrOnplatal */ gid: string; @@ -329,6 +313,66 @@ export abstract class Group { throw new AuthenticationError("Not a member"); } + /** + * @memberof GraphQL.Group# + * @function requestsToGroup + * @summary Renvoie toutes les requetes adressées au groupe. + * @return {Promise(Request[])} + * @rights admin + * @async + */ + async requestsToGroup(args, context: Context, info): Promise<Request[]> { + if (context.models.auth.isAdmin(this.gid)) { + return context.models.request.getRequestsToGroup(this.gid); + } + throw new AuthenticationError("Not an admin"); + } + + /** + * @memberof GraphQL.Group# + * @function userJoinGroupRequestsToGroup + * @summary Renvoie toutes les requetes UserJoinGroup adressées au groupe. + * @return {Promise(UserJoinGroup[])} + * @rights admin + * @async + */ + async userJoinGroupRequestsToGroup(args, context: Context, info): Promise<UserJoinGroup[]> { + if (context.models.auth.isAdmin(this.gid)) { + return context.models.request.getUserJoinGroupRequestsToGroup(this.gid); + } + throw new AuthenticationError("Not an admin"); + } + + /** + * @memberof GraphQL.Group# + * @function groupJoinMetagroupRequestsToGroup + * @summary Renvoie toutes les requetes GroupJoinMetagroup adressées au groupe. + * @return {Promise(GroupJoinMetagroup[])} + * @rights admin + * @async + */ + async groupJoinMetagroupRequestsToGroup(args, context: Context, info): Promise<GroupJoinMetagroup[]> { + if (context.models.auth.isAdmin(this.gid)) { + return context.models.request.getGroupJoinMetagroupRequestsToGroup(this.gid); + } + throw new AuthenticationError("Not an admin"); + } + + /** + * @memberof GraphQL.Group# + * @function groupCoauthorEventRequestsToGroup + * @summary Renvoie toutes les requetes GroupCoauthorEvent adressées au groupe. + * @return {Promise(GroupCoauthorEvent[])} + * @rights admin + * @async + */ + async groupCoauthorEventRequestsToGroup(args, context: Context, info): Promise<GroupCoauthorEvent[]> { + if (context.models.auth.isAdmin(this.gid)) { + return context.models.request.getGroupCoauthorEventRequestsToGroup(this.gid); + } + throw new AuthenticationError("Not an admin"); + } + /** * @memberof GraphQL.Group# * @function visibilityEdges @@ -444,6 +488,8 @@ export class SimpleGroup extends Group { * Ci-dessous les resolvers a proprement parler. */ + __typename: string = "SimpleGroup"; + /** * @memberof GraphQL.SimpleGroup# * @function members @@ -668,6 +714,8 @@ export class MetaGroup extends Group { * Ci-dessous les resolvers a proprement parler. */ + __typename: string = "MetaGroup"; + /** * @memberof GraphQL.MetaGroup# * @function admins diff --git a/src/graphql/resolvers/messages.ts b/src/graphql/object_resolvers/messages.ts similarity index 95% rename from src/graphql/resolvers/messages.ts rename to src/graphql/object_resolvers/messages.ts index 8e9a6c49b889db14756c831bbac6b88215b94326..623bf59f8023c51ddb837685ae30e417ad0673f2 100644 --- a/src/graphql/resolvers/messages.ts +++ b/src/graphql/object_resolvers/messages.ts @@ -8,6 +8,7 @@ import {User} from './users'; import knex from '../../../db/knex_router'; import { Context } from '../typeDefs/queries'; import { ApolloError } from 'apollo-server-core'; +import { GroupSet } from '../models/tools'; export abstract class Message { @@ -153,6 +154,8 @@ export class Announcement extends Message { */ constructor(mid: number) { super(mid); + this.m_authors = new GroupSet(); + this.m_recipients = new GroupSet(); } /** @@ -201,12 +204,28 @@ export class Announcement extends Message { this.m_views = m.views; this.m_dataLoaded = true; - return true; } else { return false; } + + //Charge les authors dans m_authors + + data = await knex.select('gid').from('announcements_authors').where('mid', this.mid); + + for(let t of data) { + this.m_authors.add(t.gid); + } + + //Charge les recipients dans m_recipients + + data = await knex.select('gid').from('announcements_recipients').where('mid', this.mid); + + for (let t of data) { + this.m_authors.add(t.gid); + } } + return true; } @@ -219,6 +238,8 @@ export class Announcement extends Message { */ protected m_importance: number protected m_views : number + protected m_authors : GroupSet + protected m_recipients : GroupSet /** * Ci-dessous les resolvers a proprement parler. @@ -233,10 +254,15 @@ export class Announcement extends Message { * @async */ async authors(args, context: Context, info): Promise<Group[]> { + //TODO: verifier les authorisations throw "Not implemented"; - /*return knex.select({ uid: 'group' }).from('group_message_relationships') - .where('message', messageID).whereIn('status', ['host', 'publish']);*/ + await this.fetchData(); + var ret:Group[]; + for(let t of this.m_authors) { + ret.push(new SimpleGroup(t)); + } + return ret; } /** @@ -248,10 +274,15 @@ export class Announcement extends Message { * @async */ async recipients(args, context: Context, info): Promise<Group[]> { + //TODO: verifier les authorisations throw "Not implemented"; - /*return knex.select({ uid: 'group' }).from('group_message_relationships') - .where('message', messageID).where('status', 'recieve');*/ + await this.fetchData(); + var ret: Group[]; + for (let t of this.m_recipients) { + ret.push(new SimpleGroup(t)); + } + return ret; } /** diff --git a/src/graphql/resolvers/requests.ts b/src/graphql/object_resolvers/requests.ts similarity index 100% rename from src/graphql/resolvers/requests.ts rename to src/graphql/object_resolvers/requests.ts diff --git a/src/graphql/resolvers/users.ts b/src/graphql/object_resolvers/users.ts similarity index 92% rename from src/graphql/resolvers/users.ts rename to src/graphql/object_resolvers/users.ts index ff5bc8abfe947a73646749555d79ed648df2dab9..c69048c4152c48b492ed55be13dcb4f88f1607cd 100644 --- a/src/graphql/resolvers/users.ts +++ b/src/graphql/object_resolvers/users.ts @@ -6,7 +6,7 @@ import {Group, SimpleGroup, MetaGroup} from './groups'; import {Question} from './messages'; import {User as LDAP_User} from '../../ldap/export/user'; -import {Tools, GroupSet} from '../connectors/tools'; +import {Tools, GroupSet} from '../models/tools'; import { Context } from '../typeDefs/queries'; export class User { @@ -64,16 +64,15 @@ export class User { this.m_nickname = data.nickname; this.m_nationality = data.nationality; this.m_birthdate = data.birthdate; - this.m_promotion = data.promotion; this.m_mail = data.mail; this.m_phone = data.phone; - this.m_addresses = [data.address]; + this.m_address = data.address; - this.m_memberOf = data.groups; - //this.m_speakerOf = data.groupsIsSpeaker; - this.m_adminOf = data.groupsIsAdmin; - //this.m_likes = data.likes; + this.m_memberOf = data.members; + this.m_speakerOf = data.speakers; + this.m_adminOf = data.admins; + this.m_likes = data.followers; this.m_dataLoaded = true; return true; @@ -99,11 +98,10 @@ export class User { protected m_nickname: string protected m_nationality: string protected m_birthdate: string - protected m_promotion: string protected m_mail: string protected m_phone: string - protected m_addresses: string[] + protected m_address: string protected m_memberOf: string[] protected m_speakerOf: string[] @@ -192,7 +190,7 @@ export class User { */ async promotion(args, context: Context, info): Promise<string> { await this.fetchData(); - return this.m_promotion; + throw "Not implemented"; } /** @@ -223,15 +221,15 @@ export class User { /** * @memberof GraphQL.User# - * @function addresses - * @summary Renvoie les adresses - * @return {Promise(string[])} + * @function address + * @summary Renvoie l'adresse + * @return {Promise(string)} * @rights connectedOrOnplatal * @async */ - async addresses(args, context: Context, info): Promise<string[]> { + async address(args, context: Context, info): Promise<string> { await this.fetchData(); - return this.m_addresses; + return this.m_address; } /** @@ -247,13 +245,15 @@ export class User { let simple = new GroupSet(this.m_memberOf); let meta = await Tools.metaGroupsOfGroups(simple); - let all: Group[]; + let all = new Array<Group>(); for(let gid of simple) { all.push(new SimpleGroup(gid)); + //all.push(await SimpleGroup.tryCreate(gid)); } for(let gid of meta) { all.push(new MetaGroup(gid)); + //all.push(await MetaGroup.tryCreate(gid)); } return all; diff --git a/src/graphql/resolvers.ts b/src/graphql/resolvers.ts index 5fa111621c73cab2114c93e384c86b47acfc5e07..5256612b1de2fbee97d87b30ba9536dfa6f8d277 100644 --- a/src/graphql/resolvers.ts +++ b/src/graphql/resolvers.ts @@ -1,61 +1,27 @@ /** - * @file Implémentation des requêtes GraphQL. + * @file Résolveurs des requêtes GraphQL. * @author akka vodol, ofacklam * @memberof GraphQL -*/ + * @desc On ne définit dans ce fichier que les resolvers pour les types Query et Mutations. + * En effet on exploite les default resolvers fournis par Apollo Server (le deuxième point) : + * + * > Explicit resolvers are not needed for every type, since Apollo Server provides a default that can perform two actions depending on the contents of parent: + * > - Return the property from parent with the relevant field name + * > - Calls a function on parent with the relevant field name and provide the remaining resolver parameters as arguments + * https://www.apollographql.com/docs/apollo-server/v2/essentials/data.html#default + * + * Dans notre cas, le type de retour de chaque resolver est un objet JS (Group, Message, Request ou User) + * défini dans un des fichiers de `./object_resolvers/` ; donc les méthodes des classes Group, Message, Request et User + * dont le prototype est (parent, args, context: Context, info) sont utilisées comme resolvers de l'objet GraphQL respectif. + */ import { AuthenticationError } from "apollo-server-core"; import { Context } from "./typeDefs/queries"; -import { User } from "./resolvers/users"; -import { Group, SimpleGroup, MetaGroup } from "./resolvers/groups"; -import { Announcement, Event, PrivatePost, Question, Answer, Message } from "./resolvers/messages"; -import { UserJoinGroup, GroupJoinMetagroup, GroupCoauthorEvent, Request } from "./resolvers/requests"; -import { GroupCollection, GroupSet } from "./connectors/tools"; - -/* - Le tag @rights est la gestion des autorisations. - - Le système GraphQL est pensé comme l'interface par laquelle les utilisateurs - intéragissent avec sigma, les graphismes en moins. - Le client peut envoyer tout type de requête. C'est au niveau des resolvers - que les permissions sont gérées. D'où le @rights - - Commençons par un rappel sur le fonctionnement des droits. - Chaque utilisateur a un certain niveau de droit sur chaque groupe. Ce niveau de droit indique - ce qu'il a le droit de savoir et de faire. Chaque niveau est inclus dans les niveaus supérieur. - Les différents niveaux sont : - none - aucun droit - viewer : l'utilisateur a visibilité sur le groupe. Il sait que le groupe existe, et a accès à un certain nombre d'infos. - member : l'utilisateur est membre du groupe - speaker : l'utilisateur peut parler au nom du groupe. Il a le droit de publier des annonces et d'organiser des évènements - admin : l'utilisateur a tous les droits sur le groupe - - Certaines fonctions de connectors effectuent des vérifications d'authorisations avant - de renvoyer une réponse, d'autres non. Pour être sur qu'on ne renvoie jamais de réponse - sans avoir au préalable éffectué les bonnes vérifications, chaque fonction possède dans sa - description un attribut droit, qui décrit les droits que fournit cette fonction. - - La valeur de @rights peut être : - super - la fonction n'effectue aucune véri-fication, et renvoie le resultat demandé - admin( groupUID ) - la fonction ne fait que ce qu'un admin du groupe indiqué aurait le droit de faire - speaker( groupUID ), member( groupUID ), veiwer( groupUID ) - même chose - user - la fonction ne fait que ce que l'utiliateur a le droit de faire (vérifications via l'argument user) - - La procédure a suivre est la suivante : quand une fonction possède un certain niveau de droit, - elle ne peut appeler une fonction possédant un niveau de droit plus large que si - 1 ) on a au préalable vérifié que l'utilisateur possédait effectivement ces droits. - ou - 2 ) on s'est assuré que l'opération effectuée par cet appel particulier de la fonction était dans les droits - de l'utilisateur - - Les resolvers de base de mutation et query ont des droits user. - - Les fonctions qui ne modifient pas la BDD et ne renvoient pas de données sur la BDD n'ont pas de rights. -*/ - -/** - * Résolveurs des différentes requêtes GraphQL - */ +import { User } from "./object_resolvers/users"; +import { Group, SimpleGroup, MetaGroup } from "./object_resolvers/groups"; +import { Announcement, Event, PrivatePost, Question, Answer, Message } from "./object_resolvers/messages"; +import { UserJoinGroup, GroupJoinMetagroup, GroupCoauthorEvent, Request } from "./object_resolvers/requests"; +import { GroupCollection, GroupSet } from "./models/tools"; export const resolvers = { Query: { @@ -203,39 +169,6 @@ export const resolvers = { return context.models.group.getAllSimpleGroups(visibleGroupCollection.simpleGroups); }, - // Toutes les Requests auxquelles un groupe doit répondre - // @rights admin - requestsToGroup: async function (root, args, context: Context): Promise<Request[]> { - if(context.models.auth.isAdmin(args.gid)) { - return context.models.request.getRequestsToGroup(args.gid); - } - throw new AuthenticationError("Not an admin"); - }, - - // @rights admin - userJoinGroupRequestsToGroup: async function (root, args, context: Context): Promise<UserJoinGroup[]> { - if (context.models.auth.isAdmin(args.gid)) { - return context.models.request.getUserJoinGroupRequestsToGroup(args.gid); - } - throw new AuthenticationError("Not an admin"); - }, - - // @rights admin - groupJoinMetagroupRequestsToGroup: async function (root, args, context: Context): Promise<GroupJoinMetagroup[]> { - if (context.models.auth.isAdmin(args.gid)) { - return context.models.request.getGroupJoinMetagroupRequestsToGroup(args.gid); - } - throw new AuthenticationError("Not an admin"); - }, - - // @rights admin - groupCoauthorEventRequestsToGroup: async function (root, args, context: Context): Promise<GroupCoauthorEvent[]> { - if (context.models.auth.isAdmin(args.gid)) { - return context.models.request.getGroupCoauthorEventRequestsToGroup(args.gid); - } - throw new AuthenticationError("Not an admin"); - }, - // TOL // @rights connectedOrOnplatal searchTOL: async function (root, args, context: Context): Promise<User[]> { @@ -364,6 +297,22 @@ export const resolvers = { throw new AuthenticationError("Not a speaker"); }, + // @rights speaker + groupParticipate: async function (root, args, context: Context): Promise<boolean> { + if (context.models.auth.isSpeaker(args.gid)) { + return context.models.message.groupParticipate(args.gid, args.forEvent); + } + throw new AuthenticationError("Not a speaker"); + }, + + // @rights speaker + groupUnparticipate: async function (root, args, context: Context): Promise<boolean> { + if (context.models.auth.isSpeaker(args.gid)) { + return context.models.message.groupUnparticipate(args.gid, args.forEvent); + } + throw new AuthenticationError("Not a speaker"); + }, + // @rights speaker du groupe émetteur groupRequestCoauthorEvent: async function (root, args, context: Context): Promise<GroupCoauthorEvent> { if (context.models.auth.isSpeaker(args.fromGroup)) { @@ -506,6 +455,22 @@ export const resolvers = { throw new AuthenticationError("Not an admin"); }, + // @rights admin + addVisibilityEdge: async function (root, args, context: Context): Promise<boolean> { + if (context.models.auth.isAdmin(args.forGroup)) { + return context.models.group.addVisibilityEdge(args.forGroup, args.visibleBy); + } + throw new AuthenticationError("Not an admin"); + }, + + // @rights admin + removeVisibilityEdge: async function (root, args, context: Context): Promise<boolean> { + if (context.models.auth.isAdmin(args.forGroup)) { + return context.models.group.removeVisibilityEdge(args.forGroup, args.visibleBy); + } + throw new AuthenticationError("Not an admin"); + }, + // @rights admin du groupe émetteur groupRequestJoinMetagroup: async function (root, args, context: Context): Promise<GroupJoinMetagroup> { if (context.models.auth.isAdmin(args.fromGroup)) { @@ -564,6 +529,7 @@ export const resolvers = { // @rights admin du groupe destinataire acceptGroupCoauthorEventRequest: async function (root, args, context: Context): Promise<boolean> { + // Pour l'instant, ce n'est pas a implémenter... let req = await GroupCoauthorEvent.tryCreate(args.request); throw "Not implemented"; //TODO : Vérifier les autorisations @@ -574,6 +540,7 @@ export const resolvers = { // @rights admin du groupe destinataire refuseGroupCoauthorEventRequest: async function (root, args, context: Context): Promise<boolean> { + // Pour l'instant, ce n'est pas a implémenter... let req = await GroupCoauthorEvent.tryCreate(args.request); throw "Not implemented"; //TODO : Vérifier les autorisations @@ -606,7 +573,7 @@ export const resolvers = { throw new AuthenticationError("Not an admin"); }, - // @rights admin du groupe + // @rights admin d'un groupe author censorAnnouncement: async function (root, args, context: Context): Promise<boolean> { throw "Not implemented"; //TODO : Vérifier les autorisations @@ -614,29 +581,12 @@ export const resolvers = { throw new AuthenticationError("Not an admin"); }, - // @rights admin du groupe + // @rights admin d'un groupe author censorEvent: async function (root, args, context: Context): Promise<boolean> { throw "Not implemented"; //TODO : Vérifier les autorisations return context.models.message.censorEvent(args.eventToCensor); throw new AuthenticationError("Not an admin"); - }, - - // Supervisor mutations - // @rights supervisor - takeAdminRights : async function(root, args, context: Context): Promise<boolean> { - if (context.models.auth.isSupervisor(args.forGroup)) { - return context.models.group.takeAdminRights(args.forGroup, context.user.uid); - } - throw new AuthenticationError("Not a supervisor"); - }, - - // @rights supervisor - releaseAdminRights: async function (root, args, context: Context): Promise<boolean> { - if (context.models.auth.isSupervisor(args.forGroup)) { - return context.models.group.releaseAdminRights(args.forGroup, context.user.uid); - } - throw new AuthenticationError("Not a supervisor"); } } }; diff --git a/src/graphql/schema.js b/src/graphql/schema.ts similarity index 50% rename from src/graphql/schema.js rename to src/graphql/schema.ts index 77c88112ca5856a69e3fa1b398575fbd8393c6fb..12b34f9f0fb3b42122a2be73d7eaefbaa3450f62 100644 --- a/src/graphql/schema.js +++ b/src/graphql/schema.ts @@ -3,8 +3,8 @@ * @author akka vodol */ -import actionDefs from './typeDefs/actions.graphql'; -import objectDefs from './typeDefs/objects.graphql'; +const actionDefs = require('./typeDefs/actions.graphql'); +const objectDefs = require('./typeDefs/objects.graphql'); import { resolvers } from './resolvers'; const typeDefs = actionDefs.concat(objectDefs); @@ -13,7 +13,9 @@ const schema = { typeDefs, resolvers, logger: {log: e => console.log(e)}, - inheritResolversFromInterfaces: true + inheritResolversFromInterfaces: true, + //formatResponse: response => { console.log(JSON.stringify(response)); return response; }, + //formatError: error => {console.log(JSON.stringify(error)); return error; } }; export default schema; \ No newline at end of file diff --git a/src/graphql/typeDefs/actions.graphql b/src/graphql/typeDefs/actions.graphql index 42395a204c51cd0b881e99bacd1e2a710b7337b1..9fe106739adfd8abdadeab53f27331ceae4636c1 100644 --- a/src/graphql/typeDefs/actions.graphql +++ b/src/graphql/typeDefs/actions.graphql @@ -13,7 +13,6 @@ type Query { metaGroup(gid:ID!): MetaGroup # Message queries de base - #message(mid:ID!): Message announcement(mid:ID!): Announcement event(mid:ID!): Event privatePost(mid:ID!): PrivatePost @@ -21,7 +20,6 @@ type Query { answer(mid:ID!): Answer # Request queries de base - #request(rid:ID!): Request userJoinGroupRequest(rid:ID!): UserJoinGroup groupJoinMetagroupRequest(rid:ID!): GroupJoinMetagroup groupCoauthorEventRequest(rid:ID!): GroupCoauthorEvent @@ -36,15 +34,6 @@ type Query { allGroups: [Group] allSimpleGroups: [SimpleGroup] - - # Toutes les Requests auxquelles un groupe doit répondre - requestsToGroup(gid:ID!): [Request] - userJoinGroupRequestsToGroup(gid:ID!): [UserJoinGroup] - groupJoinMetagroupRequestsToGroup(gid:ID!): [GroupJoinMetagroup] - groupCoauthorEventRequestsToGroup(gid:ID!): [GroupCoauthorEvent] - - - # TOL searchTOL( givenName: String, @@ -52,14 +41,11 @@ type Query { nickname: String, nationality: String, school: String, - promotion: String, groups: [String], studies: String, - sport: String, phone: String, mail: String, - addresses: [String], - ips: [String] + address: String ): [User!] } @@ -69,30 +55,48 @@ type Mutation { Par rapport à un groupe donné, un user peut avoir différents niveaux de droits : - none : ne sait meme pas que le groupe existe, aucun autre droit (typiquement, une connection où l'utilisateur ne s'est pas authentifié) - authenticated : sait que le groupe existe, aucun autre droit (une connection on-platal sans auth, ou une connection authentifiée) - - viewer : le user a aussi accès à l'activité publique du groupe : frontpage, Q&A, liste des membres, speakers et admins - - member : le user a aussi acces à l'activité interne du groupe : les PrivatePost, ainsi que les Message dont le groupe est auteur ou destinataire + - viewer : le user a aussi accès à l'activité publique du groupe : frontpage, Q&A, liste des membres, speakers et admins, Message dont le groupe est destinataire + - member : le user a aussi acces à l'activité interne du groupe : les PrivatePost, ainsi que les Message dont le groupe est auteur - speaker : le user peut aussi parler au nom du groupe. Il a le droit de publier des annonces et d'organiser des évènements - admin : le user a tous les droits sur le groupe - - supervisor : le user est admin du parent du groupe et peut donc intervenir dans ce groupe (il est par défaut 'viewer' mais peut prendre les droits d'admin arbitrairement) Un des rôles du *graphe organique des groupes* est de définir le niveau de droit des users pour chaque groupe. - D'abord, petit détail de terminologie : les cinq niveaux de droits sont inclus les uns dans les autres (un speaker est aussi un viewer, par ex.) (sauf pour supervisor qui n'est pas admin par défaut) - - Les conditions pour qu'un user soit membre, speaker ou admin sont claires, puisque cette information est stockée directement en BDD. - - Un user non-membre est viewer du groupe G : - - s'il est membre d'un groupe immédiatement parent de G (one-edge-down visibility), ou - - s'il est membre d'un groupe faisant partie du champ "visibilityEdge" de G + D'abord, petit détail de terminologie : les cinq niveaux de droits sont inclus les uns dans les autres (un speaker est aussi un viewer, par ex.) (sauf pour les permissions héritées) + Plus précisément, on a les inclusions suivantes : admin strict > speaker > membre strict > membre hérité > viewer > authenticated. + Il n'y a que admin hérité qui n'est pas nécessairement inclus dans les autres niveaux de droits. + + Dans la BDD sous-jacente, il faut que pour chaque groupe, on ait admin > speaker > member. + + Détaillons ici les conditions exactes pour avoir un niveau de droit donné. + == Pour les groupes simples == + - Member : + - Un user est membre strict du groupe G s'il est member de G selon la BDD sous-jacente. + - Un user est membre hérité du groupe G s'il est membre strict d'un de ses descendants. + - Speaker : un user est speaker du groupe G s'il est speaker de G selon la BDD. Pas de notion d'héritage de speaker. + - Admin : + - Un user est admin strict du groupe G s'il est admin de G selon la BDD. + - Un user est admin hérité du groupe G s'il est admin strict d'un de ses ascendants. + - Viewer : un user est viewer du groupe G + - s'il est membre hérité de G. + - s'il est membre hérité d'un groupe immédiatement parent de G (one-edge-down visibility), ou + - s'il est membre hérité d'un groupe faisant partie du champ "visibilityEdge" de G - s'il est membre d'un métagroupe dont G est membre (implicit visibility-edges). - - Dans tous les autres cas, le user a le niveau de droits "none". + - Dans tous les autres cas, le user a le niveau de droits "none" ou "authenticated", selon le cas de figure. + + == Pour les méta-groupes == + - Un user est membre d'un méta-groupe G s'il est membre (hérité) d'un groupe simple dans G. + - Un user est speaker d'un méta-groupe G s'il est speaker d'un groupe simple dans G. + - Un user est admin d'un méta-groupe G s'il est admin (hérité) d'un groupe simple dans G. + - Un user est viewer d'un méta-groupe G s'il est viewer d'un groupe simple dans G. + L'autre rôle du *graphe organique des groupes* est de permettre l'administration "en cascade" des groupes enfants. - Si un groupe est le parent d'un autre, alors les admins du groupe parent peuvent se déclarer admins du groupe enfant. Exemples : - - BR est parent de Chocapix. L'admin de Chocapix est parti en vacances. L'admin de BR peut se déclarer admin de Chocapix et faire ce qu'il a à faire, sans attendre le retour du respo Chocapix. - - Cotisants-Kès est parent de Troll'X. Troll'X fait n'importe quoi (en floodant de Messages par ex). Les admins de Cotisants-Kès (les kessiers) peuvent se déclarer admin de Troll'X et stopper les dégâts. + Si un groupe est le parent d'un autre, alors les admins du groupe parent sont admins (hérités) du groupe enfant. Exemples : + - BR est parent de Chocapix. L'admin de Chocapix est parti en vacances. L'admin de BR peut, en tant qu'admin (hérité) de Chocapix, faire ce qu'il a à faire, sans attendre le retour du respo Chocapix. + - Cotisants-Kès est parent de Troll'X. Troll'X fait n'importe quoi (en floodant de Messages par ex). Les admins de Cotisants-Kès (les kessiers) peuvent, comme ils sont admins hérités de Troll'X, stopper les dégâts. Remarque sur speaker : - Il s'agit d'un nouveau niveau de droit par rapport à Frankiz 3.0 ; il n'est pas implémenté dans le LDAP frankiz. - Par conséquent, il est probable que, au début du moins, on impose que speaker=admin, pour pouvoir continuer à utiliser ce LDAP. - Le mieux serait néanmoins de rajouter cette propriété au LDAP. + Il s'agit d'un nouveau niveau de droit par rapport à Frankiz 3.0 ; qui est a présent implémenté sur le LDAP bloaziadur. Les mutations ci-dessous sont divisées en quatre, selon le niveau de droit requis pour pouvoir les appeler. Les Mutations concernant les *Requests* suivent à peu près toutes le schéma suivant : @@ -167,6 +171,9 @@ type Mutation { # Speaker mutations writePostsSummary(forGroup: ID!, content: String): Boolean + groupParticipate(gid: ID!, forEvent: ID!): Boolean + groupUnparticipate(gid: ID!, forEvent: ID!): Boolean + groupRequestCoauthorEvent( fromGroup: ID!, toGroup: ID!, @@ -250,9 +257,13 @@ type Mutation { description: String, mail: String, website: String, + frontPage: String, school: String ): Group + addVisibilityEdge(forGroup: ID!, visibleBy: ID!): Boolean + removeVisibilityEdge(forGroup: ID!, visibleBy: ID!): Boolean + groupRequestJoinMetagroup(fromGroup: ID!, toMetagroup: ID!, comment: String): GroupJoinMetagroup acceptUserJoinRequest(request: ID!, comment: String): Boolean @@ -271,8 +282,4 @@ type Mutation { censorAnnouncement(announcementToCensor: ID!): Boolean censorEvent(eventToCensor: ID!): Boolean - # Superviser mutations - takeAdminRights(forGroup: ID!) : Boolean - releaseAdminRights(forGroup: ID!) : Boolean - } diff --git a/src/graphql/typeDefs/objects.graphql b/src/graphql/typeDefs/objects.graphql index 05dc650ace078ee2a511d782b3577da4ae19d9de..1150f11df008dcfecd5652d619ff870ffde7c40d 100644 --- a/src/graphql/typeDefs/objects.graphql +++ b/src/graphql/typeDefs/objects.graphql @@ -37,13 +37,16 @@ type User { # Pour le contacter mail: String phone: String - addresses: [String] # Adresse(s) de l'utilisateur (numero de casert par exemple) + address: String # Adresse de l'utilisateur (numero de casert par exemple) # Ses interactions avec des groupes - memberOf: [Group] # Groupes dont l'utilisateur est membre - speakerOf: [Group] - adminOf: [Group] + memberOf: [Group] # Membre strict + inheritedMemberOf: [Group] # Membre hérité + speakerOf: [Group] # Speaker (strict) + adminOf: [Group] # Admin strict + inheritedAdminOf: [Group] # Admin hérité likes: [Group] # Groupes dont l'utilisateur est sympathisant (purement indicatif, pas d'influence sur les niveaux de droit) + dislikes: [Group] # Groupes que l'utilisateur veut cacher # Les Message dont il est l'auteur questionsFromUser: [Question] # Les seuls Messages publics où `authors` est de type User @@ -76,13 +79,24 @@ interface Group { answers: [Answer] # permet d'obtenir les questions qui ont eu une réponse # Activité interne - announcementsFromGroup: [Announcement] # annonces écrites par le groupe + # Viewer pour voir les events/annonces adressés au groupe announcementsToGroup: [Announcement] # annonces adressées au groupe - eventsFromGroup: [Event] eventsToGroup: [Event] + + # Member pour voir les events/annonces créés par le groupe + announcementsFromGroup: [Announcement] # annonces écrites par le groupe + eventsFromGroup: [Event] + + # Member pour voir les posts privés privatePosts: [PrivatePost] postsSummary: String # récapitulatif de l'activité interne du groupe, en markdown + # Toutes les Requests auxquelles un groupe doit répondre (admin) + requestsToGroup: [Request] + userJoinGroupRequestsToGroup: [UserJoinGroup] + groupJoinMetagroupRequestsToGroup: [GroupJoinMetagroup] + groupCoauthorEventRequestsToGroup: [GroupCoauthorEvent] + # Graphe organique visibilityEdges: [Group] # se rendre visible par des groupes en plus du graphe organique } @@ -97,7 +111,7 @@ type SimpleGroup implements Group { mail: String website: String - # Admins, speakers (respos com), membres, sympathisants du groupe + # Admins, speakers (respos com), membres, sympathisants du groupe (stricts pour ce groupe) members: [User] speakers: [User] admins: [User] @@ -109,15 +123,26 @@ type SimpleGroup implements Group { answers: [Answer] # permet d'obtenir les questions qui ont eu une réponse # Activité interne - announcementsFromGroup: [Announcement] # annonces écrites par le groupe + # Viewer pour voir les events/annonces adressés au groupe announcementsToGroup: [Announcement] # annonces adressées au groupe - eventsFromGroup: [Event] eventsToGroup: [Event] + + # Member pour voir les events/annonces créés par le groupe + announcementsFromGroup: [Announcement] # annonces écrites par le groupe + eventsFromGroup: [Event] + + # Member pour voir les posts privés privatePosts: [PrivatePost] postsSummary: String # récapitulatif de l'activité interne du groupe, en markdown + + # Toutes les Requests auxquelles un groupe doit répondre (admin) + requestsToGroup: [Request] + userJoinGroupRequestsToGroup: [UserJoinGroup] + groupJoinMetagroupRequestsToGroup: [GroupJoinMetagroup] + groupCoauthorEventRequestsToGroup: [GroupCoauthorEvent] # Graphe organique des groupes - parent: SimpleGroup # Groupe parent + parents: [SimpleGroup] # Groupes parents children: [SimpleGroup] # Groupes enfants memberOfMeta: [MetaGroup] visibilityEdges: [Group] # se rendre visible par des groupes en plus du graphe organique @@ -145,13 +170,24 @@ type MetaGroup implements Group { answers: [Answer] # permet d'obtenir les questions qui ont eu une réponse # Activité interne - announcementsFromGroup: [Announcement] # annonces écrites par le groupe + # Viewer pour voir les events/annonces adressés au groupe announcementsToGroup: [Announcement] # annonces adressées au groupe - eventsFromGroup: [Event] eventsToGroup: [Event] + + # Member pour voir les events/annonces créés par le groupe + announcementsFromGroup: [Announcement] # annonces écrites par le groupe + eventsFromGroup: [Event] + + # Member pour voir les posts privés privatePosts: [PrivatePost] postsSummary: String # récapitulatif de l'activité interne du groupe, en markdown + # Toutes les Requests auxquelles un groupe doit répondre (admin) + requestsToGroup: [Request] + userJoinGroupRequestsToGroup: [UserJoinGroup] + groupJoinMetagroupRequestsToGroup: [GroupJoinMetagroup] + groupCoauthorEventRequestsToGroup: [GroupCoauthorEvent] + # Graphe organique visibilityEdges: [Group] # se rendre visible par des groupes en plus du graphe organique } diff --git a/src/graphql/typeDefs/objects_ldap.graphql b/src/graphql/typeDefs/objects_ldap.graphql deleted file mode 100644 index 28c5d4e57318639158bed719d7307226509f816a..0000000000000000000000000000000000000000 --- a/src/graphql/typeDefs/objects_ldap.graphql +++ /dev/null @@ -1,241 +0,0 @@ -# hawkspar->all ; doc ? - -# Utilisateurs -type User { - # Prénom de l'utilisateur - givenName: String! - # Nom de famille - lastName: String! - # Surnom - nickname: String - nationality: String - uid: ID! - birthdate: String! - mail: String - phone: String - # Groupes dont l'utilisateur est membre. - groups: [SimpleGroup] - # Groupes que l'utilisateur aime. - likes: [Group] - # A terme rajouter aussi admin - # Adresse(s) de l'utilisateur. - addresses: [String] - # Promotion - promotion: String - photo: String -} - -# Groupes associatifs - -""" -L'interface Group représente les deux types de groupes implémentés dans Sigma : les groupes -simples, dont les membres sont des utilisateurs, et les métagroupes, dont les membres sont -des groupes simples (tel que Federez, dont les membres incluent le BR et DaTA). -""" -interface Group { - gid: ID! - name: String - # Site Web. - website: String - description: String - - # Jour et heure de création du groupe. - createdAt: String! - # Dernière mise à jour du groupe. - updatedAt: String! - - # member requests - - # Les posts prives dans ce groupe - privatePosts: [PrivatePost] - # Les questions addressees à ce groupe - questions: [Question] - # Les reponses donnees par ce groupe - answers: [Answer] -} - -# Le groupe de base, dont les membres sont des utilisateurs : binets, Kès... -type SimpleGroup implements Group { - uid: ID - name: String - website: String - createdAt: String! - updatedAt: String! - - # Admin, membres, sympathisants du groupe - admins: [User] - members: [User] - likers: [User] - - description: String - # École d'origine du groupe - school: String - # Groupe parent - parent: Group - - privatePosts: [PrivatePost] - questions: [Question] - answers: [Answer] -} - -# Un groupe dont les membre sont d'autres groupes -type MetaGroup implements Group { - uid: ID - name: String - website: String - createdAt: String! - updatedAt: String! - description: String - - # Les groupes constitutifs du méta-groupe. - members: [Group]! - - privatePosts: [PrivatePost] - questions: [Question] - answers: [Answer] -} - - -# Tout type de message adressé à un ou plusieurs groupes. - -# Auteur possible d'un Message -# union AuthorUnion = Group | [Group] | User -# union RecipientUnion = Group | [Group] - -# Les unions sont assez faibles dans GraphQL, -# elles n'acceptent pas les listes ni les interfaces - -# L'interface Message représente toute information que veut communiquer un groupe ou un user. -# Par choix de paradigme, tout Message est adressé à un (ou des) groupe(s). -# Les types implémentés sont divisés en deux : -# - les Message émanant d'un groupe : Announcement et Event, ainsi que Answer -# - les Message émanant d'un user : PrivatePost, ainsi que Question - -interface Message { - id: ID! - # Titre du message - title: String! - content: String - createdAt: String! - updatedAt: String! -} - -# Annonce publique effectuée par un ou plusieurs groupes. -type Announcement implements Message { - id: ID! - title: String! - createdAt: String! - updatedAt: String! - content: String! - importance: Int - views: Int - forEvent: Event - - authors: [Group] - recipients: [Group] -} - -# Événements organisés par un ou plusieurs groupes. -type Event implements Message { - id: ID! - # Intitulé de l'événement - title: String! - # Lieu de l'événement - location: String - createdAt: String! - updatedAt: String! - startTime: String! - endTime: String! - # Organisateurs - # Personnes qui participent à l'événement. - participatingGroups: [Group] - participatingUsers: [User] - content: String - asAnnouncement: Announcement - - authors: [Group] - recipients: [Group] -} - -# Post interne d'un membre sur la page interne de son groupe -type PrivatePost implements Message { - id: ID! - createdAt: String! - updatedAt: String! - title: String! - content: String! - - authors: User - recipients: Group -} - -# Question posée par un user à un groupe -type Question implements Message { - id: ID! - createdAt: String! - updatedAt: String! - title: String! - content: String! - - authors: User - recipients: Group - - # Une annonce éventuellement concernée par cette question. - # Null si la question ne concerne pas une annonce particulière - - forAnnouncement: Announcement - - # Référence la réponse donnée par le groupe à cette Question. Si pas encore répondu, null. - forAnswer: Answer -} - -# Réponse à une Question -type Answer implements Message { - id: ID! - createdAt: String! - updatedAt: String! - title: String! - content: String! - - authors: Group - recipients: Group - - # La question à laquelle cette Answer répond. Non-nullable bien sûr - forQuestion: Question! -} - -interface Request { - # ID de la demande - id: ID! - # message accompagnant la demande - message: String -} - -# Demande d'un utilisateur désirant rejoindre le groupe. -type UserJoinGroup implements Request{ - id: ID! - message: String - # Émetteur de la demande - user: User -} - - -# Demande d'un groupe voulant rejoindre un événement -type GroupJoinEvent implements Request{ - id: ID! - message: String - # Événement concerné - event: Event - # Groupe voulant rejoindre l'événement - groupWantingToJoin: Group -} - -# Demande au récipiendaire de rejoindre l'organisation d'un événement. -type YourGroupHostEvent implements Request{ - id: ID! - message: String - # Événement concerné - event: Event - # Groupe ayant publié l'évènement et lancé l'invitation - sender: Group -} diff --git a/src/graphql/typeDefs/queries.d.ts b/src/graphql/typeDefs/queries.d.ts index 96cbc8779c60eab5c9981f4c6d452effba1b1fbd..31d469632dbc75cd3393622e98b3ac71fb3889b0 100644 --- a/src/graphql/typeDefs/queries.d.ts +++ b/src/graphql/typeDefs/queries.d.ts @@ -1,14 +1,19 @@ -import { AuthorisationModel } from "../connectors/authorisationModel"; -import { UserModel } from "../connectors/userModel"; -import { GroupModel } from "../connectors/groupModel"; -import { MessageModel } from "../connectors/messageModel"; -import { RequestModel } from "../connectors/requestModel"; +/** + * @file Ce fichier définit quelques types utiles pour le serveur Apollo. + * @author ofacklam +*/ + +import { AuthorizationModel } from "../models/authorization"; +import { UserModel } from "../models/userModel"; +import { GroupModel } from "../models/groupModel"; +import { MessageModel } from "../models/messageModel"; +import { RequestModel } from "../models/requestModel"; interface Context { request, user: { uid: string }, models: { - auth: AuthorisationModel, + auth: AuthorizationModel, user: UserModel, group: GroupModel, message: MessageModel, @@ -22,14 +27,11 @@ interface searchTOLArgs { nickname: string, nationality: string, school: string, - promotion: string, groups: string[], studies: string, - sport: string, phone: string, mail: string, - addresses: string[], - ips: string[] + address: string } interface editProfileArgs { @@ -54,5 +56,6 @@ interface editGroupArgs { description: string, mail: string, website: string, + frontPage: string, school: string } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index f55c10752cdc50e6dc083b745c74d68f7b3eeb6b..e0aa4dd5fa60f18298a95c0c42482efaf2c62b89 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ dotenv.config(); import app from './app'; import colors from 'colors'; -const port = process.env.PORT || 3000; +const port = process.env.PORT; const hostnameConfigMap = { 'development': 'localhost', 'staging': '0.0.0.0', diff --git a/src/ldap/export/group.ts b/src/ldap/export/group.ts index 7f9f11f9d4fd12d7600e67f40942113339a0646d..d36eb37a844afe75926bc3cc8c51b5eab1e66f34 100644 --- a/src/ldap/export/group.ts +++ b/src/ldap/export/group.ts @@ -1,34 +1,19 @@ /** * @file Ce fichier contient la classe de l'API du LDAP qui gère les opérations sur les groupes. Elle est destinée à être exportée pour être utilisée par les resolvers. * @author hawkspar + * @memberof LDAP */ -import {ldapConfig} from '../internal/config'; +import { ldapConfig, groupData, categories } from '../internal/config'; import {Basics} from '../internal/basics'; import {Tools} from '../internal/tools'; -/** - * @interface groupData - * @var {string} gid - Identifiant du groupe - * @var {string} name - Nom du groupe (souvent son nom mais pas nécessairement) - * @var {string} type - Statut du groupe ; binet, section sportive... (actuellement juste 'binet' ou 'free') - * @var {string[]} members - Liste des membres du groupe - * @var {string[]} admins - Liste des admins du groupe ; supposée être une sous-liste de la précédente - * @var {string} description - Description du groupe (facultatif) - */ -export interface groupData { - "gid": string, - "name": string, - "type": string, - "members": string[], - "admins": string[], - "description"?: string -} - //------------------------------------------------------------------------------------------------------------------------ // Classes à exporter TBT //------------------------------------------------------------------------------------------------------------------------ +export {groupData}; + export class Group { /** * @memberof LDAP @@ -41,7 +26,7 @@ export class Group { /** * @memberof LDAP * @summary Fonction qui renvoit toutes les infos relatives à un groupe particulier. - * @desc Cette fonction utilise {@link Tools.peek} avec l'interface {@link groupData}. + * @desc Cette fonction utilise {@link Tools.peek} avec l'interface {@link groupData}. Elle ne fait que consulter le groupe sans le changer, et en extrayant les uid des membres. * @arg {string} gid - Identifiant du groupe * @return {Promise(groupData)} Informations recueillies ; renvoie une liste de dictionnaire avec le profil complet du groupe au format {@link groupData}. * @static @@ -49,7 +34,10 @@ export class Group { */ static async peek(gid: string) : Promise<groupData> { try { - return Tools.peek<groupData>("gr", gid); + let data = await Tools.peek<groupData>("group", gid, groupData); + // Extraction des uid de membres (TBM pour inclure childs aussi) + for (let cat of categories.concat(["parents"])) data[cat] = data[cat].map(dn => dn.split(',')[0].split('=')[1]); + return data; } catch(err) { throw "Erreur lors d'une recherche d'informations sur un groupe."; @@ -67,185 +55,117 @@ export class Group { */ static async search(data: groupData) : Promise<string[]> { try { - return Tools.search("gr", data); + return Tools.search("group", data); } catch(err) { throw "Erreur lors de la recherche approximative d'un groupe."; } } + /** + * @memberof LDAP + * @summary Fonction qui permet de rajouter un administrateur à un groupe. + * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. Le nouvel administrateur ne devient pas membre ou porte-parole du groupe pour autant ! + * @arg {string} uid - Identifiant du membre futur admin + * @arg {string} gid - Identifiant du groupe + * @return {boolean} `true` si la modification s'est bien déroulée, false sinon + * @async + * @static + */ + static async addAdmin(uid: string, gid: string): Promise<boolean> { return Tools.add(uid, gid, "admins"); } + + /** + * @memberof LDAP + * @summary Fonction qui permet de supprimer un administrateur. + * @desc Cette fonction fait essentiellement appel à {@link Tools.remove}. + * Elle ne remonte pas les échelons, car cela permettrait à un admin d'un petit groupe de supprimer un admin d'un grand. + * @arg {string} uid - Identifiant de l'admin à dégrader, supposé membre + * @arg {string} gid - Identifiant du groupe + * @return {boolean} `true` si la modification s'est bien déroulée, false sinon + * @async + * @static + */ + static async remAdmin(uid: string, gid: string): Promise<boolean> { return Tools.remove(uid, gid, "admins"); } + + /** + * @memberof LDAP + * @summary Fonction qui permet de rajouter un porte-parole à un groupe. + * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. Elle ne rajoute pas l'utilisateur au groupe. + * @arg {string} uid - Identifiant du membre futur porte-parole + * @arg {string} gid - Identifiant du groupe + * @return {boolean} `true` si la modification s'est bien déroulée, false sinon + * @async + * @static + */ + static async addSpeaker(uid: string, gid: string): Promise<boolean> { return Tools.add(uid, gid, "speakers"); } + + /** + * @memberof LDAP + * @summary Fonction qui permet de rétrograder un membre du stade de porte-parole d'un groupe au stade d'utilisateur. + * @desc Cette fonction fait essentiellement appel à {@link Tools.remove}. Elle dégrade aussi d'un éventuel statut d'administrateur. + * @arg {string} uid - Identifiant de l'admin à dégrader (pas supposé valide) + * @arg {string} gid - Identifiant du groupe + * @return {boolean} `true` si la modification s'est bien déroulée, false sinon + * @async + * @static + */ + static async remSpeaker(uid: string, gid: string): Promise<boolean> { return Tools.remove(uid, gid, "speakers"); } + /** * @memberof LDAP * @summary Fonction qui permet d'ajouter un utilisateur à un groupe. - * @desc Cette fonction fait essentiellement appel à {@link Tools.getMembers}, {@link Tools.getGroups} et {@link LDAP.change}. + * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. * @arg {string} uid - Identifiant de l'utilisateur à ajouter * @arg {string} gid - Identifiant du groupe * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ - static async addMember(uid: string, gid: string) : Promise<boolean> { - try { - // Vérifie que l'utilisateur est pas déjà membre pour groupes - let lm = await Tools.getMembers(gid); - if (!lm.includes(uid)) { - let vals = {}; - vals[ldapConfig.group.members] = uid; - // Erreur si pb lors de la modification - if (!await Basics.change("gr", gid, "add", vals)) { - throw "Erreur lors de la modification dans l'arbre des groupes pour ajouter un membre."; - } - } - } - catch(err) { - throw "Erreur lors de la recherche de la liste des membres pour ajouter un membre."; - } - try { - // Vérifie que l'utilisateur est pas déjà membre pour users - let lg = await Tools.getGroups(uid); - if (!lg.includes(gid)) { - let vals2 = {}; - vals2[ldapConfig.user.groups] = gid; - // Erreur si pb lors de la modification - if (!await Basics.change("us", uid, "add", vals2)) { - throw "Erreur lors de la modification dans l'arbre des utilisateurs pour ajouter un membre."; - } - } - return true; - } - catch(err) { - throw "Erreur lors de la recherche de la liste des membres pour ajouter un membre."; - } - } + static async addMember(uid: string, gid: string) : Promise<boolean> { return Tools.add(uid, gid, "members"); } /** * @memberof LDAP * @summary Fonction qui permet de supprimer un membre existant d'un groupe. - * @desc Cette fonction fait essentiellement appel à {@link Tools.getMembers}, {@link Tools.getGroups} et {@link LDAP.change}. - * @arg {string} uid - Identifiant de l'ex-membre + * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. + * Cette fonction supprime tous les droits de l'utilisateur sur le groupe, mais aussi sur les groupes sources si son statut de membre était hérité. + * @arg {string} uid - Identifiant de l'ex-membre (pas supposé valide) * @arg {string} gid - Identifiant du groupe * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ - static async remMember(uid: string, gid: string): Promise<boolean> { - try { - // Vérifie que l'utilisateur est pas déjà viré pour groupes - let lm = await Tools.getMembers(gid); - if (lm.includes(uid)) { - // Supprime tous les utilisateurs - if (!await Basics.change("gr", gid, "del", ldapConfig.group.members)) { - throw "Erreur lors de la suppression de tous les membres du groupe."; - } - // Les rajoute un par un, sauf pour le supprimé - lm.forEach(id => { - if (id!=uid) { - Group.addMember(id, gid).then(res => { - if (!res) { throw "Erreur lors du ré-ajout d'un autre membre"; } - }); - } - }); - } - } - catch(err) { - throw "Erreur pour obtenir une liste de membres d'un groupe pour supprimer un membre du groupe."; - } - try { - let lg = await Tools.getGroups(uid); - // Vérifie que l'utilisateur est pas déjà viré pour users - if (lg.includes(gid)) { - // Supprime tous les groupes - if (!await Basics.change("us", uid, "del", ldapConfig.user.groups)) { - throw "Erreur lors de la suppression de tous les groupes du membre."; - } - // Les rajoute un par un, sauf pour le supprimé - lg.forEach(id => { - if (id!=gid) { - Group.addMember(uid, id).then(res => { - if (!res) { throw "Erreur lors du ré-ajout des autres groupes"; } - }); - } - }); - } - return true; - } - catch(err) { - throw "Erreur pour obtenir une liste de groupes d'un membres pour le supprimer du groupe."; - } - } + static async remMember(uid: string, gid: string): Promise<boolean> { return Tools.remove(uid, gid, "members"); } /** * @memberof LDAP - * @summary Fonction qui permet de promouvoir un membre au stade d'administrateur d'un groupe. - * @desc Cette fonction fait essentiellement appel à {@link Group.addMember} {@link Tools.getAdmins} et {@link LDAP.change}. Elle n'autorise pas - * les doublons et opère dans les deux dns users et groups. - * @arg {string} uid - Identifiant du membre futur admin + * @summary Fonction qui permet d'ajouter un sympathisant à un groupe. + * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. + * @arg {string} uid - Identifiant de l'utilisateur à ajouter * @arg {string} gid - Identifiant du groupe - * @return {boolean} `true` si la modification s'est bien déroulée, false sinon + * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ - static async addAdmin(uid: string, gid: string): Promise<boolean> { - // Ajoute le membre au groupe avant d'en faire un admin - if (!await Group.addMember(uid,gid)) { throw "Erreur lors de l'ajout du futur admin en tant que membre."; } - try { - let la = await Tools.getAdmins(gid); - if (!la.includes(uid)) { - // Finalement modification, uniquement dans groups - let vals = {}; - vals[ldapConfig.group.admins] = uid; - if (!await Basics.change("gr", gid, "add", vals)) { - throw "Erreur lors de l'ajout de l'admin dans l'arbre des groupes."; - } - } - return true; - } - catch(err) { - throw "Erreur lors de l'obtention de la liste des administrateurs d'un groupe."; - } - } + static async addFollower(uid: string, gid: string) : Promise<boolean> { return Tools.add(uid, gid, "followers"); } /** * @memberof LDAP - * @summary Fonction qui permet de rétrograder un membre du stade d'administrateur d'un groupe au stade d'utilisateur. - * @desc Cette fonction fait essentiellement appel à {@link Group.remMember}, {@link Group.addMember} {@link LDAP.change}. - * Rajoute l'utilisateur au groupe par effet de bord si l'utilisateur n'est pas administrateur. - * @arg {string} uid - Identifiant de l'admin à dégrader, supposé membre + * @summary Fonction qui permet de supprimer un sympathisant d'un groupe. + * @desc Cette fonction fait essentiellement appel à {@link Tools.add}. + * @arg {string} uid - Identifiant de l'ex-sympathisant (pas supposé valide) * @arg {string} gid - Identifiant du groupe - * @return {boolean} `true` si la modification s'est bien déroulée, false sinon + * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static */ - static async remAdmin(uid: string, gid: string): Promise<boolean> { - // Peut paraître absurde mais permet de s'assurer que le membre est bien présent et que ses champs sont comme il faut - if (!(await Group.remMember(uid, gid) && Group.addMember(uid,gid))) { throw "Erreur dans l'éjection/réadmission de l'ex-admin."; } - try { - // Vérifie que l'utilisateur est bien admin (comme dans delGroupMember) - let la = await Tools.getAdmins(gid); - if (la.includes(uid)) { - // Supprime tous les administrateurs - if (!await Basics.change("gr", gid, "del", ldapConfig.group.admins)) { - throw "Erreur dans la suppression de tous les admins pour en supprimer un."; - } - // Les rajoute un par un, sauf pour le supprimé - la.forEach(id => { - if (id!=uid) { Group.addAdmin(id, gid).then(res => { - if (!res) { throw "Erreur dans le réajout d'un des autres admins."; } - }); } - }); - } - return true; - } - catch(err) { - throw "Erreur lors de l'obtention de la liste des administrateurs d'un groupe."; - } - } + static async remFollower(uid: string, gid: string): Promise<boolean> { return Tools.remove(uid, gid, "followers"); } + /** * @memberof LDAP * @summary Fonction qui créé un nouveau groupe dans le LDAP. * @desc Cette fonction fait une utilisation massive d'eval pour anonymiser son code ; c'est mal et cela suppose que beaucoup de soins ont été pris lors de - * l'escape de ses paramètres. Appelle {@link LDAP.add} et {@link LDAP.change}, mais aussi {@link Group.addMember} et {@link Group.addAdmin} - * pour gérer les groupes du nouvel utilisateur. Attention une manip FOIREUSE est cachée dedans. + * l'escape de ses paramètres. Appelle {@link LDAP.add} et {@link LDAP.change}, mais aussi {@link Tools.add} + * pour gérer les groupes du nouvel utilisateur. Cettte application permet de rajouter des utilisateurs à toutes les catégories du groupe. * @arg {groupData} data - Dictionnaire des informations utilisateurs (voir détail des champs dans ldapConfig.json) * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async @@ -257,80 +177,67 @@ export class Group { // gid de base généré à partir du nom standardisé, pas à partir de l'entrée 'gid' ! try { - Tools.generateReadableId(data['name']).then(id => { - vals[ldapConfig.key_id]=id; - vals[ldapConfig.group['name']]=id; + Tools.generateReadableId("group", data['name']).then(id => { + vals[ldapConfig.group.gid] = id; + vals[ldapConfig.group['name']] = id; }); } catch(err) { throw "Erreur lors de la génération d'un hruid pour créer un nouveau groupe."; } - let gid: string = vals[ldapConfig.key_id]; + let gid: string = vals[ldapConfig.group.gid]; // Ecriture de toutes les valeurs directement inscrites dans le LDAP - for (let key_att in data) { vals[ldapConfig.group[key_att]]=data[key_att] }; + for (let key_att of ["name","logo","description","site","category"]) { + if (data[key_att] != undefined) vals[ldapConfig.group[key_att]]=data[key_att] + }; // Appel à la fonction de base - if (!await Basics.add("gr", vals)) { - throw "Erreur lors de la création d'une nouvelle feuille dans l'arbre des groupes."; - } + if (!await Basics.add("group", vals)) throw "Erreur lors de la création d'une nouvelle feuille dans l'arbre des groupes."; + // Certains champs nécessitent de petits calculs let vals2={}; - // Encore un champ redondant - vals2[ldapConfig.group['adress']] = gid; - // ?! - vals2[ldapConfig.group['password']] = ''; + vals2[ldapConfig.group['password']] = "{CRYPT}"+data['password']; // Génération id aléatoire et test contre le LDAP try { - Tools.generateId(ldapConfig.group["idNumber"], "gr").then(id => { vals2[ldapConfig.group['idNumber']]=id; }); + Tools.generateId(ldapConfig.group["idNumber"], "group").then(id => { vals2[ldapConfig.group['idNumber']]=id; }); } catch(err) { throw "Erreur lors de la génération d'un id numérique pour créer un nouveau groupe."; } - // FOIREUX : Hypothèse sur la structure du reste des données mais évite un test.assurerUnicite à deux variables - vals2[ldapConfig.group['idNumber2']]=vals2[ldapConfig.group['idNumber']]; - - // Stockage machine ; dépend du prénom - vals2[ldapConfig.group['directory']] = '/hosting/groups/'+gid; - - // Code root - vals2[ldapConfig.group['cleanFullName']]=data['name'].replace(':', ';').toLowerCase().normalize('UFD'); - - // Adressage root - vals2[ldapConfig.group['login']] = "/sbin/nologin"; - - // Permissions BR - vals2[ldapConfig.group['readPerm']] = '!*'; - vals2[ldapConfig.group['writePerm']] = '!*'; // Inscription des valeurs calculées par effet de bord - if (!await Basics.change("gr", gid, "add", vals2)) { + if (!await Basics.change("group", gid, "add", vals2)) { throw "Erreur lors de l'ajout des valeurs intelligentes du nouveau groupe."; } - ["posixAccount", "posixGroup", "brAccount"].forEach(cst => { + ["posixGroup", "brGroup"].forEach(cst => { let vals3={}; vals3[ldapConfig.group['classes']]=cst; - Basics.change("gr", gid, "add", vals3).then(res => { - if (!res) { throw "Erreur lors de l'ajout des valeurs constantes du nouveau groupe."; } + Basics.change("group", gid, "add", vals3).then(res => { + if (!res) throw "Erreur lors de l'ajout des valeurs constantes du nouveau groupe."; + }); }); + + // Ajout groupes parents et fils + for (let rel of ["childs","parents"]) { + data[rel].forEach(gid => { + let tmp = ldapConfig.group[rel]; + Basics.change("group", gid, "add", { tmp: gid }).then(res => { + if (!res) throw "Erreur de l'ajout d'un groupe associé au nouveau groupe."; + }); }); - }); + } // Utilisation des fonctions adaptées pour assurer la cohérence de l'ensemble - data['members'].forEach(uid => { - Group.addMember(uid, gid).then(res => { - if (!res) { throw "Erreur de l'ajout d'un membre au groupe."; } - }); - }); - data['admins'].forEach(uid => { - Group.addAdmin(uid, gid).then(res => { - if (!res) { throw "Erreur de l'ajout d'un admin au groupe."; } + for (let cat of categories) { + for (let uid of data[cat]) Tools.add(uid, gid, cat).then(res => { + if (!res) throw "Erreur de l'ajout d'un membre au nouveau groupe."; }); - }); + } return true; } @@ -338,7 +245,7 @@ export class Group { * @memberof LDAP * @summary Fonction qui supprime un groupe du LDAP. * @desc Cette fonction commence par gérer les groupes du membre puis le supprime entièrement. A modifier une fois que le LDAP incluerait les groupes administres par une utilisateur. - * Appelle {@link LDAP.clear} bien sûr, mais aussi {@link Group.remMember} et {@link Group.remAdmin} pour gérer les groupes de l'utilisateur sortant. + * Appelle {@link LDAP.clear} bien sûr, mais aussi {@link Tools.remove} pour gérer les groupes de l'utilisateur sortant. * @arg {string} gid - gid de la victime * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async @@ -346,30 +253,11 @@ export class Group { */ static async delete(gid: string): Promise<boolean> { try { - // Gestion des administrateur et membres d'abord - let profil = await Group.peek(gid); - // Modification du profil de chaque utilisateur - profil[ldapConfig.group['member']].forEach(async function quickPartRemUser(uid: string) { - // Modification des profils de tous les utilisateurs - let lg = await Tools.getGroups(uid); - // Vérifie que l'utilisateur est pas déjà viré pour users - if (lg.includes(gid)) { - // Supprime tous les groupes - if (!await Basics.change("us", uid, "del", ldapConfig.user.groups)) { - throw "Erreur lors de la suppression de tous les groupes du membre."; - } - // Les rajoute un par un, sauf pour le supprimé - lg.forEach(id => { - if (id!=gid) { - Group.addMember(uid, id).then(res => { - if (!res) { throw "Erreur lors du ré-ajout des autres groupes"; } - }); - } - }); - } - }); + // Gestion des catégories en bloc d'abord + let profile = await Group.peek(gid); + for (let cat of categories) profile[ldapConfig.group[cat]].forEach(uid => Tools.remove(uid, gid, cat)); // Elimination - if (!await Basics.clear("gr",gid)) { throw "Erreur lors de la suppression de la feuille dans l'arbre des groupes."; } + if (!await Basics.clear("group",gid)) throw "Erreur lors de la suppression de la feuille dans l'arbre des groupes."; return true; } catch(err) { @@ -388,7 +276,7 @@ export class Group { */ static async edit(data: groupData) : Promise<boolean> { try { - return Tools.edit("gr",data); + return Tools.edit("group",data); } catch(err) { throw "Erreur lors de la modification d'un groupe."; diff --git a/src/ldap/export/user.ts b/src/ldap/export/user.ts index b50f668b223274b1a78734d7504357ea9488378b..c9c4b8d1ab9b16afbe83d6305ac9c7dc11abc1a3 100644 --- a/src/ldap/export/user.ts +++ b/src/ldap/export/user.ts @@ -1,67 +1,19 @@ /** * @file Ce fichier contient la classe de l'API du LDAP qui gère les opérations sur les groupes. Elle est destinée à être exportée pour être utilisée par les resolvers. * @author hawkspar + * @memberof LDAP */ -import {ldapConfig} from '../internal/config'; +import { ldapConfig, userData, categories } from '../internal/config'; import {Basics} from '../internal/basics'; import {Tools} from '../internal/tools'; -import {Group} from './group'; - -/** - * @interface userData - * @desc Interface avec toutes les données extractables pour un utilisateur. - * @var {string} uid - Identifiant utilisateur - * @var {string} givenName - Prénom - * @var {string} lastName - Nom - * @var {string} nickname - Surnom - * @var {string} photo - Bytestring de la photo de l'utilisateur - * @var {string} birthdate - Date d'anniversaire - * TBA @var {string} nationality - Nationalité d'origine - * @var {string} promotion - Année(s) de promo - * @var {string} phone - Numéro(s) de téléphone - * @var {string[]} address - Adresse(s) - * @var {string[]} mail - Adresse(s) courriel - * @var {string[]} groups - Un ou plusieurs groupes dont l'utilisateur est membre (inclus section sportive, binet, PA...) - * @var {string} password - Mot de passe généré en amont - * @var {string[]} ips - Adresse(s) ip - * @var {string} directory - Adresse soft des données utilisateurs - * @var {string} login - Astuce de root flemmard - * @arg {string} readPerm - Permissions spéciales BR - * @var {string} writePerm - Permissions spéciales BR - * @var {string[]} forlifes - Alias BR (attention le filtre .fkz n'est plus fonctionnel) - * @var {string[]} admins - Liste des gid dont l'utilisateur est admin ; supposé sous-liste de groups - * TBA @var {string[]} likes - Liste des gid dont l'utilisateur est sympathisant - */ -export interface userData { - uid?: string, - groups?: string[], - groupsIsAdmin?: string[], - password?: string, - givenName?: string, - lastName?: string, - nickname?: string, - promotion?: string, - photo?: string, - birthdate?: string, - nationality?: string, - phone?: string, - address?: string, - mail?: string, - ips?: string[], - directory?: string, - login?: string, - readPerm?: string, - writePerm?: string, - forlifes?: string[], - sport?: string - //"likes"?: string[] -} //------------------------------------------------------------------------------------------------------------------------ // Classes à exporter TBT //------------------------------------------------------------------------------------------------------------------------ +export {userData}; + export class User { /** * @memberof LDAP @@ -82,7 +34,9 @@ export class User { */ static async peek(uid: string) : Promise<userData> { try { - return Tools.peek<userData>("us", uid); + let data = await Tools.peek<userData>("user", uid, userData); + for (let cat of categories) data[cat] = data[cat].map(dn => dn.split(',')[0].split('=')[1]); + return data; } catch(err) { throw "Error while peeking a user."; @@ -102,7 +56,7 @@ export class User { */ static async search(data: userData) : Promise<string[]> { try { - return Tools.search("us", data); + return Tools.search("user", data); } catch(err) { throw "Erreur lors de la recherche approximative d'un utilisateur."; @@ -112,9 +66,9 @@ export class User { /** * @memberof LDAP * @summary Fonction qui créé un nouvel utilisateur dans le LDAP. - * @desc Appelle {@link LDAP.add} bien sûr, mais aussi {@link Group.addMember} et {@link Group.addAdmin} pour gérer les groupes du nouvel utilisateur. - * @arg {fullUserData} data - Dictionnaire des informations utilisateurs. Des erreurs peuvent apparaître si tous les champs ne sont pas remplis. - * Cette application ne permet pas de rejoindre des groupes. + * @desc Appelle {@link LDAP.add} bien sûr, mais aussi {@link Tools.add} pour gérer les groupes du nouvel utilisateur. + * @arg {userData} data - Dictionnaire des informations utilisateurs. Des erreurs peuvent apparaître si tous les champs ne sont pas remplis. + * Cette application permet de rejoindre des groupes en masse pour toute catégorie, à la fois façon Sigma et CAS. * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async * @static @@ -126,90 +80,60 @@ export class User { // uid de base généré à partir de nom et prénom, plus potentiellement promo et un offset // MEF mélange de Promise et de fonction standard try { - Tools.generateUid(data['givenName'],data['lastName'],data['promotion']).then(id => { vals[ldapConfig.key_id]=id; } ); + Tools.generateUid("user",data['givenName'],data['lastName'],data['birthdate']).then(id => { vals[ldapConfig.user.uid]=id; } ); } catch(err) { throw "Erreur lors de la génération d'un hruid pour un nouvel utilisateur."; } - let uid = vals[ldapConfig.key_id]; + let uid : string = vals[ldapConfig.user.uid]; // Génère une erreur si un champ n'est pas rempli - for (let key_att in data) { + for (let key_att of ["givenName","lastName","nickname","gender","photo","phone","adress","mail","birthdate","nationality"]) { // Ecriture de toutes les valeurs uniques - if (!Array.isArray(data[key_att])) { vals[ldapConfig.user[key_att]]=data[key_att]; } + if (data[key_att] != undefined) vals[ldapConfig.user[key_att]]=data[key_att]; } // Appel à la fonction de base - if (!await Basics.add("us", vals)) { throw "Erreur de l'ajout de la feuille à l'arbre utilisateur."; } - - for (let key_att in data) { - // Modifications multiples pour avoir plusieurs champs de même type ; boucle sur les attributs multiples - if (Array.isArray(data[key_att])) { - // On rajoute chaque valeur en entrée - data[key_att].forEach(val => { - let vals2 = {}; - vals2[ldapConfig.user[key_att]]=val; - Basics.change("us", uid, "add", vals2).then(res => { - if (!res) { throw "Erreur lors de l'ajout d'une valeur pour un champ à valeurs multiples à la feuille du nouvel utilisateur."; } - }); - }); - } - } + if (!await Basics.add("user", vals)) throw "Erreur de l'ajout de la feuille à l'arbre utilisateur."; // Certains champs nécessitent de petits calculs let vals3={}; - // Création d'un nom complet lisible - vals3[ldapConfig.user['fullName']]=data['givenName']+' '+data['lastName'].toUpperCase(); - // ldapConfiguration du mot de passe utilisateur // Le préfixe {CRYPT} signifie que le mdp est hashé dans OpenLDAP voir : https://www.openldap.org/doc/admin24/security.html vals3[ldapConfig.user['password']] = "{CRYPT}"+data['password']; // Ecriture d'un surnom s'il y a lieu - if ((data['nickname']!=undefined) && (data['nickname']!='')) { - vals3[ldapConfig.user['nickname']]=data['nickname']; - } + if ((data['nickname']!=undefined) && (data['nickname']!='')) vals3[ldapConfig.user['nickname']]=data['nickname']; try { // Génération id aléatoire unique - vals3[ldapConfig.user['id']]= await Tools.generateId(ldapConfig.user['id'], "us"); + vals3[ldapConfig.user['id']]= await Tools.generateId(ldapConfig.user['id'], "user"); } catch(err) { throw "Erreur lors de la génération d'un id numérique pour un nouvel utilisateur."; } - - // Stockage machine ; dépend du prénom - vals3[ldapConfig.user['directory']] = '/hosting/users/' + data['givenName'][0]; // Code root vals3[ldapConfig.user['cleanFullName']]=data['fullName'].replace(':', ';').toLowerCase().normalize('UFD'); - - // Adressage root - if (data['groups'].includes("on_platal")) { vals3[ldapConfig.user['login']] = "/bin/bash"; } - else { vals3[ldapConfig.user['login']] = "/sbin/nologin"; } - - // Permissions BR - vals3[ldapConfig.user['readPerm']] = 'br.*,public.*'; - if (data['readPerm'].length>0) { vals3[ldapConfig.user['readPerm']] += ',' + data['readPerm']; } - vals3[ldapConfig.user['writePerm']] = 'br.*,!br.blague-du-jour,public.*,!br.campagnekes'; - if (data['writePerm'].length>0) { vals3[ldapConfig.user['readPerm']] += ',' + data['writePerm']; } - - // Valeur nécessaire ASKIP mais inutile - vals3[ldapConfig.user['idNum']] ='5000'; // Inscription des valeurs calculées - if (!await Basics.change("us", uid, "add", vals3)) { - throw "Erreur lors de l'ajout des valeurs calculées à la feuille du nouvel utilisateur."; - } + if (!await Basics.change("user", uid, "add", vals3)) throw "Erreur lors de l'ajout des valeurs calculées à la feuille du nouvel utilisateur."; - ["posixAccount", "shadowAccount", "inetOrgPerson", "brAccount"].forEach(cst => { + ["posixAccount", "shadowAccount", "brUser"].forEach(cst => { let val3={}; vals3[ldapConfig.user['class']]=cst; - Basics.change("us", uid, "add", vals3).then(res => { - if (!res) { throw "Erreur lors de l'ajout d'une valeur constante à la feuille du nouvel utilisateur."; } + Basics.change("user", uid, "add", vals3).then(res => { + if (!res) throw "Erreur lors de l'ajout d'une valeur constante à la feuille du nouvel utilisateur."; }); }); + + // Ajout dans les groupes à la catégorie voulue + for (let cat of categories) { + for (let gid of data[cat]) Tools.add(uid, gid, cat).then(res => { + if (!res) throw "Erreur de l'ajout d'un membre au nouveau groupe."; + }); + } return true; } @@ -221,7 +145,7 @@ export class User { * @memberof LDAP * @summary Fonction qui supprime un utilisateur du LDAP. * @desc Cette fonction commence par gérer les groupes du membre puis le supprime entièrement. - * Appelle {@link LDAP.clear} bien sûr, mais aussi {@link Group.remMember} et {@link Group.remAdmin} pour gérer les groupes de l'utilisateur sortant. + * Appelle {@link LDAP.clear} bien sûr, mais aussi {@link Tools.remove} pour gérer les groupes de l'utilisateur sortant. * @arg {string} uid - uid de la victime * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async @@ -229,34 +153,15 @@ export class User { */ static async delete(uid: string): Promise<boolean> { try { - // Gestion des groupes d'abord + // Gestion des groupes de l'utilisateur d'abord let profil = await User.peek(uid); - profil[ldapConfig.user['groups']].forEach(async function (gid: string) { - // Si l'utilisateur était admin, l'enlever - Group.remAdmin(uid, gid); - // Enlever de la liste des membres - let lm = await Tools.getMembers(gid); - if (lm.includes(uid)) { - // Supprime tous les membres - if (!await Basics.change("gr", gid, "del", ldapConfig.group.members)) { - throw "Erreur lors de la suppression de tous les membres du groupe."; - } - // Les rajoute un par un, sauf pour le supprimé - lm.forEach(id => { - if (id!=uid) { - Group.addMember(id, gid).then(res => { - if (!res) { throw "Erreur lors du ré-ajout d'un autre membre"; } - }); - } - }); - } - }); + for (let cat of categories) profil[ldapConfig.user[cat]].forEach(gid => Tools.remove(uid, gid, cat)); } catch(err) { throw "Erreur lors de l'obtention des informations de l'utilisateur à supprimer."; } - // Elimination - if (!Basics.clear("us", uid)) { throw "Erreur lors de la suppression de l'utilisateur."; } + // Elimination pure et simple + if (!Basics.clear("user", uid)) throw "Erreur lors de la suppression de l'utilisateur."; return true; } @@ -271,7 +176,7 @@ export class User { */ static async edit(data : userData) : Promise<boolean> { try { - return Tools.edit("us",data); + return Tools.edit("user",data); } catch(err) { throw "Erreur lors de la modification d'un utilisateur."; diff --git a/src/ldap/internal/basics.ts b/src/ldap/internal/basics.ts index b96736d52a7376356c2580e6cc5b3194b12b0717..089d74b60c164ba72d1360c881b11242972090a6 100644 --- a/src/ldap/internal/basics.ts +++ b/src/ldap/internal/basics.ts @@ -4,6 +4,7 @@ * Toutes les fonctions écrites ici sont asynchrones et renvoient des Promises ce qui nécessite de les appeler avec la synthaxe * un peu particulière `f(args).then(res => ...)` pour exploiter leur résultat. * @author hawkspar + * @memberof LDAP */ import ldap from 'ldapjs'; @@ -17,7 +18,7 @@ var client = ldap.createClient({ url: ldapConfig.server}); // Interface pratique pour que Typescript comprenne ce qu'est un dictionnaire simple interface dic { - [Key: string]: string; + [Key: string]: string | string[]; } //------------------------------------------------------------------------------------------------------------------------ @@ -26,9 +27,9 @@ interface dic { export class Basics { /** + * @memberof LDAP * @class Basics * @classdesc Cette classe est la brique de base du fichier tout entier puisqu'elle contient les functions qui agissent directement sur le LDAP. - * @memberof LDAP * @summary Constructeur vide. */ constructor() {} @@ -80,6 +81,7 @@ export class Basics { /** + * @memberof LDAP * @callback entryHandler * @arg entry {*} - Convoluted ldap.js search result object */ @@ -98,30 +100,37 @@ export class Basics { * @static * @async */ - static search(domain: 'gr'|'us', attributes: string[], id: string, filter: string, handler : (entry: any) => void) : void { - Basics.adminBind(); + static search(domain: 'group'|'user', attributes: string[], id: string, filter: string, handler : (entry: any) => void) : Promise<void> { let dn =""; - if (id != null) { dn+=ldapConfig.key_id+'='+id+','; } - if (domain == "gr") { dn+=ldapConfig.dn_groups; } - else { dn+=ldapConfig.dn_users; } + if (id != null) { + if (domain == "group") dn += ldapConfig.group.gid; + else dn += ldapConfig.user.uid; + dn += '=' + ldapEscape.dn("${txt}", { txt: id }) + ','; + } + dn+=ldapConfig.dn[domain]; + console.log("Searching dn= " + dn + ", filter : " + filter); // Interrogation LDAP selon filter - client.search(ldapEscape.dn("${txt}", { txt: dn}), { // Must be escaped in case of a malignious false id - "scope": "sub", - "filter": ldapEscape.filter("${txt}", { txt: filter}), // Must be escaped in case of a malignious search arg - "attributes": attributes - }, (err, res) => { - // Gestion erreur ; pb car pas simple true / autre en sortie - if (err) { - throw "Erreur lors de la recherche sur le LDAP."; - } else { - // Dès que la recherche renvoit une entrée, on stocke les attributs qui nous intéresse - res.on('searchEntry', entry => { handler(entry); }); - // Si la recherche renvoie une erreur, on renvoit - res.on('error', resErr => { throw resErr; }); - // Quand la recherche est finie on se déconnecte - res.on('end', _ => { Basics.unbind(); }); - } + let promise = new Promise<void>(function(resolve, reject) { + client.search(dn, { // Must be escaped in case of a malignious false id + "scope": "sub", + "filter": filter, // Must be escaped in case of a malignious search arg + "attributes": attributes + }, (err, res) => { + // Gestion erreur ; pb car pas simple true / autre en sortie + if (err) { + throw "Erreur lors de la recherche sur le LDAP."; + } else { + // Dès que la recherche renvoit une entrée, on stocke les attributs qui nous intéresse + res.on('searchEntry', entry => handler(entry)); + // Si la recherche renvoie une erreur, on renvoit + res.on('error', resErr => { throw resErr; }); + // Quand la recherche est finie on se déconnecte + res.on('end', _ => resolve()); + } + }); }); + + return promise; } /** @@ -137,10 +146,11 @@ export class Basics { * @static * @async */ - static async searchSingle(domain: 'gr'|'us', attribute: string, id: string=null, filter: string="(objectClass=*)") : Promise<string[]> { + static async searchSingle(domain: 'group'|'user', attribute: string, id: string=null, filter: string="(objectClass=*)") : Promise<string[]> { let vals=[]; - Basics.search(domain, [attribute], id, filter, entry => { + await Basics.search(domain, [attribute], id, filter, entry => { // Cas un seul attribut où le résultat est une liste directement + console.log("searchSingle found " + entry.object[(domain == 'group' ? ldapConfig['group']['gid'] : ldapConfig['user']['uid'])]); vals.push(entry.object[attribute]); }); return vals; @@ -160,25 +170,23 @@ export class Basics { * @static * @async */ - static async searchMultiple(domain: 'gr'|'us', attributes: string[], id: string=null, filter: string="(objectClass=*)") : Promise<Array<dic>> { + static async searchMultiple(domain: 'group'|'user', attributes: string[], id: string=null, filter: string="(objectClass=*)") : Promise<Array<dic>> { let vals=[]; - Basics.search(domain, attributes, id, filter, entry => { + await Basics.search(domain, attributes, id, filter, entry => { // Cas plusieurs attributs donc résultat dictionnaire vals.push({}); - attributes.forEach(attribute => { - vals.slice(-1)[0][attribute]=entry.object[attribute]; - }); + console.log("searchMultiple found " + entry.object[(domain == 'group' ? ldapConfig['group']['gid'] : ldapConfig['user']['uid'])]); + attributes.forEach(attribute => vals.slice(-1)[0][attribute]=entry.object[attribute]); }); return vals; } - //TBT /** * @memberof LDAP * @summary Fonction qui permet de modifier un élément sur le LDAP. Gestion intelligente de l'appartenance à un binet. * @desc Cette fonction traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode modify). * @arg {'gr'|'us'} domain - Emplacement de la requête (groupe ou utilisateur) - * @arg {string} id - Identifiant unique de la feuille à modifier + * @arg {string} id - Identifiant unique de la feuille à modifier ; passé par ldapEscape dans cette fonction * @arg {"add"|"del"|"replace"} op - Operation à réaliser sur le LDAP. Trois opération sont possibles ; "add", qui rajoute des attributs et qui peut créer des doublons, * "del" qui en supprime, et "replace" qui remplace du contenu par un autre. * @arg {dic} mod - Dictionnaire contenant les attributs à modifier et les nouvelles valeurs des attributs. @@ -187,70 +195,70 @@ export class Basics { * @static * @async */ - static async change(domain: 'gr'|'us', id: string, op: "add"|"del"|"replace", mod: dic) : Promise<boolean> { - Basics.adminBind(); - let dn = ldapConfig.key_id+'='+id+',' - if (domain == "gr") { dn+=ldapConfig.dn_groups } - else { dn+=ldapConfig.dn_users } + static async change(domain: 'group'|'user', id: string, op: "add"|"del"|"replace", mod: dic) : Promise<boolean> { + let dn = ""; + if (domain == 'group') dn += ldapConfig.group.gid; + else dn += ldapConfig.user.uid; + dn+='='+ldapEscape.dn("${txt}", { txt: id })+','+ldapConfig.dn[domain]; // Modification LDAP selon dn fourni en argument (pourrait prendre une liste de Changes) client.modify(ldapEscape.dn("${txt}", {txt: dn}), new ldap.Change({ operation: op, modification: mod, // Gestion erreur - }), err => { - throw "Erreur lors d'une opération de modification sur le LDAP."; - }); - Basics.unbind(); + }), err => { throw "Erreur lors d'une opération de modification sur le LDAP."; }); return true; } - //TBT /** * @memberof LDAP * @summary Fonction qui permet de rajouter un élément sur le LDAP. * @desc Cette fonction traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode add). + * On notera le rôle particulier de vals[uid/gid] qui sert à identifier la feuille à changer ; passé par ldapEscape dans cette fonction. * @arg {'gr'|'us'} domain - Emplacement de la requête (groupe ou utilisateur) - * @arg {Object.<string, string>} vals - Dictionnaire contenant les valeurs à créer (contient un champ en ldapConfig.key_id) + * @arg {Object.<string, string>} vals - Dictionnaire contenant les valeurs à créer (contient un champ en ldapConfig) * @arg {Object} vals[key] - Nouvelle valeur pour le champ key * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon. * @static * @async */ - static async add(domain: 'gr'|'us', vals) : Promise<boolean> { - Basics.adminBind(); - let dn = ldapConfig.key_id+"="+vals[ldapConfig.key_id]; - if (domain == "gr") { dn+=ldapConfig.dn_groups; } - else { dn+=ldapConfig.dn_users; } + static async add(domain: 'group'|'user', vals) : Promise<boolean> { + let dn = ""; + if (domain == "group") dn += ldapConfig.group.gid+"="+ldapEscape.dn("${txt}", { txt: vals[ldapConfig.group.gid] }); + else dn += ldapConfig.user.uid+"="+ldapEscape.dn("${txt}", { txt: vals[ldapConfig.user.uid] }); + dn += ldapConfig.dn[domain]; // Ajout LDAP selon la ldapConfiguration en argument - client.add(ldapEscape.dn("${txt}", { txt: dn}), vals, err => { + client.add(ldapEscape.dn("${txt}", { txt: dn }), vals, err => { throw "Erreur lors d'une opération d'ajout sur le LDAP."; }); - Basics.unbind(); return true; } - //TBT /** * @memberof LDAP * @summary Fonction qui permet de supprimer une feuille du LDAP. * @desc Cette fonction traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode del). * Elle est différente de modify avec "del" car elle affecte directement une feuille et pas un attribut. * @arg {'gr'|'us'} domain - Emplacement de la requête (groupe ou utilisateur) - * @arg {string} id - Identifiant unique de la cible + * @arg {string} id - Identifiant unique de la cible, passé par ldapEscape dans cette fonction * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @static * @async */ - static async clear(domain: 'gr'|'us', id: string) : Promise<boolean> { - Basics.adminBind(); - let dn = ldapConfig.key_id+'='+id+',' - if (domain == "gr") { dn+=ldapConfig.dn_groups; } - else { dn+=ldapConfig.dn_users; } + static async clear(domain: 'group'|'user', id: string) : Promise<boolean> { + let dn = ""; + if (domain == "group") dn += ldapConfig.group.gid+"="+ldapEscape.dn("${txt}", { txt: id }); + else dn += ldapConfig.user.uid+"="+ldapEscape.dn("${txt}", { txt: id }); + dn+=ldapConfig.dn[domain]; // Suppression LDAP client.del(ldapEscape.dn("${txt}", {txt: dn}), err => { throw "Erreur lors d'une opération de suppression sur le LDAP."; }); - Basics.unbind(); return true; } -} \ No newline at end of file +} + +// Bind +Basics.unbind(); +Basics.adminBind(); + +console.log("Binding with LDAP client completed successfully, looking good !"); \ No newline at end of file diff --git a/src/ldap/internal/config.ts b/src/ldap/internal/config.ts index bd628a3d9286458a43b867d92620923aa31c03be..3b00495644370c4c05267190703c4a55afb2af8d 100644 --- a/src/ldap/internal/config.ts +++ b/src/ldap/internal/config.ts @@ -5,25 +5,117 @@ /** * @file Importe la configuration du LDAP au sein de l'application, et remplace certaines valeurs en fonction des variables d'environnement. + * @author hawkspar * @memberof LDAP - * @author manifold, hawkspar */ import fs from 'fs'; import path from 'path'; import colors from 'colors'; +import dotenv from 'dotenv'; + +// Chargement de l'environnement +let path_env = path.resolve(__dirname, '..', '..', '..', './.env'); +console.log(colors.red("Loading .env config file from "+path_env)); +dotenv.config({ path: path_env }); + // Point central ; tous les champs de la BDD sont 'cachés' dans config.json et pas visibles directement -let path_config = path.resolve(__dirname,'..', '..', '..', 'ldap_config.json'); +let path_config = path.resolve(__dirname, '..', '..', '..', './ldap_config.json'); console.log(colors.cyan("Loading LDAP config file from "+path_config)); export const ldapConfig = JSON.parse(fs.readFileSync(path_config).toString()); -let path_credentials = path.resolve(__dirname,'..', '..', '..', 'ldap_credentials.json'); -console.log(colors.cyan("Loading LDAP credentials from "+path_credentials)); -export const credentialsLdapConfig = JSON.parse(fs.readFileSync(path_credentials).toString()); + // Override config server from environment -if (process.env.LDAP_URI != null) { - ldapConfig.server = process.env.LDAP_URI; -} +if (process.env.LDAP_URI != null) ldapConfig.server = process.env.LDAP_URI; else { - if (process.env.TARGET_ENV == `production`) { ldapConfig.server = ldapConfig.server_prod; } - else { ldapConfig.server = ldapConfig.server_dev; } + if (process.env.TARGET_ENV == `production`) ldapConfig.server = ldapConfig.server_prod; + else ldapConfig.server = ldapConfig.server_dev; +} + +// Gestion des super-identifiants +let path_credentials = path.resolve(__dirname, '..', '..', '..', 'ldap_credentials.json'); +console.log(colors.green("Loading LDAP credentials from "+path_credentials)); +export const credentialsLdapConfig = JSON.parse(fs.readFileSync(path_credentials).toString()); + +// Data formats and useful constants +export const categories = ["admins","speakers","members","followers"]; + +/** + * @memberof LDAP + * @class partUserData + * @desc Interface avec les données visibles au mponde extérieur. + * @var {string} uid - Identifiant utilisateur + * @var {string} givenName - Prénom + * @var {string} lastName - Nom + * @var {string?} gender - Sexe + * @var {string?} photo - Bytestring de la photo de l'utilisateur + * @var {string?} address - Adresse(s) + * @var {string[]} admins - Liste des gid (group id, inclus section sportive, binet, PA...) dont l'utilisateur est admin ; pas forcément sous-liste de members + * @var {string[]} speakers - Liste des gid dont l'utilisateur est porte-parole ; pas forcément sous-liste de members + * @var {string[]} members - Liste des gid dont l'utilisateur est membre + * @var {string[]} followers - Liste des gid dont l'utilisateur est sympathisant + */ +export class partUserData { + uid: string; + givenName: string; + lastName: string; + gender?: 'M'|'F'|'U'; + photo?: string; + address?: string; + admins: string[] = []; + speakers: string[] = []; + members: string[] = []; + followers: string[] = []; +} + +/** + * @memberof LDAP + * @class userData + * @desc Interface avec toutes les données extractables pour un utilisateur. + * @var {string?} password - Mot de passe (jamais transmis en clair) + * @var {string?} nickname - Surnom + * @var {string?} phone - Numéro(s) de téléphone + * @var {string?} mail - Adresse(s) courriel + * @var {string} birthdate - Date d'anniversaire + * @var {string} nationality - Nationalité d'origine + */ +export class userData extends partUserData { + nickname?: string; + password?: string; + phone?: string; + mail?: string; + birthdate: string; + nationality?: string; +} + +/** + * @memberof LDAP + * @class groupData + * @var {string} gid - Identifiant du groupe + * @var {string?} password - Mot de passe du groupe + * @var {string} name - Nom du groupe (souvent son nom mais pas nécessairement) + * @var {string?} logo - Logo du groupe (en bytestring) + * @var {string?} description - Description du groupe (script Markdown) + * @var {string?} site - Site web du groupe (URL) + * @var {string} category - Statut du groupe ; binet, section sportive... (actuellement juste 'binet' ou 'free') + * @var {string[]} parents - Liste des groupes directement parents de celui-ci + * @var {string[]} childs - Liste des groupes directement enfants de celui-ci + * @var {string[]} admins - Liste des admins du groupe + * @var {string[]} speakers - Liste des porte-parole du groupe + * @var {string[]} members - Liste des membres du groupe + * @var {string[]} followers - Liste des sympathisants du groupe + */ +export class groupData { + gid: string; + password?: string; + name: string; + logo?: string; + description?: string; + site?: string; + category: string; + parents: string[] = []; + //childs: string[] = []; + admins: string[] = []; + speakers: string[] = []; + members: string[] = []; + followers: string[] = []; } \ No newline at end of file diff --git a/src/ldap/internal/tools.ts b/src/ldap/internal/tools.ts index cb7912224c14f5fd13278897ed54052103dc7242..cb5b6b6baf29c65d0d1d4c51ca6e838f27a2a20d 100644 --- a/src/ldap/internal/tools.ts +++ b/src/ldap/internal/tools.ts @@ -1,12 +1,14 @@ /** * @file Ce fichier regroupe les fonctions génériques de recherche et de test utiles, mais trop puissantes pour être exportées directement. * @author hawkspar + * @memberof LDAP */ -import {ldapConfig} from './config'; +// Toutes les entrées utilisateur sont escapées par sécurité +import ldapEscape from 'ldap-escape'; +// Imports internes +import { ldapConfig, userData, groupData } from './config'; import {Basics} from './basics'; -import {userData} from '../export/user'; -import {groupData} from '../export/group'; //------------------------------------------------------------------------------------------------------------------------ // Fonctions intermédiaires TBT @@ -20,11 +22,11 @@ export class Tools { * @summary Constructeur vide. */ constructor() {} - + /** * @memberof LDAP * @summary Fonction qui renvoit toutes les infos relatives à un groupe ou un utilisateur particulier. - * @desc Cette fonction utilise {@link LDAP.search} avec des attributs prédéfinis. + * @desc Cette fonction utilise {@link LDAP.search} avec des attributs prédéfinis. Elle est naïve et n'opère pas de récursion. * @param T - Format renvoyé (en pratique {@link userData} ou {@link groupData}) * @arg {string} domain - Domaine de la recherche (utilisateur ou groupe) * @arg {string} id - Identifiant de la feuille cherchée (uid ou gid) @@ -32,28 +34,29 @@ export class Tools { * @static * @async */ - static async peek<T>(domain: 'us'|'gr', id: string) : Promise<T> { - if (domain='gr') { - var dirtyKeys = ldapConfig.group; - } - else { - var dirtyKeys = ldapConfig.user; - } - let cleanData : T; - let dirtyData = await Basics.searchMultiple(domain, dirtyKeys.values(), id)[0]; - // Rename output - for (let uncleanKey in dirtyData) { - for (let cleanKey in cleanData) { - if (uncleanKey=dirtyKeys[cleanKey]) { cleanData[cleanKey] = dirtyData[uncleanKey]; } + static async peek<T>(domain: 'user'|'group', id: string, type: new () => T) : Promise<T> { + // Utrilisation du tableu d'équivalence dans le fichier de configuration + let map = ldapConfig[domain]; + let cleanKeys = Object.keys(map); + let dirtyKeys = cleanKeys.map(key => map[key]); + + // Création de la structure de données renvoyée + let cleanData: T = new type(); + let dirtyData = (await Basics.searchMultiple(domain, dirtyKeys, id))[0]; + // Renommage des clés + for(let cleanKey of cleanKeys) { + let val = dirtyData[map[cleanKey]]; + if (val !== undefined) { + if (Array.isArray(cleanData[cleanKey]) && !Array.isArray(val)) val = [val]; + cleanData[cleanKey] = val; } } return cleanData; } - /** * @memberof LDAP - * @summary Fonction qui retrouve les id des paxs ou groupes validant les critères de recherche. Etape vers vrai TOL (Trombino On Line). + * @summary Fonction qui retrouve les ids des paxs ou groupes validant les critères de recherche. Etape vers vrai TOL (Trombino On Line). * Utiliser {@link peekUser} au cas par cas après pour obtenir les vraies infos. * @desc Cette fonction utilise {@link LDAP.search} mais avec un filtre généré à la volée. Accepte des champs exacts ou incomplets pour la plupart des champs * mais pas approximatifs et ne gère pas l'auto-complete. MEF Timeout pour des recherches trop vagues. Va crasher si un champ n'est pas dans ldapConfig. @@ -66,28 +69,31 @@ export class Tools { * @static * @async */ - static async search(domain : "us"|"gr", data : userData|groupData) : Promise<string[]> { + static async search(domain: "user"|"group", data: userData|groupData) : Promise<string[]> { let filter=""; // Iteration pour chaque champ, alourdissement du filtre selon des trucs prédéfinis dans ldapConfig encore - for (var key in data) { - if ((data[key]!= undefined) && (data[key] != '')) { // Si il y a qque chose à chercher pour ce filtre - if (!Array.isArray(data[key])) { data[key]=[data[key]]; } // Génération systématique d'une liste de valeurs à rechercher + for (var key in ldapConfig[domain]) { + if ((data[key]!= undefined) && (data[key] != '')) { // Si il y a qque chose à chercher pour ce filtre + if (!Array.isArray(data[key])) data[key]=[data[key]]; // Génération systématique d'une liste de valeurs à rechercher // Iteration pour chaque valeur fournie par l'utilisateur data[key].forEach(val => { // Traduction en language LDAP let attribute = ""; - if (domain="us") { attribute = ldapConfig.user[key]; } - else { attribute = ldapConfig.group[key]; } + attribute = ldapConfig[domain][key]; + // Escape user input + val = ldapEscape.filter("${fil}", { fil: val }); // Creation incrémentale du filtre - filter="(&"+filter+ "(|("+attribute+"="+ val+")"+ // On cherche la valeur exacte - "(|("+attribute+"=*"+val+")"+ // La valeur finale avec des trucs avant ; wildcard * (MEF la wildcart ne marche pas pour tous les attributs) - "(|("+attribute+"=*"+val+"*)"+ // La valeur du milieu avec des trucs avant et après - "("+ attribute+"="+ val+"*)))))"; // La valeur du début avec des trucs après + filter="(&"+filter+ "(|("+attribute+"="+ val+")"+ // On cherche la valeur exacte + "("+attribute+"=*"+val+")"+ // La valeur finale avec des trucs avant ; wildcard * (MEF la wildcart ne marche pas pour tous les attributs) + "("+attribute+"=*"+val+"*)"+ // La valeur du milieu avec des trucs avant et après + "("+ attribute+"="+ val+"*)))"; // La valeur du début avec des trucs après }); } } - // Appel avec filtre de l'espace - return Basics.searchSingle(domain, ldapConfig.key_id, null, filter); + // Appel avec filtre de l'espace + if (domain == "group") var att=ldapConfig.group.gid; + else var att=ldapConfig.user.uid; + return Basics.searchSingle(domain, att, null, filter); } /** @@ -100,228 +106,428 @@ export class Tools { * @async * @static */ - static async edit(domain: "us"|"gr", data: userData|groupData) : Promise<boolean> { - if (domain = "us") { - var id=data['uid']; - var dirtyKeys=ldapConfig.user; - } - else { - var id=data['gid']; - var dirtyKeys=ldapConfig.group; - } + static async edit(domain: "user"|"group", data: userData|groupData) : Promise<boolean> { + if (domain == "user") var id=data['uid']; + else var id=data['gid']; + var dirtyKeys=ldapConfig[domain]; // Rename in an LDAP-friendly way let dirtyData = {}; Object.keys(data).forEach(function(key: string) { // Some values edit can't change - if (!['readPerm','writePerm','groups','groupsIsAdmin','members','admins'].includes(key)) { - dirtyData[dirtyKeys.key]=data[key]; - } + if (![ 'admins','speakers','members','followers', + 'directory','classes','id','cleanFullName'].includes(key)) dirtyData[dirtyKeys.key]=data[key]; }); - return Basics.change(domain,id,"replace",dirtyData); + return Basics.change(domain, id, "replace", dirtyData); } - /** - * @callback changeValueCallback - * @param {string} id - Id à modifier - * @param {number} n - Nombre d'itérations - * @return {string} Nouveau id - */ /** * @memberof LDAP - * @summary Cette fonction teste une valeur d'un attribut (typiquement un identifiant) et le fait évoluer jusqu'à ce qu'il soit unique. - * @desc Librement adapté de Stack Overflow. Appelle {@link LDAP.search} pour vérifier - * qu'il n'y a pas d'autres occurences de cette valeur pour cette attribut - * dans le dn fourni. - * @param {string} value - Valeur de l'attribut (le plus souvent un identifiant) à tester à cette itération - * @param {string} attribute - Attribut à tester - * @param {"gr"|"us"} domain - Domaine dans lequel l'attribut doit être unique - * @param {changeValueCallback} changeValue - Fonction qui prend uniquement en argument l'id courant et - * le nombre d'itérations et qui renvoit la prochaine valeur de l'attribut - * @param {number} n [0] - Nombre d'itérations (à initialiser à 0) - * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié + * @summary Fonction qui retrouve les utilisateurs ou groupes respectivement correspondant à un groupe ou un utilisateur de la même catégorie. + * @desc Cette fonction utilise {@link LDAP.search} et va directement à la feuille de l'utilisateur ou du groupe interrogé. + * Pour autant, elle est moins naïve qu'elle en a l'air. Elle ne gère ni la descente des admins ni la remontée des membres et renvoit une réponse naïve. + * @param {string} id - Identifiant du groupe ou de l'individu à interroger (supposé valide) + * @param {"user"|"group"} domain - Arbre à interroger + * @param {"admins"|"speakers"|"members"|"followers"} category - Catégorie considérée + * @return {Promise(string[])} Liste des id de groupes ou d'utilisateurs de la bonne catégorie associé à l'id * @static * @async */ - static async ensureUnique(value: string, attribute: string, domain: 'gr'|'us', changeValue: (string, number) => string, n: number=0) : Promise<string> { - // Recherche d'autres occurences de l'id + static async get(id : string, domain : "user"|"group", category : string): Promise<string[]> { try { - return Basics.searchSingle(domain, ldapConfig.key_id, null, "("+attribute+"="+value+")").then(function (matches: string[]) { - if (!matches) { throw ""; } - // On renvoit la valeur si elle est bien unique - else if (matches.length=0) { return value; } - // Sinon, on tente de nouveau notre chance avec la valeur suivante - else { return Tools.ensureUnique(changeValue(value, n+1), attribute, domain, changeValue, n+1); } - }); + if (domain == "group") var dirtyId = ldapConfig.group.gid; + else var dirtyId = ldapConfig.user.uid; + dirtyId += "="+ldapEscape.filter("${txt}", { txt: id }) + "," + ldapConfig.dn[domain]; + return await Basics.searchSingle(domain, ldapConfig[domain][category], dirtyId); } catch(err) { - throw "Erreur lors de la recherche d'une valeur pour assurer son unicité."; + throw "Erreur lors d'une recherche générique d'un membre d'une certaine catégorie d'un groupe."; } } - + /** * @memberof LDAP - * @summary Cette fonction génère un uid standard, puis le fait évoluer jusqu'à ce qu'il soit unique. - * @desc Limité à un appel à {@link Tools.ensureUnique} avec les bons paramètres, et quelques opérations sur l'uid pour qu'il soit valide (escape, normalisation). - * @param {string} givenName - Prénom - * @param {string} lastName - Nom - * @param {string} promotion - Année de promotion - * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié - * @static + * @summary Fonction intermédiaire naïve. + * @desc Cette fonction rajoute un utilisateur à un groupe pour un des deux arbres si cette entrée n'était pas déjà présente de façon à ne pas créer de doublon. + * @arg {string} id1 - uid/gid + * @arg {"group"|"user"} domain1 - Arbre concerné pour l'id1 + * @arg {string} id2 - gid/uid + * @arg {"group"|"user"} domain2 - Arbre concerné pour l'id2 + * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné (admin, speaker, member ou follower) + * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async + * @static */ - static async generateUid(givenName: string, lastName: string, promotion: string) : Promise<string> { + static async addIfAbsent(id1: string, domain1: "group"|"user", id2: string, domain2: "group"|"user", category: string): Promise<boolean> { try { - // normalize et lowerCase standardisent le format - return Tools.ensureUnique((givenName+'.'+lastName).toLowerCase().normalize('UFD'), ldapConfig.key_id, "us", (id: string, n: number) => { - if (n=1) { id+='.'+promotion; } // Si prénom.nom existe déjà , on rajoute la promo - else if (n=2) { id+='.'+(n-1).toString(); } // Puis si prénom.nom.promo existe déjà on passe à nom.prenom.promo .1 - else if (n>2) { id+=n; } // Ensuite on continue .123, .1234, etc... - return id; - }); - } - catch(err) { - throw "Erreur lors de l'assurance de l'unicité d'un human readable unique identifier (hruid)."; + // Vérifie que l'utilisateur est pas déjà membre pour groupes + let l = await Tools.get(id1, domain1, category); + var catName = ldapConfig[domain1][category]; + if (!l.includes(id2)) { + // Ajoute l'utilisateur dans la catégorie concernée + if (domain2 == "group") var id = ldapConfig[domain2].gid; + else var id = ldapConfig[domain2].uid; + if (!await Basics.change(domain1, id1, "add", {catName: id+"="+id2+","+ldapConfig.dn[domain2]})) throw "Erreur lors de la modification dans l'arbre "+domain2+" pour ajouter une entrée dans la catégorie voulue."; + } } + catch(err) { throw "Erreur pour obtenir une liste d'entrées d'une catégorie d'un "+domain1+"."; } + return true; } /** * @memberof LDAP - * @summary Cette fonction génère un id lisible, puis le fait évoluer jusqu'à ce qu'il soit unique. - * @desc Limité à un appel à {@link Tools.ensureUnique} avec les bons paramètres, et quelques opérations sur l'uid pour qu'il soit valide (escape, normalisation). - * @param {string} name - Nom - * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié + * @summary Fonction intermédiaire. + * @desc Cette fonction gère les inclusions de droits. Elle ne rajoute pas un admin pour les admins, mais elle le rajoute en tant que speaker. + * Cette fonction agit uniquement sur l'arbre User. + * @arg {string} uid - uid de l'utilisateur à ajouter + * @arg {string} gid - gid du groupe concerné + * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné (admin, speaker, member ou follower) + * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon + * @async * @static + */ + static async addIncluded(uid: string, gid: string, category: string): Promise<boolean> { + var spk = ldapConfig.group.speakers; + var mem = ldapConfig.group.members; + switch (category) { + case "admins": + // Admin => speaker + if (!await Basics.change("user", uid, "add", { spk: ldapConfig.group.gid+"="+gid+","+ldapConfig.dn.group })) throw "Erreur à l'ajout d'un nouvel admin parmi les portes-paroles d'un groupe"; + case "speakers": + // Speaker & admin => member + if (!await Basics.change("user", uid, "add", { mem: ldapConfig.group.gid+"="+gid+","+ldapConfig.dn.group })) throw "Erreur à l'ajout d'un nouvel admin ou porte-parole parmi les membres d'un groupe"; + case "members": + case "followers": + break; + } + return true; + } + + /** + * @memberof LDAP + * @summary Fonction intermédiaire de récursion. + * @desc Cette fonction gère les droits par récursion par une classique Depth First Search. + * Cette fonction agit uniquement sur l'arbre User. + * @arg {string} uid - uid de l'utilisateur à ajouter + * @arg {string} gid - gid du groupe concerné + * @arg {boolean} direction - direction de la recursion + * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async + * @static */ - static async generateReadableId(name: string) : Promise<string> { - try { - // normalize et lowerCase standardisent le format - return Tools.ensureUnique(name.toLowerCase().normalize('UFD'), ldapConfig.key_id, "gr", (id: string, n: number) => { - if (n=1) { id+='.'+n.toString(); } // Si nom existe déjà , on essaie nom.1 - else if (n>1) { id+=n.toString(); } // Ensuite on continue .12, .123, etc... - return id; - }); + static async addDFS(uid: string, gid: string, direction: boolean): Promise<boolean> { + // Cas récursif ascendant (admins) + if (direction) { + var rol = ldapConfig.group.admins; + var tov = ldapConfig.group.childs; } - catch(err) { - throw "Erreur lors de l'assurance de l'unicité d'un human readable unique identifier (hruid)."; + // Cas récursif descendant (membres) + else { + var rol = ldapConfig.group.members; + var tov = ldapConfig.group.parents; + } + // Classic DFS + var to_visit = [gid]; + while (to_visit.length > 0) { + let cur_gid = to_visit.pop(); + Basics.change("user", uid, "add", { rol: ldapConfig.group.gid+"="+cur_gid+","+ldapConfig.dn.group }); + to_visit.concat(await Basics.searchSingle("group", tov, cur_gid)); } + return true; } /** * @memberof LDAP - * @summary Cette fonction teste une valeur dummy (0) pour un identifiant numérique puis le fait évoluer aléatoirement (entre 1 et 100 000) jusqu'à ce qu'il soit unique. - * @param {string} attribut - Intitulé exact de l'id concerné - * @param {"gr"|"us"} domain - Domaine dans lequel l'attribut doit être unique - * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié + * @summary Fonction essentielle qui permet d'ajouter un utilisateur à une catégorie d'un groupe. + * @desc Cette fonction fait essentiellement appel à d'autres fonctions de {@link Tools} ; {@link Tools.addIfNotPresent} et {@link Tools.manageInclusions}. + * Puis elle gère en interne la récursion et utilise {@link LDAP.change} pour cela. + * @arg {string} uid - Identifiant du futur membre + * @arg {string} gid - Identifiant du groupe + * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné (admin, speaker, member ou follower) + * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon + * @async * @static + */ + static async add(uid: string, gid: string, category: string): Promise<boolean> { + // Gestion naïve + Tools.addIfAbsent(uid, "user", gid, "group", category); + Tools.addIfAbsent(gid, "group", uid, "user", category); + // Gestion des droits par inclusion + Tools.addIncluded(uid, gid, category); + // Gestion des droits récursive + if (category != "followers") Tools.addDFS(uid, gid, false); + if (category == "admins") Tools.addDFS(uid, gid, true); + return true; + } + + /** + * @memberof LDAP + * @summary Fonction intermédiaire naïve. + * @desc Cette fonction enlève un utilisateur d'un groupe pour un des deux arbres si cette entrée n'était pas déjà absente. + * Elle ne donne pas de précédence particulière à un administrateur strict, ou de protection à une administrateur hérité. + * @arg {string} id1 - uid/gid + * @arg {"group"|"user"} domain1 - Arbre concerné pour l'id1 + * @arg {string} id2 - gid/uid + * @arg {"group"|"user"} domain2 - Arbre concerné pour l'id2 + * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné (admin, speaker, member ou follower) + * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async + * @static */ - static async generateId(attribut: string, domain: "gr"|"us") : Promise<string> { + static async remIfPresent(id1: string, domain1: "group"|"user", id2: string, domain2: "group"|"user", category: string): Promise<boolean> { try { - return Tools.ensureUnique("0", attribut, domain, (id,n) => { return Math.floor((Math.random() * 100000) + 1).toString(); }); - } - catch(err) { - throw "Erreur lors de l'assurance de l'unicité d'un unique identifier numérique."; + let l = await Tools.get(id1, domain1, category); + var catName = ldapConfig[domain1][category]; + // Vérifie que l'identifiant est bien présent + if (l.includes(id2)) { + // Supprime tous les identifiants + if (!await Basics.change(domain1, id1, "del", catName)) throw "Erreur lors de la suppression de tous les "+category+" de l'identifiant "+id1+"."; + // Les rajoute un par un, sauf pour le supprimé + l.forEach(id => { + if (id!=id2) { + if (domain2 == "group") var id_n = ldapConfig[domain2].gid; + else var id_n = ldapConfig[domain2].uid; + var catName = ldapConfig[domain1][category]; + Basics.change(domain1, id1, "add", {catName: id_n+'='+id+','+ldapConfig[domain2].dn}).then(res => { + if (!res) throw "Erreur lors du ré-ajout d'un autre "+domain1+" de la catégorie "+category+"."; + }); + } + }); + } } + catch(err) { throw "Erreur pour obtenir une liste d'entrées d'une catégorie d'un "+domain1+"."; } + return true; } /** * @memberof LDAP - * @summary Fonction qui retrouve les groupes dont un individu est membre. - * @desc Cette fonction utilise {@link LDAP.search} va directement à la feuille de l'utilisateur. - * @arg {string} uid - Identifiant de l'individu à interroger (le plus souvent prenom.nom, parfois l'année, supposé valide) - * @return {Promise(string[])} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre + * @summary Fonction intermédiaire. + * @desc Cette fonction gère les inclusions de droits. Elle ne rajoute pas un admin pour les admins, mais elle le rajoute en tant que speaker. + * Cette fonction agit uniquement sur l'arbre User. + * @arg {string} uid - uid de l'utilisateur à ajouter + * @arg {string} gid - gid du groupe concerné + * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné (admin, speaker, member ou follower) + * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon + * @async * @static + */ + static async remIncluded(uid: string, gid: string, category: string): Promise<boolean> { + var spk = ldapConfig.group.speakers; + var mem = ldapConfig.group.members; + switch (category) { + case "admins": + // Admin => speaker + let l = await Tools.get(gid, "group", spk); + // Supprime tous les identifiants + if (!await Basics.change("group", gid, "del", spk)) throw "Erreur lors de la suppression de tous les portes-paroles de l'identifiant "+gid+"."; + // Les rajoute un par un, sauf pour le supprimé + l.forEach(id => { + if (id!=uid) { + let tmp = ldapConfig.user.uid; + Basics.change("group", gid, "add", {spk: tmp+'='+uid+','+ldapConfig.user.dn}).then(res => { + if (!res) throw "Erreur lors du ré-ajout d'un autre membre de la catégorie porte-parole."; + }); + } + }); + case "speakers": + // Speaker & admin => member + let lm = await Tools.get(gid, "group", mem); + // Supprime tous les identifiants + if (!await Basics.change("group", gid, "del", mem)) throw "Erreur lors de la suppression de tous les portes-paroles de l'identifiant "+gid+"."; + // Les rajoute un par un, sauf pour le supprimé + l.forEach(id => { + if (id!=uid) { + let tmp = ldapConfig.user.uid; + Basics.change("group", gid, "add", {mem: tmp+'='+uid+','+ldapConfig.user.dn}).then(res => { + if (!res) throw "Erreur lors du ré-ajout d'un autre membre de la catégorie membre."; + }); + } + }); + case "members": + case "followers": + break; + } + return true; + } + + /** + * @memberof LDAP + * @summary Fonction intermédiaire de récursion. + * @desc Cette fonction gère les droits par récursion par une classique Depth First Search. + * Cette fonction agit uniquement sur l'arbre User. TBM + * @arg {string} uid - uid de l'utilisateur à ajouter + * @arg {string} gid - gid du groupe concerné + * @arg {boolean} direction - direction de la recursion + * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon * @async + * @static */ - static async getGroups(uid: string) : Promise<string[]> { - try { - return Basics.searchSingle("us", ldapConfig.user.groups, uid); + static async remDFS(uid: string, gid: string, direction: boolean): Promise<boolean> { + // Cas récursif ascendant (admins) + if (direction) { + var rol = ldapConfig.group.admins; + var tov = ldapConfig.group.childs; } - catch(err) { - throw "Erreur lors de la recherche des groupes d'un individu."; + // Cas récursif descendant (membres) + else { + var rol = ldapConfig.group.members; + var tov = ldapConfig.group.parents; } + // Classic DFS + var to_visit = [gid]; + while (to_visit.length > 0) { + let cur_gid = to_visit.pop(); + let l = await Tools.get(gid, "group", rol); + // Supprime tous les identifiants + if (!await Basics.change("group", gid, "del", rol)) throw "Erreur lors de la suppression de tous les "+rol+" de l'identifiant "+gid+"."; + // Les rajoute un par un, sauf pour le supprimé + l.forEach(id => { + if (id!=uid) { + let tmp = ldapConfig.user.uid; + Basics.change("group", gid, "add", {rol: tmp+'='+uid+','+ldapConfig.user.dn}).then(res => { + if (!res) throw "Erreur lors du ré-ajout d'un autre membre de la catégorie "+rol+"."; + }); + } + }); + to_visit.concat(await Basics.searchSingle("group", tov, cur_gid)); + } + return true; } - + + /** + * @memberof LDAP + * @summary Fonction qui permet de supprimer un membre d'une catégorie existant d'un groupe. + * @desc Cette fonction fait essentiellement appel à d'autres fonctions de {@link Tools} passées en argument et {@link LDAP.change}. + * Elle essaie d'assurer les propriétés d'inclusion et de récursion du LDAP. Elle est sans effet pour un statut hérité. + * @arg {string} uid - Identifiant de l'ex-membre + * @arg {string} gid - Identifiant du groupe + * @arg {"admins"|"speakers"|"members"|"followers"} category - Categorie de l'utilisateur concerné (admin, speaker, member ou follower) + * @return {Promise(boolean)} `true` si la modification s'est bien déroulée, false sinon + * @async + * @static + */ + static async remove(uid: string, gid: string, category : string): Promise<boolean> { + // Invulnérabilité pour les admins hérités + if ((await Tools.get(gid, "group", category)).includes(uid)) { + Tools.remIfPresent(uid, "user", gid, "group", category); + Tools.remIfPresent(gid, "group", uid, "user", category); + // Gestion des droits par inclusion + Tools.remIncluded(uid, gid, category); + // Gestion des droits récursive + if (category != "followers") Tools.remDFS(uid, gid, false); + if (category == "admins") Tools.remDFS(uid, gid, true); + } + return true; + } + + /** + * @memberof LDAP + * @callback changeValueCallback + * @param {string} id - Id à modifier + * @param {number} n - Nombre d'itérations + * @return {string} Nouveau id + */ /** * @memberof LDAP - * @summary Fonction qui retrouve la liste des membres d'un groupe. - * @desc Cette fonction utilise {@link LDAP.search} avec un dictionnaire prédéfini dans ldapConfig.json. - * @arg {string} gid - Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule) - * @return {Promise(string[])} Liste des uid des membres où l'id fournie est membre (noms flat des groupes) + * @summary Cette fonction teste une valeur d'un attribut (typiquement un identifiant) et le fait évoluer jusqu'à ce qu'il soit unique. + * @desc Librement adapté de Stack Overflow. Appelle {@link LDAP.search} pour vérifier + * qu'il n'y a pas d'autres occurences de cette valeur pour cette attribut + * dans le dn fourni. + * @param {string} value - Valeur de l'attribut (le plus souvent un identifiant) à tester à cette itération + * @param {string} attribute - Attribut à tester + * @param {"gr"|"us"} domain - Domaine dans lequel l'attribut doit être unique + * @param {changeValueCallback} changeValue - Fonction qui prend uniquement en argument l'id courant et + * le nombre d'itérations et qui renvoit la prochaine valeur de l'attribut + * @param {number} n [0] - Nombre d'itérations (à initialiser à 0) + * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié * @static * @async */ - static async getMembers(gid: string) : Promise<string[]> { + static async ensureUnique(value: string, attribute: string, domain: 'group'|'user', changeValue: (string, number) => string, n: number=0) : Promise<string> { + // Recherche d'autres occurences de l'id try { - return Basics.searchSingle("gr", ldapConfig.group.members, gid); + if (domain == "group") var att=ldapConfig.group.gid; + else var att=ldapConfig.user.uid; + let matches = await Basics.searchSingle(domain, att, null, "("+attribute+"="+ldapEscape.filter("${txt}", { txt: value })+")") + // On renvoit la valeur si elle est bien unique + if (matches.length=0) return value; + // Sinon, on tente de nouveau notre chance avec la valeur suivante + else return Tools.ensureUnique(changeValue(value, n+1), attribute, domain, changeValue, n+1); } catch(err) { - throw "Erreur lors de la recherche des membres d'un groupe."; + throw "Erreur lors de la recherche d'une valeur pour assurer son unicité."; } } - + /** * @memberof LDAP - * @summary Fonction qui retrouve la liste des admins d'un groupe. - * @desc Cette fonction utilise {@link LDAP.search} avec un dictionnaire prédéfini dans ldapConfig.json. - * @arg {string} gid - Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule) - * @return {Promise(string[])} Liste des uid des membres où l'id fournie est membre (noms flat des groupes) + * @summary Cette fonction génère un uid standard, puis le fait évoluer jusqu'à ce qu'il soit unique. + * @desc Limité à un appel à {@link Tools.ensureUnique} avec les bons paramètres, et quelques opérations sur l'uid pour qu'il soit valide (escape, normalisation). + * @param {"group"|"user"} domain - Arbre à parcourir + * @param {string} givenName - Prénom + * @param {string} lastName - Nom + * @param {string} promotion - Année de promotion + * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié * @static * @async */ - static async getAdmins(gid: string) : Promise<string[]> { + static async generateUid(domain : "group"|"user", givenName: string, lastName: string, promotion: string) : Promise<string> { try { - return Basics.searchSingle("gr", ldapConfig.group.admins, gid); + if (domain == "group") var att=ldapConfig.group.gid; + else var att=ldapConfig.user.uid; + // normalize et lowerCase standardisent le format + return Tools.ensureUnique((givenName+'.'+lastName).toLowerCase().normalize('UFD'), att, "user", (id: string, n: number) => { + if (n=1) id+='.'+promotion; // Si prénom.nom existe déjà , on rajoute la promo + else if (n=2) id+='.'+(n-1).toString(); // Puis si prénom.nom.promo existe déjà on passe à nom.prenom.promo .1 + else if (n>2) id+=n; // Ensuite on continue .123, .1234, etc... + return id; + }); } catch(err) { - throw "Erreur lors de la recherche des admins d'un groupe."; + throw "Erreur lors de l'assurance de l'unicité d'un human readable unique identifier (hruid)."; } } /** * @memberof LDAP - * @summary Cette fonction teste si un utilisateur est membre d'un groupe. - * @desc Utilise les méthodes statiques {@link open.getGroups} et {@link open.getMembers} - * @param {string} uid - Identifiant de l'utilisateur à tester - * @param {string} gid - Identification du groupe à tester - * @returns {Promise(boolean)} True si l'utilisateur est membre + * @summary Cette fonction génère un id lisible, puis le fait évoluer jusqu'à ce qu'il soit unique. + * @desc Limité à un appel à {@link Tools.ensureUnique} avec les bons paramètres, et quelques opérations sur l'uid pour qu'il soit valide (escape, normalisation). + * @param {"group"|"user"} domain - Arbre à parcourir + * @param {string} name - Nom + * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié * @static * @async */ - static async isGroupMember(uid: string, gid: string) : Promise<boolean> { + static async generateReadableId(domain : "group"|"user", name: string) : Promise<string> { try { - let lg = await Tools.getGroups(uid); - let lm = await Tools.getMembers(gid); - if (lg.includes(gid) && lm.includes(uid)) { - return true; - } - else { return false; } + if (domain == "group") var att=ldapConfig.group.gid; + else var att=ldapConfig.user.uid; + // normalize et lowerCase standardisent le format + return Tools.ensureUnique(name.toLowerCase().normalize('UFD'), att, domain, (id: string, n: number) => { + if (n=1) id+='.'+n.toString(); // Si nom existe déjà , on essaie nom.1 + else if (n>1) id+=n.toString(); // Ensuite on continue .12, .123, etc... + return id; + }); } catch(err) { - throw "Erreur lors du test d'appartenance à un groupe."; + throw "Erreur lors de l'assurance de l'unicité d'un human readable unique identifier (hruid)."; } } /** * @memberof LDAP - * @summary Cette fonction teste si un utilisateur est admin d'un groupe. - * @desc Utilise la méthode statique {@link Open.getAdmins} - * @param {string} uid - Identifiant de l'utilisateur à tester - * @param {string} gid - Identification du groupe à tester - * @returns {Promise(boolean)} True si l'utilisateur est administrateur + * @summary Cette fonction teste une valeur dummy (0) pour un identifiant numérique puis le fait évoluer aléatoirement (entre 1 et 100 000) jusqu'à ce qu'il soit unique. + * @param {string} attribute - Intitulé exact de l'id concerné + * @param {"gr"|"us"} domain - Domaine dans lequel l'attribut doit être unique + * @return {Promise(string)} Valeur unique dans le domaine spécifié de l'attribut spécifié * @static * @async */ - static async isGroupAdmin(uid: string, gid: string) : Promise<boolean> { + static async generateId(attribute: string, domain: "group"|"user") : Promise<string> { try { - let lm = await Tools.getMembers(gid); - let la = await Tools.getAdmins(gid); - if (la.includes(uid) && lm.includes(uid)) { return true; } - else { return false; } + return Tools.ensureUnique("0", attribute, domain, (id,n) => Math.floor((Math.random() * 100000) + 1).toString()); } catch(err) { - throw "Erreur lors du test d'appartenance au bureau d'administration un groupe."; + throw "Erreur lors de l'assurance de l'unicité d'un unique identifier numérique."; } } } \ No newline at end of file diff --git a/src/ldap/test.js b/src/ldap/test.js new file mode 100644 index 0000000000000000000000000000000000000000..832f1fee2566b21bbcba60cf0552242b64903ad0 --- /dev/null +++ b/src/ldap/test.js @@ -0,0 +1,6 @@ +var Group = require("../../tsbuild/src/ldap/export/group").Group; +console.log(Group); + +Group.peek("faerix").then(dat => { console.log(dat); }); + +var User = require("../../tsbuild/src/ldap/export/group"); \ No newline at end of file diff --git a/test/resolvers/data/onplatal.ts b/test/resolvers/data/onplatal.ts new file mode 100644 index 0000000000000000000000000000000000000000..d1a3fdfcbaf2d7b755c28ae0195a29fb580b4b8d --- /dev/null +++ b/test/resolvers/data/onplatal.ts @@ -0,0 +1,41 @@ +/** + * @file Ce fichier charge tous les tests sans authentification + * @author ofacklam + */ + +import fs from 'fs'; +import path from 'path'; +import { TestCollection, TestSet } from "../testData"; +import { AuthorizationModel } from "../../../src/graphql/models/authorization"; +import { UserModel } from "../../../src/graphql/models/userModel"; +import { GroupModel } from "../../../src/graphql/models/groupModel"; +import { MessageModel } from "../../../src/graphql/models/messageModel"; +import { RequestModel } from "../../../src/graphql/models/requestModel"; + +let uid = AuthorizationModel.ONPLATALUSER; + +const tests : TestCollection = { + description: "On-platal user", + context : async ({ req }) => { + return { + request: req, + user: { uid: uid }, + models: { + auth: await AuthorizationModel.create(uid), + user: new UserModel(uid), + group: new GroupModel(uid), + message: new MessageModel(uid), + request: new RequestModel(uid) + } + }; + }, + tests : [] +} + +let dir = path.resolve(__dirname, './onplatal') +fs.readdirSync(dir).forEach(file => { + const testSet : TestSet = require(path.resolve(dir, file)).tests; + tests.tests.push(testSet); +}); + +export {tests}; \ No newline at end of file diff --git a/test/resolvers/data/onplatal/groups.ts b/test/resolvers/data/onplatal/groups.ts new file mode 100644 index 0000000000000000000000000000000000000000..7682bb21546467311a954c6fab83e52935210200 --- /dev/null +++ b/test/resolvers/data/onplatal/groups.ts @@ -0,0 +1,23 @@ +/** + * @file Ce fichier contient les tests des resolvers des groupes + * @author ofacklam +*/ + +import { TestSet } from '../../testData'; + +export const tests : TestSet = { + description: "Group type resolvers", + tests: [ + { + description: "group(gid)", + query: ` + query { + group(gid:"br") { + gid + } + } + `, + result: { "data": { "group": { "gid": "br" } } } + } + ] +} diff --git a/test/resolvers/data/onplatal/users.ts b/test/resolvers/data/onplatal/users.ts new file mode 100644 index 0000000000000000000000000000000000000000..4dc55f1eee01cb696029595364a382bd48567c92 --- /dev/null +++ b/test/resolvers/data/onplatal/users.ts @@ -0,0 +1,150 @@ +/** + * @file Ce fichier contient les tests des resolvers des users + * @author ofacklam +*/ + +import { TestSet } from '../../testData'; + +export const tests: TestSet = { + description: "User type resolvers", + tests: [ + { + description: "user(uid)", + query: ` + query { + user(uid: "oliver.facklam") { + uid + } + } + `, + result: { + "data": { + "user": { + "uid": "oliver.facklam" + } + } + } + }, + + { + description: "searchTOL(givenName)", + query: ` + query { + searchTOL(givenName: "Olivér") { + uid + } + } + `, + result: { + "data": { + "searchTOL": [ + { + "uid": "oliver.facklam" + } + ] + } + } + }, + + { + description: "searchTOL(lastName) partial", + query: ` + query { + searchTOL(lastName: "Fack") { + uid + } + } + `, + result: { + "data": { + "searchTOL": [ + { + "uid": "hugues.asofa-zeufack" + }, + { + "uid": "fabrice.zapfack" + }, + { + "uid": "jordan.lekeufack-sopze" + }, + { + "uid": "oliver.facklam" + } + ] + } + } + }, + + /*{ + description: "searchTOL(groups) triclassés", + query: ` + query { + searchTOL(groups: ["br", "faerix", "jtx"]) { + uid + } + } + `, + result: { + "data": { + "searchTOL": [ + { + "uid": "dubut.2003" + }, + { + "uid": "brodard.2004" + }, + { + "uid": "le-floch.2004" + }, + { + "uid": "rabie.2004" + }, + { + "uid": "pierre-etienne.marx" + }, + { + "uid": "lauriane.aufrant" + }, + { + "uid": "matthias.bry" + }, + { + "uid": "julia.chatain" + }, + { + "uid": "victor.berger" + }, + { + "uid": "augustin.lenormand" + }, + { + "uid": "timothee.darcet" + } + ] + } + } + },*/ + + { + description: "firstName, lastName, nickName", + query: ` + query { + user(uid: "oliver.facklam") { + givenName + lastName + nickname + } + } + `, + result: { + "data": { + "user": { + "givenName": "Olivér", + "lastName": "Facklam", + "nickname": null + } + } + } + }, + ] +} \ No newline at end of file diff --git a/test/resolvers/data/unauthenticated.ts b/test/resolvers/data/unauthenticated.ts new file mode 100644 index 0000000000000000000000000000000000000000..a606551678b0697004a461e6630797b37154b0e2 --- /dev/null +++ b/test/resolvers/data/unauthenticated.ts @@ -0,0 +1,41 @@ +/** + * @file Ce fichier charge tous les tests sans authentification + * @author ofacklam + */ + +import fs from 'fs'; +import path from 'path'; +import { TestCollection, TestSet } from "../testData"; +import { AuthorizationModel } from "../../../src/graphql/models/authorization"; +import { UserModel } from "../../../src/graphql/models/userModel"; +import { GroupModel } from "../../../src/graphql/models/groupModel"; +import { MessageModel } from "../../../src/graphql/models/messageModel"; +import { RequestModel } from "../../../src/graphql/models/requestModel"; + +let uid = AuthorizationModel.PUBLICUSER; + +const tests : TestCollection = { + description: "Public user", + context : async ({ req }) => { + return { + request: req, + user: { uid: uid }, + models: { + auth: await AuthorizationModel.create(uid), + user: new UserModel(uid), + group: new GroupModel(uid), + message: new MessageModel(uid), + request: new RequestModel(uid) + } + }; + }, + tests : [] +} + +let dir = path.resolve(__dirname, './unauthenticated') +fs.readdirSync(dir).forEach(file => { + const testSet : TestSet = require(path.resolve(dir, file)).tests; + tests.tests.push(testSet); +}); + +export {tests}; \ No newline at end of file diff --git a/test/resolvers/data/unauthenticated/users.ts b/test/resolvers/data/unauthenticated/users.ts new file mode 100644 index 0000000000000000000000000000000000000000..9321a578b3ee10bb7c7b01bb399719244273adba --- /dev/null +++ b/test/resolvers/data/unauthenticated/users.ts @@ -0,0 +1,44 @@ +/** + * @file Ce fichier contient les tests des resolvers des users + * @author ofacklam +*/ + +import { TestSet } from '../../testData'; + +export const tests: TestSet = { + description: "User type resolvers", + tests: [ + { + description: "user(uid) not authorized", + query: ` + query { + user(uid: "oliver.facklam") { + uid + } + } + `, + result: { + "data": { + "user": null + } + } + }, + + { + description: "searchTOL() not authorized", + query: ` + query { + searchTOL(givenName: "Olivér") { + uid + } + } + `, + result: { + "data": { + "searchTOL": null + } + } + } + ] +} + diff --git a/test/resolvers/resolvers.test.ts b/test/resolvers/resolvers.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae4b159139c45e6b4eb48cd7fd523ccc3e3c08dc --- /dev/null +++ b/test/resolvers/resolvers.test.ts @@ -0,0 +1,63 @@ +/** + * @file Ce fichier charge et execute tous les tests sur les resolvers + * @author ofacklam + */ + +import { expect } from 'chai'; +import fs from 'fs'; +import path from 'path'; +import { ApolloServer } from 'apollo-server-express'; +import { createTestClient } from 'apollo-server-testing'; + +//TODO : Set up a mock LDAP server (LDAP_URI = ... or TARGET_ENV=testing) + +import schema from '../../src/graphql/schema'; +import { TestCollection } from './testData'; + +const dir = path.resolve(__dirname, './data'); + +describe("GraphQL resolvers", function() { + fs.readdirSync(dir, {withFileTypes:true}) + .filter(item => !item.isDirectory()) + .forEach(file => { + const testCol : TestCollection = require(path.resolve(dir, file.name)).tests; + + describe(testCol.description, function() { + //contruct context and apollo server + const server = new ApolloServer({ + ...schema, + context: testCol.context + }); + const {query} = createTestClient(server); + + for (let testSet of testCol.tests) { + describe(testSet.description, function() { + for(let t of testSet.tests) { + it(t.description, async function() { + //silence the console + console.log = function () { }; + + //query + let res = await query({query: t.query}); + + //reset console + delete console.log; + + let final = {}; + final['data'] = res.data; + //if(res.errors !== undefined) final['errors'] = res.errors; + expect(final).to.deep.equal(t.result); + }) + } + }) + } + }) + }) + + beforeEach(function () { + + }); + afterEach(function () { + + }); +}) \ No newline at end of file diff --git a/test/resolvers/testData.d.ts b/test/resolvers/testData.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..b8a75520bb36fc0ee06ae7dd40947ae4009cab0a --- /dev/null +++ b/test/resolvers/testData.d.ts @@ -0,0 +1,23 @@ +/** + * @file Ce fichier définit le type de base pour les tests + * @author ofacklam +*/ + +import { Context } from "../../src/graphql/typeDefs/queries"; + +interface Test { + description : string, + query : string, + result +} + +interface TestSet { + description : string, + tests : Test[] +} + +interface TestCollection { + description : string, + context : ({req:any}) => Promise<Context>, + tests : TestSet[] +} \ No newline at end of file diff --git a/test/test.js b/test/test.js index 15eb334306f0c1ec4be59c9578c67b8818a0bc3a..f56440ecafc710c1d2bdaa484fe07415dca8e68c 100644 --- a/test/test.js +++ b/test/test.js @@ -1,6 +1,6 @@ -require('dotenv').config() +require('dotenv').config(); -const { credentialsConfig } = require('../src/ldap/config'); +import { credentialsLdapConfig as credentialsConfig } from '../src/ldap/internal/config'; process.env.PORT = process.env.TEST_PORT || 3001; // The port is changed so that the test suite can be ran without interfering with a running server @@ -11,70 +11,70 @@ const chai = require('chai'); const expect = chai.expect; -const { GraphQLClient } = require('graphql-request') +const { GraphQLClient } = require('graphql-request'); -const apiEndpoint = `http://localhost:${process.env.PORT || 3001}/graphql`; +const apiEndpoint = `http://localhost:${process.env.PORT}/graphql`; const auth = { - username : credentialsConfig.dn.split("=")[1].split(",")[0], - password : credentialsConfig.passwd + username : credentialsConfig.dn.split("=")[1].split(",")[0], + password : credentialsConfig.passwd }; const testList = require('./testData').testList; describe('test server API', function () { - let client; + let client; - it('Should authentify and initialize the client', async function (){ + it('Should authentify and initialize the client', async function (){ - const tempClient = new GraphQLClient(apiEndpoint); - const query = ` - mutation { - login(username : "${auth.username}", password: "${auth.password}" ) - } - `; + const tempClient = new GraphQLClient(apiEndpoint); + const query = ` + mutation { + login(username : "${auth.username}", password: "${auth.password}" ) + } + `; - const res = await tempClient.request(query); + const res = await tempClient.request(query); - expect(res).to.have.property('login'); + expect(res).to.have.property('login'); - const token = res.login; + const token = res.login; - client = new GraphQLClient(apiEndpoint, { - headers: { - mode : 'cors', // Don't know what that does, isn't necessary. Worth looking into - credentials : 'include', // Same - authorization: `Bearer ${token}` - } - }); + client = new GraphQLClient(apiEndpoint, { + headers: { + mode : 'cors', // Don't know what that does, isn't necessary. Worth looking into + credentials : 'include', // Same + authorization: `Bearer ${token}` + } + }); - }); + }); - it('Should query all groups to test the client', async function (){ - const query = ` - query { - allGroups { - name - } - } - `; + it('Should query all groups to test the client', async function (){ + const query = ` + query { + allGroups { + name + } + } + `; - const res = await client.request(query); + const res = await client.request(query); - expect(res).to.have.property('allGroups'); - expect(res.allGroups).to.be.an('array'); - expect(res.allGroups).to.have.lengthOf.above(3); - }); + expect(res).to.have.property('allGroups'); + expect(res.allGroups).to.be.an('array'); + expect(res.allGroups).to.have.lengthOf.above(3); + }); - for(const test of testList){ + for(const test of testList){ - it(test.description, async function (){ - const res = await client.request(test.query); - expect(res).to.be.deep.equal(test.result); - }); + it(test.description, async function (){ + const res = await client.request(test.query); + expect(res).to.be.deep.equal(test.result); + }); - } + } }); diff --git a/test/testData.js b/test/testData.js index f5a32126ab5754bd0c519edec0c7aa56f1ff720b..00496169990173c6a9737237e29dcd0fc0c4cc89 100644 --- a/test/testData.js +++ b/test/testData.js @@ -12,72 +12,72 @@ exports.testList = [ { - query : `query{allGroups{name}}`, - result: { - "allGroups": [ - { "name": "BR" }, - { "name": "JTX" }, - { "name": "Faërix" }, - { "name": "Bôbar" }, - { "name": "Kès" }, - { "name": "Subaïsse" }, - { "name": "X-Broadway" }, - { "name": "Œnologie" }, - { "name": "Tribunes de l'X" }, - { "name": "X-Finance" }, - { "name": "ASK" } - ] - }, - description : "Should query all groups" + query : `query{allGroups{name}}`, + result: { + "allGroups": [ + { "name": "BR" }, + { "name": "JTX" }, + { "name": "Faërix" }, + { "name": "Bôbar" }, + { "name": "Kès" }, + { "name": "Subaïsse" }, + { "name": "X-Broadway" }, + { "name": "Œnologie" }, + { "name": "Tribunes de l'X" }, + { "name": "X-Finance" }, + { "name": "ASK" } + ] + }, + description : "Should query all groups" }, { - query : ` - query{group(uid : "br"){ - uid, - name, - website - }}`, - result : { - "group": { - "uid": "br", - "name": "BR", - "website": "br.binets.fr" - } - }, - description : "Should query a single group" + query : ` + query{group(uid : "br"){ + uid, + name, + website + }}`, + result : { + "group": { + "uid": "br", + "name": "BR", + "website": "br.binets.fr" + } + }, + description : "Should query a single group" }, { - query : `query{ - allMessages{ - id, - title, - content - } - }`, - result : { - "allMessages": [ - { - "id": "11", - "title": "Fête de la lune", - "content": "La fête de la lune, c'est bientôt dans le grand hall !" - }, - { - "id": "12", - "title": "Perm BR du mardi soir", - "content": "La perm' BR c'est maintenant!" - }, - { - "id": "13", - "title": "Formation Git", - "content": "Aujourd'hui, on va parler du système de contrôle de versions Git, qui est particulièrement utile pour travailler à plusieurs sur des projets informatiques: PSC, code de PI ou de projet de MAP, site binet, quoi que ce soit!" - }, - { - "id": "14", - "title": "Formation Web", - "content": "Envie d'apprendre à faire un site Web en Django ? Alors viens en amphi Sauvy ce jeudi à 20h !" - } - ] - }, - description : "Should fetch all messages" + query : `query{ + allMessages{ + id, + title, + content + } + }`, + result : { + "allMessages": [ + { + "id": "11", + "title": "Fête de la lune", + "content": "La fête de la lune, c'est bientôt dans le grand hall !" + }, + { + "id": "12", + "title": "Perm BR du mardi soir", + "content": "La perm' BR c'est maintenant!" + }, + { + "id": "13", + "title": "Formation Git", + "content": "Aujourd'hui, on va parler du système de contrôle de versions Git, qui est particulièrement utile pour travailler à plusieurs sur des projets informatiques: PSC, code de PI ou de projet de MAP, site binet, quoi que ce soit!" + }, + { + "id": "14", + "title": "Formation Web", + "content": "Envie d'apprendre à faire un site Web en Django ? Alors viens en amphi Sauvy ce jeudi à 20h !" + } + ] + }, + description : "Should fetch all messages" } - ]; \ No newline at end of file +]; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 7284a436ec35bdd7978e1ec22cb25a379a841fe3..fe9726b049c06760f49696848eec7396b3f7d135 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "comment": "Fichier servant à la configuration des fichiers typescript, ou javascript typé", + "comment": "Fichier servant à la configuration des fichiers typescript, ou javascript typé (https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)", "compilerOptions": { "module": "commonjs", "esModuleInterop": true, diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000000000000000000000000000000000000..fa6d17853c1dbc8a0380f1ea9f6aa65c1e70e756 --- /dev/null +++ b/tslint.json @@ -0,0 +1,26 @@ +{ + "defaultSeverity": "error", + "extends": "tslint:recommended", + "rules": { + "indent": { "options": ["spaces", 4] }, + "linebreak-style": { "options": ["LF"] }, + "semicolon": { "options": ["always"] }, + "max-line-length": { + "severity": "warning", + "options": [120] + }, + "no-console": { + "severity": "warning", + "options": [ + "debug", + "info", + "log", + "time", + "timeEnd", + "trace" + ] + } + }, + "jsRules": true, + "rulesDirectory": [] +} \ No newline at end of file