diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a51eefe..1f9cf983 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,34 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [2.0.0] - 2020-08-15 + +The first major back-end and front-end rewrite of Ackee with new API, dashboard, active visitors counter and more. Updating is as easy as ever. Simple grab the newest version, ensure that you're using Node.js v14 or higher and start Ackee. That's it! + +### Added + +- GraphQL API +- Overview with facts and data from all domains +- Facts card with live visitor counter, average visits and durations and the total number of visits today, this month and year +- New navigation that allows you to view stats by domain +- Keyboard shortcuts +- Switch between daily, monthly and yearly durations +- Click on a card headline to view more of this domain or insight +- Support `+srv` connection string modifier for MongoDB urls (#132, thanks @ericsandine) + +### Changed + +- Improved performance for all aggregations +- Show stale data while loading new data +- Removed detailed durations +- Delete records of a domain when deleting a domain +- Updated the required Node.js version and Docker Node.js version to v14 +- Removed "All time" and replaced it with "Last 6 months" for performance reasons + +### Fixed + +- Sorting of yearly views + ## [1.7.1] - 2020-05-15 ### Added diff --git a/Dockerfile b/Dockerfile index 484638f6..6775a2ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mhart/alpine-node:10 +FROM mhart/alpine-node:14 EXPOSE 3000 diff --git a/README.md b/README.md index 392fa9c1..01ee4203 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Ackee is a web app you install on your server to analyse the traffic of your sit ### Why Ackee? -Ackee is lightweight, easy to install and has a good balance between analytics and privacy. It features an API and web interface and tracks only what's necessary. +Ackee is lightweight, easy to install and has a good balance between analytics and privacy. It features a GraphQL API and web interface and tracks only what's necessary. It's is the right tool for you if you care about privacy and don't need a full-features marketing analytics platform like Google Analytics or Matomo. @@ -52,7 +52,7 @@ It's is the right tool for you if you care about privacy and don't need a full-f - Modern and fast architecture - Beautiful and focused interface - No unique user tracking and no cookies -- Fully documented API +- Fully documented GraphQL API ### How does it work? @@ -68,7 +68,7 @@ The interface of Ackee lets you view and analyse your tracked information. Ackee depends on... -- [Node.js](https://nodejs.org/en/) (v10.16 or newer) +- [Node.js](https://nodejs.org/en/) (v14 or newer) - [yarn](https://yarnpkg.com/en/) - [MongoDB](https://www.mongodb.com) (v4.0.6 or newer) @@ -76,19 +76,7 @@ Make sure to install and update all dependencies before you setup Ackee. ### API -- [/](docs/UI.md) -- [/tokens](docs/tokens.md) -- [/domains](docs/domains.md) -- [/domains/:domainId/records](docs/records.md) -- [/domains/:domainId/views](docs/views.md) -- [/domains/:domainId/pages](docs/pages.md) -- [/domains/:domainId/referrers](docs/referrers.md) -- [/domains/:domainId/durations](docs/durations.md) -- [/domains/:domainId/systems](docs/systems.md) -- [/domains/:domainId/devices](docs/devices.md) -- [/domains/:domainId/browsers](docs/browsers.md) -- [/domains/:domainId/sizes](docs/sizes.md) -- [/domains/:domainId/languages](docs/languages.md) +Ackee features a [GraphQL API](docs/API.md) that allows you to build custom tools upon Ackee. Everything you see in the UI is made from data delivered by the API. ### Options diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 00000000..87c2cb2d --- /dev/null +++ b/docs/API.md @@ -0,0 +1,220 @@ +# API + +Ackee features a GraphQL API that allows you to build custom tools upon Ackee. Everything you see in the UI is made from data delivered by the API. + +Here are a few resources to help you get started with GraphQL: + +- https://graphql.org/learn/ +- https://www.howtographql.com + +## Playground + +GraphQL Playground is a graphical, interactive, in-browser GraphQL IDE. It allows you to play and experiment with the API of Ackee. + +Simply run Ackee with `NODE_ENV` set to `development` and visit the `/api` playground in your browser. You can do so by adding `NODE_ENV=development` to the environment of your `docker-compose.yml` or by using `yarn start:dev`. Only use this mode on your local machine as Ackee runs slower when in development mode. + +Try the [🔮 live playground](https://demo.ackee.electerious.com/api) of the Ackee demo. + +## Authentication + +Modifying domains or receiving aggregated data is only possible once you're authenticated. Only the creation of new data is possible without a token. + +### Creating a token + +The following mutation returns a new token `id` that should be used for authentication. This is what happens in the UI when you submit your username and password. + +```graphql +mutation createToken($input: CreateTokenInput!) { + createToken(input: $input) { + payload { + id + } + } +} +``` + +```json +{ + "input": { + "username": "admin", + "password": "123456" + } +} +``` + +The token is valid for one day and will be renewed on every request made with it. You can modify the TTL (time to live) in [the options](Options.md#ttl). + +### Use token + +Protected queries and mutations need to include the `Authorization` HTTP header. Replace `tokenId` with the token `id` from the previous step. + +```json +{ + "Authorization": "Bearer tokenId" +} +``` + +## Queries + +Queries are used to receive data. Here are a few examples: + +### Get all domains + +```graphql +query getDomains { + domains { + id + title + } +} +``` + +### Get a specific domain + +```graphql +query getDomain($id: ID!) { + domain(id: $id) { + id + title + } +} +``` + +```json +{ + "id": "3b8bc3ed-cdcb-492a-bc6d-8d5b2746da0e" +} +``` + +### Get facts of domains + +```graphql +query getDomainsFacts { + domains { + facts { + activeVisitors + averageViews + averageDuration + viewsToday + viewsMonth + viewsYear + } + } +} +``` + +### Get statistics of domains + +```graphql +query getDomainsStatistics { + domains { + statistics { + durations(interval: DAILY) { + id + count + } + views(interval: YEARLY, type: UNIQUE) { + id + count + } + languages(sorting: TOP) { + id + count + created + } + browsers(sorting: TOP, type: WITH_VERSION) { + id + count + created + } + devices(sorting: TOP, type: WITH_MODEL) { + id + count + created + } + pages(sorting: TOP) { + id + count + created + } + referrers(sorting: TOP) { + id + count + created + } + sizes(sorting: TOP, type: SCREEN_RESOLUTION) { + id + count + created + } + systems(sorting: TOP, type: NO_VERSION) { + id + count + created + } + } + } +} +``` + +## Mutations + +Mutations are used to add, update or delete data. Here are a few examples: + +### Create a domain + +```graphql +mutation createDomain($input: CreateDomainInput!) { + createDomain(input: $input) { + payload { + id + title + } + } +} +``` + +```json +{ + "input": { + "title": "Domain Title" + } +} +``` + +### Delete a domain + +```graphql +mutation deleteDomain($id: ID!) { + deleteDomain(id: $id) { + success + } +} +``` + +```json +{ + "id": "3b8bc3ed-cdcb-492a-bc6d-8d5b2746da0e" +} +``` + +### Create a record + +```graphql +mutation createRecord($domainId: ID!, $input: CreateRecordInput!) { + createRecord(domainId: $domainId, input: $input) { + payload { + id + } + } +} +``` + +```json +{ + "domainId": "3b8bc3ed-cdcb-492a-bc6d-8d5b2746da0e", + "input": { + "siteLocation": "https://example.com" + } +} +``` \ No newline at end of file diff --git a/docs/Get started.md b/docs/Get started.md index ff5709e8..188b9594 100644 --- a/docs/Get started.md +++ b/docs/Get started.md @@ -5,6 +5,7 @@ - [With Helm](#with-helm) - [Without Docker](#without-docker) - [With Heroku](#with-heroku) +- [With Render](#with-render) ## With Docker Compose @@ -114,7 +115,7 @@ If you're using the `ingress-nginx`, enabling the ingress will set the necessary Ackee dependents on … -- [Node.js](https://nodejs.org/en/) (v10.16 or newer) +- [Node.js](https://nodejs.org/en/) (v14 or newer) - [yarn](https://yarnpkg.com/en/) - [MongoDB](https://www.mongodb.com) (v4.0.6 or newer) @@ -169,7 +170,9 @@ Simply deploy to Heroku by clicking this button: ### 2. Configure Ackee -Ensure that you're using the correct CORS headers by setting [`ACKEE_ALLOW_ORIGIN`](CORS%20headers.md#heroku-or-platforms-as-a-service-configuration). +- You need to have a MongoDB instance running, either hosting it yourself or using a (paid) add-on like [ObjectRocket MongoDB](https://elements.heroku.com/addons/ormongo). This is as simple as typing `heroku addons:create ormongo:2-wt --app ` using the CLI, or using the web dashboard; more details at the [official documentation](https://devcenter.heroku.com/articles/managing-add-ons). You'll need to provide connection details to Ackee dyno, either from the web dashboard or via command line, e.g. `heroku config:add "ACKEE_MONGODB=mongodb://:/"` + +- Ensure that you're using the correct CORS headers by setting [`ACKEE_ALLOW_ORIGIN`](CORS%20headers.md#heroku-or-platforms-as-a-service-configuration). ### 3. Updating Ackee @@ -187,7 +190,17 @@ You'll then want to add the Ackee repo as origin, pull the latest changes, and p ```sh git remote add origin https://github.com/electerious/Ackee.git git pull origin master -git push origin heroku master +git push heroku master ``` -After your application re-deploys you'll have the latest version of Ackee! \ No newline at end of file +After your application re-deploys you'll have the latest version of Ackee! + +## With Render + +You can use [Render's](https://render.com/) one-click deploy button to get up and running with Ackee in minutes. + +Click **Deploy to Render** below and follow the prompts to set up Ackee on Render. + +[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/render-examples/ackee) + +Once your deploy has finished, you are ready to start using Ackee! Visit the URL for your service to login. You can get your login credentials from the `ACKEE_USERNAME` and `ACKEE_PASSWORD` environment variables in the **Environment** tab of your service. By default, your username will be `render` and your password will be a randomly generated string. diff --git a/docs/SSL and HTTPS.md b/docs/SSL and HTTPS.md index 85613c30..eb5cecc7 100644 --- a/docs/SSL and HTTPS.md +++ b/docs/SSL and HTTPS.md @@ -6,7 +6,7 @@ Ackee runs a simple server that doesn't support TSL/SSL. This means it's not pos > A reverse proxy is a type of proxy server that retrieves resources on behalf of a client from one or more servers. These resources are then returned to the client, appearing as if they originated from the proxy server itself. -A reverse proxy makes it easy for you to run Ackee on your server along with other services. It also allows you to secure connections using TSL/SSL. +A reverse proxy makes it easy for you to run Ackee on your server along with other services. It also allows you to secure connections using TLS/SSL. I highly recommend [this article](https://medium.com/intrinsic/why-should-i-use-a-reverse-proxy-if-node-js-is-production-ready-5a079408b2ca) if you want to lean more about reverse proxies. diff --git a/docs/UI.md b/docs/UI.md deleted file mode 100644 index e1ef36ad..00000000 --- a/docs/UI.md +++ /dev/null @@ -1,109 +0,0 @@ -# UI - -- [Index](#index) -- [Favicon](#favicon) -- [Styles](#styles) -- [Scripts](#scripts) -- [Tracker](#tracker) - -## Index - -HTML used to display the UI of Ackee. - -### Request - -``` -GET / -GET /index.html -``` - -### Response - -``` -Status: 200 OK -``` - -```html - - - - - Ackee - … -``` - -## Favicon - -Favicon of Ackee. - -### Request - -``` -GET /favicon.ico -``` - -### Response - -``` -Status: 200 OK -``` - -## Styles - -CSS used to display the UI of Ackee. - -### Request - -``` -GET /index.css -``` - -### Response - -``` -Status: 200 OK -``` - -```css -/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;… -``` - -## Scripts - -JS used to display the UI of Ackee. - -### Request - -``` -GET /index.js -``` - -### Response - -``` -Status: 200 OK -``` - -```js -!function(){return function e(t,n,r){function o(i,u){if(!n[i]){if(!t[i]){var l… -``` - -## Tracker - -Tracking script that should be added to the sites you want to track. Equal to [ackee-tracker](https://github.com/electerious/ackee-tracker). - -### Request - -``` -GET /tracker.js -``` - -### Response - -``` -Status: 200 OK -``` - -```js -!function(){return function e(t,n,r){function o(i,u){if(!n[i]){if(!t[i]){var l… -``` \ No newline at end of file diff --git a/docs/browsers.md b/docs/browsers.md deleted file mode 100644 index 51b1f8ed..00000000 --- a/docs/browsers.md +++ /dev/null @@ -1,168 +0,0 @@ -# Browsers - -- [Top browsers without version](#top-browsers-without-version) -- [Top browsers with version](#top-browsers-with-version) -- [Recent browsers without version](#recent-browsers-without-version) -- [Recent browsers with version](#recent-browsers-with-version) - -## Top browsers without version - -Get the top 30 browsers without the version. - -### Request - -``` -GET /domains/:domainId/browsers?sorting=top&type=noVersion -GET /domains/:domainId/browsers?sorting=top&type=noVersion&range=daily -GET /domains/:domainId/browsers?sorting=top&type=noVersion&range=weekly -GET /domains/:domainId/browsers?sorting=top&type=noVersion&range=monthly -GET /domains/:domainId/browsers?sorting=top&type=noVersion&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "browsers", - "data": [ - { - "type": "browser", - "data": { - "id": "Safari", - "count": 1 - } - } - ] -} -``` - -## Top browsers with version - -Get the top 30 browsers with the version. - -### Request - -``` -GET /domains/:domainId/browsers?sorting=top&type=withVersion -GET /domains/:domainId/browsers?sorting=top&type=withVersion&range=daily -GET /domains/:domainId/browsers?sorting=top&type=withVersion&range=weekly -GET /domains/:domainId/browsers?sorting=top&type=withVersion&range=monthly -GET /domains/:domainId/browsers?sorting=top&type=withVersion&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "browsers", - "data": [ - { - "type": "browser", - "data": { - "id": { - "browserName": "Safari", - "browserVersion": "5.1" - }, - "count": 1 - } - } - ] -} -``` - -## Recent browsers without version - -Get the 30 most recent browsers without the version. - -### Request - -``` -GET /domains/:domainId/browsers?sorting=recent&type=noVersion -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "browsers", - "data": [ - { - "type": "browser", - "data": { - "id": "Safari", - "created": "2019-09-19T15:54:00.020Z" - } - } - ] -} -``` - -## Recent browsers with version - -Get the 30 most recent browsers with the version. - -### Request - -``` -GET /domains/:domainId/browsers?sorting=recent&type=withVersion -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "browsers", - "data": [ - { - "type": "browser", - "data": { - "id": { - "browserName": "Safari", - "browserVersion": "5.1" - }, - "created": "2019-09-19T15:54:00.020Z" - } - } - ] -} -``` \ No newline at end of file diff --git a/docs/devices.md b/docs/devices.md deleted file mode 100644 index 81718a9a..00000000 --- a/docs/devices.md +++ /dev/null @@ -1,168 +0,0 @@ -# Devices - -- [Top devices without model](#top-devices-without-model) -- [Top devices with model](#top-devices-with-model) -- [Recent devices without model](#recent-devices-without-model) -- [Recent devices with model](#recent-devices-with-model) - -## Top devices without model - -Get the top 30 devices without the model. - -### Request - -``` -GET /domains/:domainId/devices?sorting=top&type=noModel -GET /domains/:domainId/devices?sorting=top&type=noModel&range=daily -GET /domains/:domainId/devices?sorting=top&type=noModel&range=weekly -GET /domains/:domainId/devices?sorting=top&type=noModel&range=monthly -GET /domains/:domainId/devices?sorting=top&type=noModel&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "devices", - "data": [ - { - "type": "device", - "data": { - "id": "Apple", - "count": 1 - } - } - ] -} -``` - -## Top devices with model - -Get the top 30 devices with the model. - -### Request - -``` -GET /domains/:domainId/devices?sorting=top&type=withModel -GET /domains/:domainId/devices?sorting=top&type=withModel&range=daily -GET /domains/:domainId/devices?sorting=top&type=withModel&range=weekly -GET /domains/:domainId/devices?sorting=top&type=withModel&range=monthly -GET /domains/:domainId/devices?sorting=top&type=withModel&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "devices", - "data": [ - { - "type": "device", - "data": { - "id": { - "deviceManufacturer": "Apple", - "deviceName": "iPad" - }, - "count": 1 - } - } - ] -} -``` - -## Recent devices without model - -Get the 30 most recent devices without the model. - -### Request - -``` -GET /domains/:domainId/devices?sorting=recent&type=noModel -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "devices", - "data": [ - { - "type": "device", - "data": { - "id": "Apple", - "created": "2019-09-19T15:54:00.020Z" - } - } - ] -} -``` - -## Recent devices with model - -Get the 30 most recent devices with the model. - -### Request - -``` -GET /domains/:domainId/devices?sorting=recent&type=withModel -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "devices", - "data": [ - { - "type": "device", - "data": { - "id": { - "deviceManufacturer": "Apple", - "deviceName": "iPad" - }, - "created": "2019-09-19T15:54:00.020Z" - } - } - ] -} -``` \ No newline at end of file diff --git a/docs/domains.md b/docs/domains.md deleted file mode 100644 index 74ecd563..00000000 --- a/docs/domains.md +++ /dev/null @@ -1,152 +0,0 @@ -# Domains - -- [Get all domains](#get-all-domains) -- [Add a domain](#add-a-domain) -- [Update a domain](#update-a-domain) -- [Delete a domain](#delete-a-domain) - -## Get all domains - -### Request - -``` -GET /domains -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "domains", - "data": [ - { - "type": "domain", - "data": { - "id": ":domainId", - "title": "Example", - "created": "1475491394341", - "updated": "1475491394341" - } - } - ] -} -``` - -## Add a domain - -### Request - -``` -POST /domains -``` - -```json -{ - "title": "Example" -} -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Parameters - -| Name | Type | Required | Description | -|:-----------|:------------|:------------|:------------| -| title | String | true | Title of the domain. | - -### Response - -``` -Status: 201 Created -Location: /domains/:domainId -``` - -```json -{ - "type": "domain", - "data": { - "id": ":domainId", - "title": "Example", - "created": "1475491394341", - "updated": "1475491394341" - } -} -``` - -## Update a domain - -### Request - -``` -PUT /domains/:domainId -``` - -```json -{ - "title": "Example" -} -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Parameters - -| Name | Type | Required | Description | -|:-----------|:------------|:------------|:------------| -| title | String | false | Title of the domain. | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "domain", - "data": { - "id": ":domainId", - "title": "Example", - "created": "1475491394341", - "updated": "1475491394341" - } -} -``` - -## Delete a domain - -### Request - -``` -DELETE /domains/:domainId -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 204 No Content -``` \ No newline at end of file diff --git a/docs/durations.md b/docs/durations.md deleted file mode 100644 index 75bb3361..00000000 --- a/docs/durations.md +++ /dev/null @@ -1,85 +0,0 @@ -# Durations - -- [Average durations](#average-durations) -- [Detailed durations](#detailed-durations) - -## Average durations - -Get the average time users spend on your site per day for the last 14 days. Days without entries are omitted. - -### Request - -``` -GET /domains/:domainId/durations?type=average -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "durations", - "data": [ - { - "type": "duration", - "data": { - "id": { - "day": 3, - "month": 10, - "year": 2016 - }, - "average": 20000 - } - } - ] -} -``` - -## Detailed durations - -Get the time users spend on your sites, grouped by similar durations in an interval of 15s. Includes data from the last 7 days. Durations above 30m will be grouped together. - -The included average is the average time users spend on your site for the last 7 days. Every item includes the same average. - -### Request - -``` -GET /domains/:domainId/durations?type=detailed -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "durations", - "data": [ - { - "type": "duration", - "data": { - "id": 20000, - "average": 20000, - "count": 1 - } - } - ] -} -``` \ No newline at end of file diff --git a/docs/languages.md b/docs/languages.md deleted file mode 100644 index ee6284a6..00000000 --- a/docs/languages.md +++ /dev/null @@ -1,82 +0,0 @@ -# Languages - -- [Top languages](#top-languages) -- [Recent languages](#recent-languages) - -## Top languages - -Get the top 30 user languages ([ISO-639-1 codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)). - -### Request - -``` -GET /domains/:domainId/languages?sorting=top -GET /domains/:domainId/languages?sorting=top&range=daily -GET /domains/:domainId/languages?sorting=top&range=weekly -GET /domains/:domainId/languages?sorting=top&range=monthly -GET /domains/:domainId/languages?sorting=top&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "languages", - "data": [ - { - "type": "language", - "data": { - "id": "de", - "count": 1 - } - } - ] -} -``` - -## Recent languages - -Get the 30 most recent user languages ([ISO-639-1 codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)). - -### Request - -``` -GET /domains/:domainId/languages?sorting=recent -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "languages", - "data": [ - { - "type": "language", - "data": { - "id": "de", - "created": "2019-09-19T15:54:00.020Z" - } - } - ] -} -``` \ No newline at end of file diff --git a/docs/pages.md b/docs/pages.md deleted file mode 100644 index 010e6dcf..00000000 --- a/docs/pages.md +++ /dev/null @@ -1,82 +0,0 @@ -# Pages - -- [Top pages](#top-pages) -- [Recent pages](#recent-pages) - -## Top pages - -Get the top 30 pages. - -### Request - -``` -GET /domains/:domainId/pages?sorting=top -GET /domains/:domainId/pages?sorting=top&range=daily -GET /domains/:domainId/pages?sorting=top&range=weekly -GET /domains/:domainId/pages?sorting=top&range=monthly -GET /domains/:domainId/pages?sorting=top&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "pages", - "data": [ - { - "type": "page", - "data": { - "id": "https://example.com/", - "count": 1 - } - } - ] -} -``` - -## Recent pages - -Get the 30 most recent page views. - -### Request - -``` -GET /domains/:domainId/pages?sorting=recent -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "pages", - "data": [ - { - "type": "page", - "data": { - "id": "https://example.com/", - "created": "2019-09-19T15:54:00.020Z" - } - } - ] -} -``` \ No newline at end of file diff --git a/docs/records.md b/docs/records.md deleted file mode 100644 index 3bfa52fd..00000000 --- a/docs/records.md +++ /dev/null @@ -1,141 +0,0 @@ -# Records - -- [Add a record](#add-a-record) -- [Update a record](#update-a-record) - -## Add a record - -Ackee uses the IP and user-agent to identify a user. A new record with an existing identification will remove all data from previous records, even when the new record contains less information than the previous record. - -### Request - -``` -POST /domains/:domainId/records -``` - -```json -{ - "siteLocation": "https://example.com/index.html", - "siteReferrer": "https://example.com/referrer.html", - "siteLanguage": "en", - "screenWidth": 2560, - "screenHeight": 1440, - "screenColorDepth": 32, - "deviceName": "iPad", - "deviceManufacturer": "Apple", - "osName": "iOS", - "osVersion": "9.0.1", - "browserName": "Safari", - "browserVersion": "9.0.1", - "browserWidth": 1000, - "browserHeight": 900 -} -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Parameters - -| Name | Type | Required | Description | -|:-----------|:------------|:------------|:------------| -| siteLocation | String | true | URL of the site. | -| siteReferrer | String | false | URL of the document that loaded the current document. | -| siteLanguage | String | false | Language version of the browser. | -| screenWidth | Number | false | The width of the screen in pixels. | -| screenHeight | Number | false | The height of the screen in pixels. | -| screenColorDepth | Number | false | The bit depth of the color palette for displaying images (in bits per pixel). | -| deviceName | String | false | The name of the product hosting the browser. | -| deviceManufacturer | String | false | The name of the product's manufacturer. | -| osName | String | false | The family of the OS. | -| osVersion | String | false | The version of the OS. | -| browserName | String | false | The name of the browser/environment. | -| browserVersion | String | false | The browser/environment version. | -| browserWidth | Number | false | The width of the screen in pixels. | -| browserHeight | Number | false | The height of the screen in pixels. | - -### Response - -``` -Status: 201 Created -Location: /domains/:domainId/records/:recordId -``` - -```json -{ - "type": "record", - "data": { - "id": ":recordId", - "domainId": ":domainId", - "siteLocation": "https://example.com/index.html", - "siteReferrer": "https://example.com/referrer.html", - "siteLanguage": "en", - "screenWidth": 2560, - "screenHeight": 1440, - "screenColorDepth": 32, - "deviceName": "iPad", - "deviceManufacturer": "Apple", - "osName": "iOS", - "osVersion": "9.0.1", - "browserName": "Safari", - "browserVersion": "9.0.1", - "browserWidth": 1000, - "browserHeight": 900, - "created": "1475491394341", - "updated": "1475491394341" - } -} -``` - -## Update a record - -It's not possible to update attributes of a record. An record PATCH will only update `updated`, which is used to determine the time a user spent on a page. - -The response might contain less data than initially added to the record. That's the case when a record has been anonymized, after a new record with an existing user identification has been added. - -### Request - -``` -PATCH /domains/:domainId/records/:recordId -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "record", - "data": { - "id": ":recordId", - "domainId": ":domainId", - "siteLocation": "https://example.com/index.html", - "siteReferrer": "https://example.com/referrer.html", - "siteLanguage": "en", - "screenWidth": 2560, - "screenHeight": 1440, - "screenColorDepth": 32, - "deviceName": "iPad", - "deviceManufacturer": "Apple", - "osName": "iOS", - "osVersion": "9.0.1", - "browserName": "Safari", - "browserVersion": "9.0.1", - "browserWidth": 1000, - "browserHeight": 900, - "created": "1475491394341", - "updated": "1475491394341" - } -} -``` \ No newline at end of file diff --git a/docs/referrers.md b/docs/referrers.md deleted file mode 100644 index 58a37f9a..00000000 --- a/docs/referrers.md +++ /dev/null @@ -1,121 +0,0 @@ -# Referrers - -- [Top referrers](#top-referrers) -- [New referrers](#new-referrers) -- [Recent referrers](#recent-referrers) - -## Top referrers - -Get the top 30 referrers. - -### Request - -``` -GET /domains/:domainId/referrers?sorting=top -GET /domains/:domainId/referrers?sorting=top&range=daily -GET /domains/:domainId/referrers?sorting=top&range=weekly -GET /domains/:domainId/referrers?sorting=top&range=monthly -GET /domains/:domainId/referrers?sorting=top&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "referrers", - "data": [ - { - "type": "referrer", - "data": { - "id": "https://www.example.com/", - "count": 1 - } - } - ] -} -``` - -## New referrers - -Get the 30 most recent referrers who have linked to your site for the first time. - -### Request - -``` -GET /domains/:domainId/referrers?sorting=new -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "referrers", - "data": [ - { - "type": "referrer", - "data": { - "id": "https://www.example.com/", - "count": 1, - "created": "2019-09-19T15:54:00.020Z" - } - } - ] -} -``` - -## Recent referrers - -Get the 30 most recent referrers. - -### Request - -``` -GET /domains/:domainId/referrers?sorting=recent -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "referrers", - "data": [ - { - "type": "referrer", - "data": { - "id": "https://www.example.com/", - "created": "2019-09-19T15:54:00.020Z" - } - } - ] -} -``` \ No newline at end of file diff --git a/docs/sizes.md b/docs/sizes.md deleted file mode 100644 index 003a4df5..00000000 --- a/docs/sizes.md +++ /dev/null @@ -1,260 +0,0 @@ -# Sizes - -- [Browser resolutions](#browser-resolutions) -- [Browser widths](#browser-widths) -- [Browser heights](#browser-heights) -- [Screen resolutions](#screen-resolutions) -- [Screen widths](#screen-widths) -- [Screen heights](#screen-heights) - -## Browser resolutions - -Get the top 30 browser resolutions. - -### Request - -``` -GET /domains/:domainId/sizes?type=browser_resolution -GET /domains/:domainId/sizes?type=browser_resolution&range=daily -GET /domains/:domainId/sizes?type=browser_resolution&range=weekly -GET /domains/:domainId/sizes?type=browser_resolution&range=monthly -GET /domains/:domainId/sizes?type=browser_resolution&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "sizes", - "data": [ - { - "type": "size", - "data": { - "id": { - "browserWidth": "1920", - "browserHeight": "1080" - }, - "count": 1 - } - } - ] -} -``` - -## Browser widths - -Get the top 30 browser widths. - -### Request - -``` -GET /domains/:domainId/sizes?type=browser_width -GET /domains/:domainId/sizes?type=browser_width&range=daily -GET /domains/:domainId/sizes?type=browser_width&range=weekly -GET /domains/:domainId/sizes?type=browser_width&range=monthly -GET /domains/:domainId/sizes?type=browser_width&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "sizes", - "data": [ - { - "type": "size", - "data": { - "id": "1920", - "count": 1 - } - } - ] -} -``` - -## Browser heights - -Get the top 30 browser heights. - -### Request - -``` -GET /domains/:domainId/sizes?type=browser_height -GET /domains/:domainId/sizes?type=browser_height&range=daily -GET /domains/:domainId/sizes?type=browser_height&range=weekly -GET /domains/:domainId/sizes?type=browser_height&range=monthly -GET /domains/:domainId/sizes?type=browser_height&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "sizes", - "data": [ - { - "type": "size", - "data": { - "id": "1080", - "count": 1 - } - } - ] -} -``` - -## Screen resolutions - -Get the top 30 screen resolutions. - -### Request - -``` -GET /domains/:domainId/sizes?type=screen_resolution -GET /domains/:domainId/sizes?type=screen_resolution&range=daily -GET /domains/:domainId/sizes?type=screen_resolution&range=weekly -GET /domains/:domainId/sizes?type=screen_resolution&range=monthly -GET /domains/:domainId/sizes?type=screen_resolution&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "sizes", - "data": [ - { - "type": "size", - "data": { - "id": { - "screenWidth": "1920", - "screenHeight": "1080" - }, - "count": 1 - } - } - ] -} -``` - -## Screen widths - -Get the top 30 screen widths. - -### Request - -``` -GET /domains/:domainId/sizes?type=screen_width -GET /domains/:domainId/sizes?type=screen_width&range=daily -GET /domains/:domainId/sizes?type=screen_width&range=weekly -GET /domains/:domainId/sizes?type=screen_width&range=monthly -GET /domains/:domainId/sizes?type=screen_width&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "sizes", - "data": [ - { - "type": "size", - "data": { - "id": "1920", - "count": 1 - } - } - ] -} -``` - -## Screen heights - -Get the top 30 screen heights. - -### Request - -``` -GET /domains/:domainId/sizes?type=height -GET /domains/:domainId/sizes?type=height&range=daily -GET /domains/:domainId/sizes?type=height&range=weekly -GET /domains/:domainId/sizes?type=height&range=monthly -GET /domains/:domainId/sizes?type=height&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "sizes", - "data": [ - { - "type": "size", - "data": { - "id": "1080", - "count": 1 - } - } - ] -} -``` \ No newline at end of file diff --git a/docs/systems.md b/docs/systems.md deleted file mode 100644 index a3134acf..00000000 --- a/docs/systems.md +++ /dev/null @@ -1,168 +0,0 @@ -# Systems - -- [Top systems without version](#top-systems-without-version) -- [Top systems with version](#top-systems-with-version) -- [Recent systems without version](#recent-systems-without-version) -- [Recent systems with version](#recent-systems-with-version) - -## Top systems without version - -Get the top 30 systems without the version. - -### Request - -``` -GET /domains/:domainId/systems?sorting=top&type=noVersion -GET /domains/:domainId/systems?sorting=top&type=noVersion&range=daily -GET /domains/:domainId/systems?sorting=top&type=noVersion&range=weekly -GET /domains/:domainId/systems?sorting=top&type=noVersion&range=monthly -GET /domains/:domainId/systems?sorting=top&type=noVersion&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "systems", - "data": [ - { - "type": "system", - "data": { - "id": "Windows", - "count": 1 - } - } - ] -} -``` - -## Top systems with version - -Get the top 30 systems with the version. - -### Request - -``` -GET /domains/:domainId/systems?sorting=top&type=withVersion -GET /domains/:domainId/systems?sorting=top&type=withVersion&range=daily -GET /domains/:domainId/systems?sorting=top&type=withVersion&range=weekly -GET /domains/:domainId/systems?sorting=top&type=withVersion&range=monthly -GET /domains/:domainId/systems?sorting=top&type=withVersion&range=allTime -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "systems", - "data": [ - { - "type": "system", - "data": { - "id": { - "osName": "Windows", - "osVersion": "7" - }, - "count": 1 - } - } - ] -} -``` - -## Recent systems without version - -Get the 30 most recent systems without the version. - -### Request - -``` -GET /domains/:domainId/systems?sorting=recent&type=noVersion -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "systems", - "data": [ - { - "type": "system", - "data": { - "id": "Windows", - "created": "2019-09-19T15:54:00.020Z" - } - } - ] -} -``` - -## Recent systems with version - -Get the 30 most recent systems with the version. - -### Request - -``` -GET /domains/:domainId/systems?sorting=recent&type=withVersion -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "systems", - "data": [ - { - "type": "system", - "data": { - "id": { - "osName": "Windows", - "osVersion": "7" - }, - "created": "2019-09-19T15:54:00.020Z" - } - } - ] -} -``` \ No newline at end of file diff --git a/docs/tokens.md b/docs/tokens.md deleted file mode 100644 index 9883ef70..00000000 --- a/docs/tokens.md +++ /dev/null @@ -1,60 +0,0 @@ -# Tokens - -- [Create a token](#create-a-token) -- [Delete a token](#delete-a-token) - -## Create a token - -A token stays valid for as long as specified in the [TTL option](Options.md#ttl). Using a token will reset the timeout. - -### Request - -``` -POST /tokens -``` - -```json -{ - "username": "username", - "password": "password" -} -``` - -### Parameters - -| Name | Type | Required | Description | -|:-----------|:------------|:------------|:------------| -| username | String | true | [Username of Ackee](Options.md#username-and-password). | -| password | String | true | [Password of Ackee](Options.md#username-and-password). | - -### Response - -``` -Status: 201 Created -Location: /tokens/:tokenId -``` - -```json -{ - "type": "token", - "data": { - "id": ":tokenId", - "created": "1526999812", - "updated": "1526999812" - } -} -``` - -## Delete a token - -### Request - -``` -DELETE /tokens/:tokenId -``` - -### Response - -``` -Status: 204 No Content -``` \ No newline at end of file diff --git a/docs/views.md b/docs/views.md deleted file mode 100644 index 8ba45d77..00000000 --- a/docs/views.md +++ /dev/null @@ -1,90 +0,0 @@ -# Views - -- [Unique site views](#unique-site-views) -- [Total page views](#total-page-views) - -## Unique site views - -Get the unique amount of visits per day, month or year for the last 14 intervals. Entries without views are omitted. A user is unique when he visits a site for the first time a day. - -### Request - -``` -GET /domains/:domainId/views?type=unique&interval=daily -GET /domains/:domainId/views?type=unique&interval=monthly -GET /domains/:domainId/views?type=unique&interval=yearly -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "views", - "data": [ - { - "type": "view", - "data": { - "id": { - "day": 3, - "month": 10, - "year": 2016 - }, - "count": 1 - } - } - ] -} -``` - -## Total page views - -Get the total amount of visits per day, month or year for the last 14 intervals. Entries without views are omitted. - -### Request - -``` -GET /domains/:domainId/views?type=total&interval=daily -GET /domains/:domainId/views?type=total&interval=monthly -GET /domains/:domainId/views?type=total&interval=yearly -``` - -### Headers - -| Name | Example | -|:-----------|:------------| -| Authorization | `Authorization: Bearer :tokenId` | - -### Response - -``` -Status: 200 OK -``` - -```json -{ - "type": "views", - "data": [ - { - "type": "view", - "data": { - "id": { - "day": 3, - "month": 10, - "year": 2016 - }, - "count": 1 - } - } - ] -} -``` \ No newline at end of file diff --git a/package.json b/package.json index be4fafc3..8255fd40 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ackee", "private": true, - "version": "1.7.1", + "version": "2.0.0", "authors": [ "Tobias Reich " ], @@ -24,7 +24,7 @@ }, "scripts": { "start": "node src/index.js", - "dev": "NODE_ENV=development nodemon", + "start:dev": "NODE_ENV=development nodemon", "coveralls": "nyc report --reporter=text-lcov | coveralls", "test": "nyc ava", "lint": "eslint '{src,test}/**/*.js'" @@ -34,18 +34,25 @@ "extends": "@electerious/eslint-config" }, "dependencies": { - "@babel/core": "^7.9.6", - "@babel/preset-env": "^7.9.6", - "ackee-tracker": "^3.2.3", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "ackee-tracker": "^4.0.0", + "apollo-server-micro": "^2.16.1", "classnames": "^2.2.6", - "date-fns": "^2.13.0", + "date-fns": "^2.15.0", + "date-fns-tz": "^1.0.10", + "debounce-promise": "^3.1.2", "dotenv": "^8.2.0", "formbase": "^12.0.1", - "immer": "^6.0.5", + "graphql": "^15.3.0", + "graphql-scalars": "^1.2.6", + "graphql-tools": "^6.0.18", + "human-number": "^1.0.5", + "immer": "^7.0.7", "is-url": "^1.2.4", "micro": "^9.3.4", "microrouter": "^3.1.3", - "mongoose": "^5.9.13", + "mongoose": "^5.10.0", "node-fetch": "^2.6.0", "node-schedule": "^1.3.2", "normalize-url": "^5.0.0", @@ -54,33 +61,34 @@ "prop-types": "^15.7.2", "react": "^16.13.1", "react-dom": "^16.13.1", - "react-error-boundary": "^2.2.1", - "react-fast-compare": "^3.1.1", - "react-redux": "^7.2.0", - "react-use": "^14.2.0", + "react-error-boundary": "^2.3.1", + "react-fast-compare": "^3.2.0", + "react-hotkeys-hook": "^2.2.2", + "react-redux": "^7.2.1", + "react-use": "^15.3.3", "redux": "^4.0.5", "redux-devtools-extension": "^2.13.8", "redux-thunk": "^2.3.0", "request-ip": "^2.1.3", "rosid-handler-js": "^13.0.0", "rosid-handler-sass": "^7.0.0", - "s-ago": "^2.1.0", + "s-ago": "^2.2.0", "shortid": "^2.2.15", "signale": "^1.4.0", - "uuid": "^8.0.0" + "uuid": "^8.3.0" }, "devDependencies": { "@electerious/eslint-config": "^1.3.4", - "ava": "3.8.2", + "ava": "3.11.1", "coveralls": "^3.1.0", - "eslint": "^7.0.0", - "eslint-plugin-import": "^2.20.2", - "eslint-plugin-react": "^7.19.0", - "eslint-plugin-react-hooks": "^4.0.0", + "eslint": "^7.7.0", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-react": "^7.20.6", + "eslint-plugin-react-hooks": "^4.0.8", "eslint-plugin-react-native": "^3.8.1", "mocked-env": "^1.3.2", - "nodemon": "^2.0.3", - "nyc": "^15.0.1", + "nodemon": "^2.0.4", + "nyc": "^15.1.0", "test-listen": "^1.1.0" }, "ava": { @@ -91,6 +99,7 @@ } }, "nodemonConfig": { + "ext": "js,json,graphql", "ignore": [ "data/*", "docs/*", diff --git a/src/aggregations/aggregateActiveVisitors.js b/src/aggregations/aggregateActiveVisitors.js new file mode 100644 index 00000000..b2734391 --- /dev/null +++ b/src/aggregations/aggregateActiveVisitors.js @@ -0,0 +1,23 @@ +'use strict' + +const { DURATIONS_LIMIT, DURATIONS_INTERVAL } = require('../constants/durations') +const matchDomains = require('../stages/matchDomains') + +module.exports = (ids, dateDetails) => { + + const aggregation = [ + matchDomains(ids), + { + $count: 'count' + } + ] + + // Ignore users that are on the page for too long + aggregation[0].$match.created = { $gte: dateDetails.lastMilliseconds(DURATIONS_LIMIT) } + + // Ignore users that aren't active anymore + aggregation[0].$match.updated = { $gte: dateDetails.lastMilliseconds(DURATIONS_INTERVAL * 2) } + + return aggregation + +} \ No newline at end of file diff --git a/src/aggregations/aggregateDailyViews.js b/src/aggregations/aggregateDailyViews.js deleted file mode 100644 index ffb6a031..00000000 --- a/src/aggregations/aggregateDailyViews.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict' - -module.exports = (id, unique) => { - - const aggregation = [ - { - $match: { - domainId: id - } - }, - { - $group: { - _id: { - day: { - $dayOfMonth: '$created' - }, - month: { - $month: '$created' - }, - year: { - $year: '$created' - } - }, - count: { - $sum: 1 - } - } - }, - { - $sort: { - '_id.year': -1, - '_id.month': -1, - '_id.day': -1 - } - }, - { - $limit: 14 - } - ] - - if (unique === true) aggregation[0].$match.clientId = { - $exists: true, - $ne: null - } - - return aggregation - -} \ No newline at end of file diff --git a/src/aggregations/aggregateDurations.js b/src/aggregations/aggregateDurations.js new file mode 100644 index 00000000..68829564 --- /dev/null +++ b/src/aggregations/aggregateDurations.js @@ -0,0 +1,55 @@ +'use strict' + +const intervals = require('../constants/intervals') +const matchDomains = require('../stages/matchDomains') +const projectDuration = require('../stages/projectDuration') +const projectMinInterval = require('../stages/projectMinInterval') +const matchLimit = require('../stages/matchLimit') + +module.exports = (ids, interval, limit, dateDetails) => { + + const aggregation = [ + matchDomains(ids), + projectDuration(), + projectMinInterval(), + matchLimit(), + { + $group: { + _id: {}, + count: { + $avg: '$duration' + } + } + }, + { + $sort: { + '_id.year': -1, + '_id.month': -1, + '_id.day': -1 + } + } + ] + + const dateExpression = { date: '$created', timezone: dateDetails.userTimeZone } + + if (interval === intervals.INTERVALS_DAILY) { + aggregation[0].$match.created = { $gte: dateDetails.includeDays(limit) } + aggregation[4].$group._id.day = { $dayOfMonth: dateExpression } + aggregation[4].$group._id.month = { $month: dateExpression } + aggregation[4].$group._id.year = { $year: dateExpression } + } + + if (interval === intervals.INTERVALS_MONTHLY) { + aggregation[0].$match.created = { $gte: dateDetails.includeMonths(limit) } + aggregation[4].$group._id.month = { $month: dateExpression } + aggregation[4].$group._id.year = { $year: dateExpression } + } + + if (interval === intervals.INTERVALS_YEARLY) { + aggregation[0].$match.created = { $gte: dateDetails.includeYears(limit) } + aggregation[4].$group._id.year = { $year: dateExpression } + } + + return aggregation + +} \ No newline at end of file diff --git a/src/aggregations/aggregateMonthlyViews.js b/src/aggregations/aggregateMonthlyViews.js deleted file mode 100644 index 3fb33bfb..00000000 --- a/src/aggregations/aggregateMonthlyViews.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict' - -module.exports = (id, unique) => { - - const aggregation = [ - { - $match: { - domainId: id - } - }, - { - $group: { - _id: { - month: { - $month: '$created' - }, - year: { - $year: '$created' - } - }, - count: { - $sum: 1 - } - } - }, - { - $sort: { - '_id.year': -1, - '_id.month': -1 - } - }, - { - $limit: 14 - } - ] - - if (unique === true) aggregation[0].$match.clientId = { - $exists: true, - $ne: null - } - - return aggregation - -} \ No newline at end of file diff --git a/src/aggregations/aggregateNewFields.js b/src/aggregations/aggregateNewFields.js index 8ed8c2c5..ea34b719 100644 --- a/src/aggregations/aggregateNewFields.js +++ b/src/aggregations/aggregateNewFields.js @@ -1,31 +1,37 @@ 'use strict' -module.exports = (id, property) => [ - { - $match: { - domainId: id, - [property]: { - $ne: null +const matchDomains = require('../stages/matchDomains') + +module.exports = (ids, properties, limit) => { + + const aggregation = [ + matchDomains(ids), + { + $group: { + _id: {}, + count: { + $sum: 1 + }, + created: { + $first: '$created' + } } - } - }, - { - $group: { - _id: `$${ property }`, - count: { - $sum: 1 - }, - created: { - $first: '$created' + }, + { + $sort: { + created: -1 } + }, + { + $limit: limit } - }, - { - $sort: { - created: -1 - } - }, - { - $limit: 30 - } -] \ No newline at end of file + ] + + properties.forEach((property) => { + aggregation[0].$match[property] = { $ne: null } + aggregation[1].$group._id[property] = `$${ property }` + }) + + return aggregation + +} \ No newline at end of file diff --git a/src/aggregations/aggregateRecentFields.js b/src/aggregations/aggregateRecentFields.js index f4a89855..0bac2762 100644 --- a/src/aggregations/aggregateRecentFields.js +++ b/src/aggregations/aggregateRecentFields.js @@ -1,26 +1,32 @@ 'use strict' -module.exports = (id, property) => [ - { - $match: { - domainId: id, - [property]: { - $ne: null +const matchDomains = require('../stages/matchDomains') + +module.exports = (ids, properties, limit) => { + + const aggregation = [ + matchDomains(ids), + { + $sort: { + created: -1 } + }, + { + $project: { + _id: {}, + created: '$created' + } + }, + { + $limit: limit } - }, - { - $sort: { - created: -1 - } - }, - { - $project: { - _id: `$${ property }`, - created: '$created' - } - }, - { - $limit: 30 - } -] \ No newline at end of file + ] + + properties.forEach((property) => { + aggregation[0].$match[property] = { $ne: null } + aggregation[2].$project._id[property] = `$${ property }` + }) + + return aggregation + +} \ No newline at end of file diff --git a/src/aggregations/aggregateRecentFieldsMultiple.js b/src/aggregations/aggregateRecentFieldsMultiple.js deleted file mode 100644 index 477f13a9..00000000 --- a/src/aggregations/aggregateRecentFieldsMultiple.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' - -module.exports = (id, properties) => { - - const aggregate = [ - { - $match: { - domainId: id - } - }, - { - $sort: { - created: -1 - } - }, - { - $project: { - _id: {}, - created: '$created' - } - }, - { - $limit: 30 - } - ] - - properties.forEach((property) => { - aggregate[0].$match[property] = { $ne: null } - aggregate[2].$project._id[property] = `$${ property }` - }) - - return aggregate - -} \ No newline at end of file diff --git a/src/aggregations/aggregateTopFields.js b/src/aggregations/aggregateTopFields.js index ca2f5c44..e294f9ab 100644 --- a/src/aggregations/aggregateTopFields.js +++ b/src/aggregations/aggregateTopFields.js @@ -1,21 +1,15 @@ 'use strict' -const offsetByRange = require('../utils/offsetByRange') +const ranges = require('../constants/ranges') +const matchDomains = require('../stages/matchDomains') -module.exports = (id, property, range) => { +module.exports = (ids, properties, range, limit, dateDetails) => { - const aggregate = [ - { - $match: { - domainId: id, - [property]: { - $ne: null - } - } - }, + const aggregation = [ + matchDomains(ids), { $group: { - _id: `$${ property }`, + _id: {}, count: { $sum: 1 } @@ -27,15 +21,31 @@ module.exports = (id, property, range) => { } }, { - $limit: 30 + $limit: limit } ] - const dateOffset = offsetByRange(range) - if (dateOffset != null) { - aggregate[0].$match.created = { $gte: dateOffset } + properties.forEach((property) => { + aggregation[0].$match[property] = { $ne: null } + aggregation[1].$group._id[property] = `$${ property }` + }) + + if (range === ranges.RANGES_LAST_24_HOURS) { + aggregation[0].$match.created = { $gte: dateDetails.lastHours(24) } + } + + if (range === ranges.RANGES_LAST_7_DAYS) { + aggregation[0].$match.created = { $gte: dateDetails.lastDays(7) } + } + + if (range === ranges.RANGES_LAST_30_DAYS) { + aggregation[0].$match.created = { $gte: dateDetails.lastDays(30) } + } + + if (range === ranges.RANGES_LAST_6_MONTHS) { + aggregation[0].$match.created = { $gte: dateDetails.lastMonths(6) } } - return aggregate + return aggregation } \ No newline at end of file diff --git a/src/aggregations/aggregateTopFieldsMultiple.js b/src/aggregations/aggregateTopFieldsMultiple.js deleted file mode 100644 index 575f1de3..00000000 --- a/src/aggregations/aggregateTopFieldsMultiple.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict' - -const offsetByRange = require('../utils/offsetByRange') - -module.exports = (id, properties, range) => { - - const aggregate = [ - { - $match: { - domainId: id - } - }, - { - $group: { - _id: {}, - count: { - $sum: 1 - } - } - }, - { - $sort: { - count: -1 - } - }, - { - $limit: 30 - } - ] - - properties.forEach((property) => { - aggregate[0].$match[property] = { $ne: null } - aggregate[1].$group._id[property] = `$${ property }` - }) - - const dateOffset = offsetByRange(range) - if (dateOffset != null) { - aggregate[0].$match.created = { $gte: dateOffset } - } - - return aggregate - -} \ No newline at end of file diff --git a/src/aggregations/aggregateViews.js b/src/aggregations/aggregateViews.js new file mode 100644 index 00000000..abd1846b --- /dev/null +++ b/src/aggregations/aggregateViews.js @@ -0,0 +1,55 @@ +'use strict' + +const intervals = require('../constants/intervals') +const matchDomains = require('../stages/matchDomains') + +module.exports = (ids, unique, interval, limit, dateDetails) => { + + const aggregation = [ + matchDomains(ids), + { + $group: { + _id: {}, + count: { + $sum: 1 + } + } + }, + { + $sort: { + '_id.year': -1, + '_id.month': -1, + '_id.day': -1 + } + } + ] + + + if (unique === true) aggregation[0].$match.clientId = { + $exists: true, + $ne: null + } + + const dateExpression = { date: '$created', timezone: dateDetails.userTimeZone } + + if (interval === intervals.INTERVALS_DAILY) { + aggregation[0].$match.created = { $gte: dateDetails.includeDays(limit) } + aggregation[1].$group._id.day = { $dayOfMonth: dateExpression } + aggregation[1].$group._id.month = { $month: dateExpression } + aggregation[1].$group._id.year = { $year: dateExpression } + } + + if (interval === intervals.INTERVALS_MONTHLY) { + aggregation[0].$match.created = { $gte: dateDetails.includeMonths(limit) } + aggregation[1].$group._id.month = { $month: dateExpression } + aggregation[1].$group._id.year = { $year: dateExpression } + } + + if (interval === intervals.INTERVALS_YEARLY) { + aggregation[0].$match.created = { $gte: dateDetails.includeYears(limit) } + aggregation[1].$group._id.year = { $year: dateExpression } + } + + return aggregation + +} \ No newline at end of file diff --git a/src/aggregations/aggregateYearlyViews.js b/src/aggregations/aggregateYearlyViews.js deleted file mode 100644 index 10746e17..00000000 --- a/src/aggregations/aggregateYearlyViews.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict' - -module.exports = (id, unique) => { - - const aggregation = [ - { - $match: { - domainId: id - } - }, - { - $group: { - _id: { - year: { - $year: '$created' - } - }, - count: { - $sum: 1 - } - } - }, - { - $sort: { - '_id.day': -1 - } - }, - { - $limit: 14 - } - ] - - if (unique === true) aggregation[0].$match.clientId = { - $exists: true, - $ne: null - } - - return aggregation - -} \ No newline at end of file diff --git a/src/constants/browsers.js b/src/constants/browsers.js index bdd9e873..832a49e8 100644 --- a/src/constants/browsers.js +++ b/src/constants/browsers.js @@ -1,13 +1,9 @@ -// Constants will be shared between client and server. -// They will be used as values in the DOM and in the URL of the referrer calls. -const BROWSERS_SORTING_TOP = 'top' -const BROWSERS_SORTING_RECENT = 'recent' -const BROWSERS_TYPE_WITH_VERSION = 'withVersion' -const BROWSERS_TYPE_NO_VERSION = 'noVersion' +'use strict' + +const BROWSERS_TYPE_WITH_VERSION = 'WITH_VERSION' +const BROWSERS_TYPE_NO_VERSION = 'NO_VERSION' module.exports = { - BROWSERS_SORTING_TOP, - BROWSERS_SORTING_RECENT, BROWSERS_TYPE_WITH_VERSION, BROWSERS_TYPE_NO_VERSION } \ No newline at end of file diff --git a/src/constants/devices.js b/src/constants/devices.js index 21707491..558bccb3 100644 --- a/src/constants/devices.js +++ b/src/constants/devices.js @@ -1,13 +1,9 @@ -// Constants will be shared between client and server. -// They will be used as values in the DOM and in the URL of the referrer calls. -const DEVICES_SORTING_TOP = 'top' -const DEVICES_SORTING_RECENT = 'recent' -const DEVICES_TYPE_WITH_MODEL = 'withModel' -const DEVICES_TYPE_NO_MODEL = 'noModel' +'use strict' + +const DEVICES_TYPE_WITH_MODEL = 'WITH_MODEL' +const DEVICES_TYPE_NO_MODEL = 'NO_MODEL' module.exports = { - DEVICES_SORTING_TOP, - DEVICES_SORTING_RECENT, DEVICES_TYPE_WITH_MODEL, DEVICES_TYPE_NO_MODEL } \ No newline at end of file diff --git a/src/constants/durations.js b/src/constants/durations.js index 45a21f97..95a0bb36 100644 --- a/src/constants/durations.js +++ b/src/constants/durations.js @@ -1,15 +1,11 @@ +'use strict' + const { hour } = require('../utils/times') -// Constants will be shared between client and server. -// They will be used as values in the DOM and in the URL of the views calls. const DURATIONS_INTERVAL = 15000 const DURATIONS_LIMIT = hour / 2 -const DURATIONS_TYPE_AVERAGE = 'average' -const DURATIONS_TYPE_DETAILED = 'detailed' module.exports = { DURATIONS_INTERVAL, - DURATIONS_LIMIT, - DURATIONS_TYPE_AVERAGE, - DURATIONS_TYPE_DETAILED + DURATIONS_LIMIT } \ No newline at end of file diff --git a/src/constants/intervals.js b/src/constants/intervals.js new file mode 100644 index 00000000..7cec87f0 --- /dev/null +++ b/src/constants/intervals.js @@ -0,0 +1,11 @@ +'use strict' + +const INTERVALS_DAILY = 'DAILY' +const INTERVALS_MONTHLY = 'MONTHLY' +const INTERVALS_YEARLY = 'YEARLY' + +module.exports = { + INTERVALS_DAILY, + INTERVALS_MONTHLY, + INTERVALS_YEARLY +} \ No newline at end of file diff --git a/src/constants/languages.js b/src/constants/languages.js deleted file mode 100644 index 6af493ed..00000000 --- a/src/constants/languages.js +++ /dev/null @@ -1,9 +0,0 @@ -// Constants will be shared between client and server. -// They will be used as values in the DOM and in the URL of the referrer calls. -const LANGUAGES_SORTING_TOP = 'top' -const LANGUAGES_SORTING_RECENT = 'recent' - -module.exports = { - LANGUAGES_SORTING_TOP, - LANGUAGES_SORTING_RECENT -} \ No newline at end of file diff --git a/src/constants/pages.js b/src/constants/pages.js deleted file mode 100644 index f48900c0..00000000 --- a/src/constants/pages.js +++ /dev/null @@ -1,9 +0,0 @@ -// Constants will be shared between client and server. -// They will be used as values in the DOM and in the URL of the referrer calls. -const PAGES_SORTING_TOP = 'top' -const PAGES_SORTING_RECENT = 'recent' - -module.exports = { - PAGES_SORTING_TOP, - PAGES_SORTING_RECENT -} \ No newline at end of file diff --git a/src/constants/ranges.js b/src/constants/ranges.js index 466f64ce..39462694 100644 --- a/src/constants/ranges.js +++ b/src/constants/ranges.js @@ -1,21 +1,13 @@ -// Constants will be shared between client and server. -// They will be used as values in the DOM and in the URL of the referrer calls. -const RANGES_LAST_24_HOURS = 'daily' -const RANGES_LAST_7_DAYS = 'weekly' -const RANGES_LAST_30_DAYS = 'monthly' -const RANGES_ALL_TIME = 'allTime' +'use strict' -const toArray = () => [ - RANGES_LAST_24_HOURS, - RANGES_LAST_7_DAYS, - RANGES_LAST_30_DAYS, - RANGES_ALL_TIME -] +const RANGES_LAST_24_HOURS = 'LAST_24_HOURS' +const RANGES_LAST_7_DAYS = 'LAST_7_DAYS' +const RANGES_LAST_30_DAYS = 'LAST_30_DAYS' +const RANGES_LAST_6_MONTHS = 'LAST_6_MONTHS' module.exports = { RANGES_LAST_24_HOURS, RANGES_LAST_7_DAYS, RANGES_LAST_30_DAYS, - RANGES_ALL_TIME, - toArray + RANGES_LAST_6_MONTHS } \ No newline at end of file diff --git a/src/constants/referrers.js b/src/constants/referrers.js deleted file mode 100644 index 12b6d5dd..00000000 --- a/src/constants/referrers.js +++ /dev/null @@ -1,11 +0,0 @@ -// Constants will be shared between client and server. -// They will be used as values in the DOM and in the URL of the referrer calls. -const REFERRERS_SORTING_TOP = 'top' -const REFERRERS_SORTING_NEW = 'new' -const REFERRERS_SORTING_RECENT = 'recent' - -module.exports = { - REFERRERS_SORTING_TOP, - REFERRERS_SORTING_NEW, - REFERRERS_SORTING_RECENT -} \ No newline at end of file diff --git a/src/constants/sizes.js b/src/constants/sizes.js index 6f242baf..c02fd80f 100644 --- a/src/constants/sizes.js +++ b/src/constants/sizes.js @@ -1,11 +1,11 @@ -// Constants will be shared between client and server. -// They will be used as values in the DOM and in the URL of the referrer calls. -const SIZES_TYPE_BROWSER_HEIGHT = 'browser_height' -const SIZES_TYPE_BROWSER_RESOLUTION = 'browser_resolution' -const SIZES_TYPE_BROWSER_WIDTH = 'browser_width' -const SIZES_TYPE_SCREEN_HEIGHT = 'screen_height' -const SIZES_TYPE_SCREEN_RESOLUTION = 'screen_resolution' -const SIZES_TYPE_SCREEN_WIDTH = 'screen_width' +'use strict' + +const SIZES_TYPE_BROWSER_HEIGHT = 'BROWSER_HEIGHT' +const SIZES_TYPE_BROWSER_RESOLUTION = 'BROWSER_RESOLUTION' +const SIZES_TYPE_BROWSER_WIDTH = 'BROWSER_WIDTH' +const SIZES_TYPE_SCREEN_HEIGHT = 'SCREEN_HEIGHT' +const SIZES_TYPE_SCREEN_RESOLUTION = 'SCREEN_RESOLUTION' +const SIZES_TYPE_SCREEN_WIDTH = 'SCREEN_WIDTH' module.exports = { SIZES_TYPE_BROWSER_HEIGHT, diff --git a/src/constants/sortings.js b/src/constants/sortings.js new file mode 100644 index 00000000..9389998d --- /dev/null +++ b/src/constants/sortings.js @@ -0,0 +1,11 @@ +'use strict' + +const SORTINGS_TOP = 'TOP' +const SORTINGS_NEW = 'NEW' +const SORTINGS_RECENT = 'RECENT' + +module.exports = { + SORTINGS_TOP, + SORTINGS_NEW, + SORTINGS_RECENT +} \ No newline at end of file diff --git a/src/constants/systems.js b/src/constants/systems.js index a4e84ada..781ae3aa 100644 --- a/src/constants/systems.js +++ b/src/constants/systems.js @@ -1,13 +1,9 @@ -// Constants will be shared between client and server. -// They will be used as values in the DOM and in the URL of the referrer calls. -const SYSTEMS_SORTING_TOP = 'top' -const SYSTEMS_SORTING_RECENT = 'recent' -const SYSTEMS_TYPE_WITH_VERSION = 'withVersion' -const SYSTEMS_TYPE_NO_VERSION = 'noVersion' +'use strict' + +const SYSTEMS_TYPE_WITH_VERSION = 'WITH_VERSION' +const SYSTEMS_TYPE_NO_VERSION = 'NO_VERSION' module.exports = { - SYSTEMS_SORTING_TOP, - SYSTEMS_SORTING_RECENT, SYSTEMS_TYPE_WITH_VERSION, SYSTEMS_TYPE_NO_VERSION } \ No newline at end of file diff --git a/src/constants/views.js b/src/constants/views.js index 42e7913c..a8559540 100644 --- a/src/constants/views.js +++ b/src/constants/views.js @@ -1,15 +1,9 @@ -// Constants will be shared between client and server. -// They will be used as values in the DOM and in the URL of the views calls. -const VIEWS_TYPE_UNIQUE = 'unique' -const VIEWS_TYPE_TOTAL = 'total' -const VIEWS_INTERVAL_DAILY = 'daily' -const VIEWS_INTERVAL_MONTHLY = 'monthly' -const VIEWS_INTERVAL_YEARLY = 'yearly' +'use strict' + +const VIEWS_TYPE_UNIQUE = 'UNIQUE' +const VIEWS_TYPE_TOTAL = 'TOTAL' module.exports = { VIEWS_TYPE_UNIQUE, - VIEWS_TYPE_TOTAL, - VIEWS_INTERVAL_DAILY, - VIEWS_INTERVAL_MONTHLY, - VIEWS_INTERVAL_YEARLY + VIEWS_TYPE_TOTAL } \ No newline at end of file diff --git a/src/database/browsers.js b/src/database/browsers.js index 88388879..ddfe6f57 100644 --- a/src/database/browsers.js +++ b/src/database/browsers.js @@ -1,49 +1,46 @@ 'use strict' const Record = require('../schemas/Record') -const aggregateRecentFieldsMultiple = require('../aggregations/aggregateRecentFieldsMultiple') -const aggregateTopFieldsMultiple = require('../aggregations/aggregateTopFieldsMultiple') const aggregateTopFields = require('../aggregations/aggregateTopFields') +const aggregateNewFields = require('../aggregations/aggregateNewFields') const aggregateRecentFields = require('../aggregations/aggregateRecentFields') +const sortings = require('../constants/sortings') const constants = require('../constants/browsers') +const bestMatch = require('../utils/bestMatch') -const getTopWithVersion = async (id, range) => { +const get = async (ids, sorting, type, range, limit, dateDetails) => { - return Record.aggregate( - aggregateTopFieldsMultiple(id, [ 'browserName', 'browserVersion' ], range) - ) -} + const enhance = (entries) => { -const getRecentWithVersion = async (id) => { + return entries.map((entry) => ({ + id: bestMatch([ + [ `${ entry._id.browserName } ${ entry._id.browserVersion }`, [ entry._id.browserName, entry._id.browserVersion ]], + [ `${ entry._id.browserName }`, [ entry._id.browserName ]] + ]), + count: entry.count, + created: entry.created + })) - return Record.aggregate( - aggregateRecentFieldsMultiple(id, [ 'browserName', 'browserVersion' ]) - ) -} + } -const getTopNoVersion = async (id, range) => { + const aggregation = (() => { - return Record.aggregate( - aggregateTopFields(id, 'browserName', range) - ) -} + if (type === constants.BROWSERS_TYPE_NO_VERSION) { + if (sorting === sortings.SORTINGS_TOP) return aggregateTopFields(ids, [ 'browserName' ], range, limit, dateDetails) + if (sorting === sortings.SORTINGS_NEW) return aggregateNewFields(ids, [ 'browserName' ], limit) + if (sorting === sortings.SORTINGS_RECENT) return aggregateRecentFields(ids, [ 'browserName' ], limit) + } + if (type === constants.BROWSERS_TYPE_WITH_VERSION) { + if (sorting === sortings.SORTINGS_TOP) return aggregateTopFields(ids, [ 'browserName', 'browserVersion' ], range, limit, dateDetails) + if (sorting === sortings.SORTINGS_NEW) return aggregateNewFields(ids, [ 'browserName', 'browserVersion' ], limit) + if (sorting === sortings.SORTINGS_RECENT) return aggregateRecentFields(ids, [ 'browserName', 'browserVersion' ], limit) + } -const getRecentNoVersion = async (id) => { + })() - return Record.aggregate( - aggregateRecentFields(id, 'browserName') + return enhance( + await Record.aggregate(aggregation) ) -} - - -const get = async (id, sorting, type, range) => { - - switch (sorting) { - case constants.BROWSERS_SORTING_TOP: - return type === constants.BROWSERS_TYPE_NO_VERSION ? getTopNoVersion(id, range) : getTopWithVersion(id, range) - case constants.BROWSERS_SORTING_RECENT: - return type === constants.BROWSERS_TYPE_NO_VERSION ? getRecentNoVersion(id) : getRecentWithVersion(id) - } } diff --git a/src/database/devices.js b/src/database/devices.js index 3825fb93..d6e4fdb7 100644 --- a/src/database/devices.js +++ b/src/database/devices.js @@ -1,49 +1,46 @@ 'use strict' const Record = require('../schemas/Record') -const aggregateRecentFieldsMultiple = require('../aggregations/aggregateRecentFieldsMultiple') -const aggregateTopFieldsMultiple = require('../aggregations/aggregateTopFieldsMultiple') const aggregateTopFields = require('../aggregations/aggregateTopFields') +const aggregateNewFields = require('../aggregations/aggregateNewFields') const aggregateRecentFields = require('../aggregations/aggregateRecentFields') +const sortings = require('../constants/sortings') const constants = require('../constants/devices') +const bestMatch = require('../utils/bestMatch') -const getTopWithModel = async (id, range) => { +const get = async (ids, sorting, type, range, limit, dateDetails) => { - return Record.aggregate( - aggregateTopFieldsMultiple(id, [ 'deviceManufacturer', 'deviceName' ], range) - ) -} + const enhance = (entries) => { -const getRecentWithModel = async (id) => { + return entries.map((entry) => ({ + id: bestMatch([ + [ `${ entry._id.deviceManufacturer } ${ entry._id.deviceName }`, [ entry._id.deviceManufacturer, entry._id.deviceName ]], + [ `${ entry._id.deviceManufacturer }`, [ entry._id.deviceManufacturer ]] + ]), + count: entry.count, + created: entry.created + })) - return Record.aggregate( - aggregateRecentFieldsMultiple(id, [ 'deviceManufacturer', 'deviceName' ]) - ) -} + } -const getTopNoModel = async (id, range) => { + const aggregation = (() => { - return Record.aggregate( - aggregateTopFields(id, 'deviceManufacturer', range) - ) -} + if (type === constants.DEVICES_TYPE_NO_MODEL) { + if (sorting === sortings.SORTINGS_TOP) return aggregateTopFields(ids, [ 'deviceManufacturer' ], range, limit, dateDetails) + if (sorting === sortings.SORTINGS_NEW) return aggregateNewFields(ids, [ 'deviceManufacturer' ], limit) + if (sorting === sortings.SORTINGS_RECENT) return aggregateRecentFields(ids, [ 'deviceManufacturer' ], limit) + } + if (type === constants.DEVICES_TYPE_WITH_MODEL) { + if (sorting === sortings.SORTINGS_TOP) return aggregateTopFields(ids, [ 'deviceManufacturer', 'deviceName' ], range, limit, dateDetails) + if (sorting === sortings.SORTINGS_NEW) return aggregateNewFields(ids, [ 'deviceManufacturer', 'deviceName' ], limit) + if (sorting === sortings.SORTINGS_RECENT) return aggregateRecentFields(ids, [ 'deviceManufacturer', 'deviceName' ], limit) + } -const getRecentNoModel = async (id) => { + })() - return Record.aggregate( - aggregateRecentFields(id, 'deviceManufacturer') + return enhance( + await Record.aggregate(aggregation) ) -} - - -const get = async (id, sorting, type, range) => { - - switch (sorting) { - case constants.DEVICES_SORTING_TOP: - return type === constants.DEVICES_TYPE_NO_MODEL ? getTopNoModel(id, range) : getTopWithModel(id, range) - case constants.DEVICES_SORTING_RECENT: - return type === constants.DEVICES_TYPE_NO_MODEL ? getRecentNoModel(id) : getRecentWithModel(id) - } } diff --git a/src/database/domains.js b/src/database/domains.js index 87983fe2..21644505 100644 --- a/src/database/domains.js +++ b/src/database/domains.js @@ -1,46 +1,71 @@ 'use strict' const Domain = require('../schemas/Domain') -const runUpdate = require('../utils/runUpdate') +const sortByProp = require('../utils/sortByProp') + +const response = (entry) => ({ + id: entry.id, + title: entry.title, + created: entry.created, + updated: entry.updated +}) const add = async (data) => { - return Domain.create(data) + const enhance = (entry) => { + return entry == null ? entry : response(entry) + } + + return enhance( + await Domain.create(data) + ) } const all = async () => { - return Domain.aggregate([ - { - $addFields: { - insensitive: { - $toLower: '$title' - } - } - }, - { - $sort: { - insensitive: 1 - } - } - ]) + const enhance = (entries) => { + return entries + .map(response) + .sort(sortByProp('title')) + } + + return enhance( + await Domain.find({}) + ) } const get = async (id) => { - return Domain.findOne({ - id - }) + const enhance = (entry) => { + return entry == null ? entry : response(entry) + } + + return enhance( + await Domain.findOne({ id }) + ) } const update = async (id, data) => { - return runUpdate(Domain, id, data, [ - 'title' - ]) + const enhance = (entry) => { + return entry == null ? entry : response(entry) + } + + return enhance( + await Domain.findOneAndUpdate({ + id + }, { + $set: { + title: data.title, + updated: Date.now() + } + }, { + new: true + }) + ) } diff --git a/src/database/durations.js b/src/database/durations.js index 811d8cbb..84f42521 100644 --- a/src/database/durations.js +++ b/src/database/durations.js @@ -1,194 +1,69 @@ 'use strict' -const { subDays } = require('date-fns') +const { utcToZonedTime } = require('date-fns-tz') const Record = require('../schemas/Record') -const constants = require('../constants/durations') -const zeroDate = require('../utils/zeroDate') - -// The time that elapsed between the creation and updating of records. -const projectDuration = { - $project: { - created: '$created', - duration: { - $subtract: [ '$updated', '$created' ] - } - } -} +const aggregateDurations = require('../aggregations/aggregateDurations') +const intervals = require('../constants/intervals') +const createArray = require('../utils/createArray') +const matchesDate = require('../utils/matchesDate') -// Ackee tracks durations in an interval, but some durations are between -// possible interval times. This could be caused by a network delay or the -// browser who's throttling JS execution. This step rounds all durations -// down to the nearest possible interval to get rid of inaccuracy. -const projectInterval = { - $project: { - created: '$created', - duration: { - $multiply: [ - { - $floor: [ - { - $divide: [ '$duration', constants.DURATIONS_INTERVAL ] - } - ] - }, - constants.DURATIONS_INTERVAL - ] - } - } -} +const includeFn = (dateDetails, interval) => { -// Visits below the tracking interval will have a duration of zero. That's -// incorrect as visitors spent time on the site, but just not enough. This -// step sets the minimum duration to the half of the tracking interval. -// This value is a compromise that doesn't influence the average too much. -const projectMinInterval = { - $project: { - created: '$created', - duration: { - $cond: { - if: { - $lt: [ '$duration', constants.DURATIONS_INTERVAL ] - }, - then: constants.DURATIONS_INTERVAL / 2, - else: '$duration' - } - } + switch (interval) { + case intervals.INTERVALS_DAILY: return dateDetails.lastDays + case intervals.INTERVALS_MONTHLY: return dateDetails.lastMonths + case intervals.INTERVALS_YEARLY: return dateDetails.lastYears } -} -// Some visitors keep sites open in the background. Their duration is often -// way above the limit. This distorts the average and should be omitted. -const matchLimit = { - $match: { - duration: { - $lt: constants.DURATIONS_LIMIT - } - } } -const getAverage = async (id) => { +const get = async (ids, interval, limit, dateDetails) => { - return Record.aggregate([ - { - $match: { - domainId: id - } - }, - projectDuration, - projectInterval, - projectMinInterval, - matchLimit, - { - $group: { - _id: { - day: { - $dayOfMonth: '$created' - }, - month: { - $month: '$created' - }, - year: { - $year: '$created' - } - }, - average: { - $avg: '$duration' - } - } - }, - { - $sort: { - '_id.year': -1, - '_id.month': -1, - '_id.day': -1 - } - }, - { - $limit: 14 - } - ]) + const enhance = (entries) => { -} + const matchDay = [ intervals.INTERVALS_DAILY ].includes(interval) + const matchMonth = [ intervals.INTERVALS_DAILY, intervals.INTERVALS_MONTHLY ].includes(interval) + const matchYear = [ intervals.INTERVALS_DAILY, intervals.INTERVALS_MONTHLY, intervals.INTERVALS_YEARLY ].includes(interval) -const getDetailed = async (id) => { + return createArray(limit).map((_, index) => { - const averageEntries = await Record.aggregate([ - { - $match: { - domainId: id, - created: { - $gte: subDays(zeroDate(), 6) - } - } - }, - projectDuration, - projectInterval, - projectMinInterval, - matchLimit, - { - $group: { - _id: null, - average: { - $avg: '$duration' - } - } - } - ]) - - // No need to continue when there're no entries - if (averageEntries.length === 0) return [] - - const detailedEntries = await Record.aggregate([ - { - $match: { - domainId: id, - created: { - $gte: subDays(zeroDate(), 6) - } - } - }, - projectDuration, - projectInterval, - { - $group: { - _id: { - $cond: { - if: { - $gte: [ '$duration', constants.DURATIONS_LIMIT ] - }, - then: constants.DURATIONS_LIMIT, - else: '$duration' - } - }, - count: { - $sum: 1 - } - } - }, - { - $addFields: { - average: averageEntries[0].average - } - }, - { - $sort: { - _id: 1 - } - } - ]) + const date = includeFn(dateDetails, interval)(index) - return detailedEntries + // Views and durations are returning day, month and year in the + // timezone of the user. We therefore need to match it against a + // date in the timezone of the user. + const userZonedDate = utcToZonedTime(date, dateDetails.userTimeZone) -} + // Find a entry that matches the date + const entry = entries.find((entry) => { + return matchesDate( + matchDay === true ? entry._id.day : undefined, + matchMonth === true ? entry._id.month : undefined, + matchYear === true ? entry._id.year : undefined, + userZonedDate + ) + }) -const get = async (id, type) => { + return { + id: date, + count: entry == null ? 0 : entry.count + } + + }) - switch (type) { - case constants.DURATIONS_TYPE_AVERAGE: return getAverage(id) - case constants.DURATIONS_TYPE_DETAILED: return getDetailed(id) } + const aggregation = (() => { + + return aggregateDurations(ids, interval, limit, dateDetails) + + })() + + return enhance( + await Record.aggregate(aggregation) + ) + } module.exports = { diff --git a/src/database/facts.js b/src/database/facts.js new file mode 100644 index 00000000..4a0e3a42 --- /dev/null +++ b/src/database/facts.js @@ -0,0 +1,23 @@ +'use strict' + +const Record = require('../schemas/Record') +const aggregateActiveVisitors = require('../aggregations/aggregateActiveVisitors') + +const getActiveVisitors = async (ids, dateDetails) => { + + const enhance = (entries) => { + const entry = entries[0] + return entry == null ? 0 : entry.count + } + + return enhance( + await Record.aggregate( + aggregateActiveVisitors(ids, dateDetails) + ) + ) + +} + +module.exports = { + getActiveVisitors +} \ No newline at end of file diff --git a/src/database/languages.js b/src/database/languages.js index 58f65989..c181d9c6 100644 --- a/src/database/languages.js +++ b/src/database/languages.js @@ -2,31 +2,34 @@ const Record = require('../schemas/Record') const aggregateTopFields = require('../aggregations/aggregateTopFields') +const aggregateNewFields = require('../aggregations/aggregateNewFields') const aggregateRecentFields = require('../aggregations/aggregateRecentFields') -const constants = require('../constants/languages') +const sortings = require('../constants/sortings') +const languageCodes = require('../utils/languageCodes') -const getTop = async (id, range) => { +const get = async (ids, sorting, range, limit, dateDetails) => { - return Record.aggregate( - aggregateTopFields(id, 'siteLanguage', range) - ) + const enhance = (entries) => { -} + return entries.map((entry) => ({ + id: languageCodes[entry._id.siteLanguage] || entry._id.siteLanguage, + count: entry.count, + created: entry.created + })) -const getRecent = async (id) => { + } - return Record.aggregate( - aggregateRecentFields(id, 'siteLanguage') - ) + const aggregation = (() => { -} + if (sorting === sortings.SORTINGS_TOP) return aggregateTopFields(ids, [ 'siteLanguage' ], range, limit, dateDetails) + if (sorting === sortings.SORTINGS_NEW) return aggregateNewFields(ids, [ 'siteLanguage' ], limit) + if (sorting === sortings.SORTINGS_RECENT) return aggregateRecentFields(ids, [ 'siteLanguage' ], limit) -const get = async (id, sorting, range) => { + })() - switch (sorting) { - case constants.LANGUAGES_SORTING_TOP: return getTop(id, range) - case constants.LANGUAGES_SORTING_RECENT: return getRecent(id) - } + return enhance( + await Record.aggregate(aggregation) + ) } diff --git a/src/database/pages.js b/src/database/pages.js index 80c3ff8f..4c7d9c18 100644 --- a/src/database/pages.js +++ b/src/database/pages.js @@ -2,31 +2,33 @@ const Record = require('../schemas/Record') const aggregateTopFields = require('../aggregations/aggregateTopFields') +const aggregateNewFields = require('../aggregations/aggregateNewFields') const aggregateRecentFields = require('../aggregations/aggregateRecentFields') -const constants = require('../constants/pages') +const sortings = require('../constants/sortings') -const getTop = async (id, range) => { +const get = async (ids, sorting, range, limit, dateDetails) => { - return Record.aggregate( - aggregateTopFields(id, 'siteLocation', range) - ) + const enhance = (entries) => { -} + return entries.map((entry) => ({ + id: entry._id.siteLocation, + count: entry.count, + created: entry.created + })) -const getRecent = async (id) => { + } - return Record.aggregate( - aggregateRecentFields(id, 'siteLocation') - ) + const aggregation = (() => { -} + if (sorting === sortings.SORTINGS_TOP) return aggregateTopFields(ids, [ 'siteLocation' ], range, limit, dateDetails) + if (sorting === sortings.SORTINGS_NEW) return aggregateNewFields(ids, [ 'siteLocation' ], limit) + if (sorting === sortings.SORTINGS_RECENT) return aggregateRecentFields(ids, [ 'siteLocation' ], limit) -const get = async (id, sorting, range) => { + })() - switch (sorting) { - case constants.PAGES_SORTING_TOP: return getTop(id, range) - case constants.PAGES_SORTING_RECENT: return getRecent(id) - } + return enhance( + await Record.aggregate(aggregation) + ) } diff --git a/src/database/records.js b/src/database/records.js index 20d1a8fd..32e814b6 100644 --- a/src/database/records.js +++ b/src/database/records.js @@ -1,23 +1,63 @@ 'use strict' const Record = require('../schemas/Record') -const runUpdate = require('../utils/runUpdate') + +const response = (entry) => ({ + id: entry.id, + siteLocation: entry.siteLocation, + siteReferrer: entry.siteReferrer, + siteLanguage: entry.siteLanguage, + screenWidth: entry.screenWidth, + screenHeight: entry.screenHeight, + screenColorDepth: entry.screenColorDepth, + deviceName: entry.deviceName, + deviceManufacturer: entry.deviceManufacturer, + osName: entry.osName, + osVersion: entry.osVersion, + browserName: entry.browserName, + browserVersion: entry.browserVersion, + browserWidth: entry.browserWidth, + browserHeight: entry.browserHeight, + created: entry.created, + updated: entry.updated +}) const add = async (data) => { - return Record.create(data) + const enhance = (entry) => { + return entry == null ? entry : response(entry) + } + + return enhance( + await Record.create(data) + ) } const update = async (id) => { - return runUpdate(Record, id) + const enhance = (entry) => { + return entry == null ? entry : response(entry) + } + + return enhance( + await Record.findOneAndUpdate({ + id + }, { + $set: { + updated: Date.now() + } + }, { + new: true + }) + ) } const anonymize = async (clientId, ignoreId) => { - return Record.updateMany({ + // Don't return anything about the update + await Record.updateMany({ $and: [ { clientId }, { @@ -27,19 +67,27 @@ const anonymize = async (clientId, ignoreId) => { } ] }, { - clientId: null, - siteLanguage: null, - screenWidth: null, - screenHeight: null, - screenColorDepth: null, - deviceName: null, - deviceManufacturer: null, - osName: null, - osVersion: null, - browserName: null, - browserVersion: null, - browserWidth: null, - browserHeight: null + clientId: undefined, + siteLanguage: undefined, + screenWidth: undefined, + screenHeight: undefined, + screenColorDepth: undefined, + deviceName: undefined, + deviceManufacturer: undefined, + osName: undefined, + osVersion: undefined, + browserName: undefined, + browserVersion: undefined, + browserWidth: undefined, + browserHeight: undefined + }) + +} + +const del = async (domainId) => { + + return Record.deleteMany({ + domainId }) } @@ -47,5 +95,6 @@ const anonymize = async (clientId, ignoreId) => { module.exports = { add, update, - anonymize + anonymize, + del } \ No newline at end of file diff --git a/src/database/referrers.js b/src/database/referrers.js index 8c72ac8d..435fa0bf 100644 --- a/src/database/referrers.js +++ b/src/database/referrers.js @@ -4,42 +4,34 @@ const Record = require('../schemas/Record') const aggregateTopFields = require('../aggregations/aggregateTopFields') const aggregateRecentFields = require('../aggregations/aggregateRecentFields') const aggregateNewFields = require('../aggregations/aggregateNewFields') -const constants = require('../constants/referrers') +const sortings = require('../constants/sortings') -const getTop = async (id, range) => { +const get = async (ids, sorting, range, limit, dateDetails) => { - return Record.aggregate( - aggregateTopFields(id, 'siteReferrer', range) - ) + const enhance = (entries) => { -} + return entries.map((entry) => ({ + id: entry._id.siteReferrer, + count: entry.count, + created: entry.created + })) -const getNew = async (id) => { + } - return Record.aggregate( - aggregateNewFields(id, 'siteReferrer') - ) + const aggregation = (() => { -} + if (sorting === sortings.SORTINGS_TOP) return aggregateTopFields(ids, [ 'siteReferrer' ], range, limit, dateDetails) + if (sorting === sortings.SORTINGS_NEW) return aggregateNewFields(ids, [ 'siteReferrer' ], limit) + if (sorting === sortings.SORTINGS_RECENT) return aggregateRecentFields(ids, [ 'siteReferrer' ], limit) -const getRecent = async (id) => { + })() - return Record.aggregate( - aggregateRecentFields(id, 'siteReferrer') + return enhance( + await Record.aggregate(aggregation) ) } -const get = async (id, sorting, range) => { - - switch (sorting) { - case constants.REFERRERS_SORTING_TOP: return getTop(id, range) - case constants.REFERRERS_SORTING_NEW: return getNew(id) - case constants.REFERRERS_SORTING_RECENT: return getRecent(id) - } - -} - module.exports = { get } \ No newline at end of file diff --git a/src/database/sizes.js b/src/database/sizes.js index 5e8defbc..93dac336 100644 --- a/src/database/sizes.js +++ b/src/database/sizes.js @@ -2,70 +2,66 @@ const Record = require('../schemas/Record') const aggregateTopFields = require('../aggregations/aggregateTopFields') -const aggregateTopFieldsMultiple = require('../aggregations/aggregateTopFieldsMultiple') +const aggregateNewFields = require('../aggregations/aggregateNewFields') +const aggregateRecentFields = require('../aggregations/aggregateRecentFields') +const sortings = require('../constants/sortings') const constants = require('../constants/sizes') +const bestMatch = require('../utils/bestMatch') -const getBrowserWidth = async (id, range) => { +const get = async (ids, sorting, type, range, limit, dateDetails) => { - return Record.aggregate( - aggregateTopFields(id, 'browserWidth', range) - ) - -} - -const getBrowserHeight = async (id, range) => { - - return Record.aggregate( - aggregateTopFields(id, 'browserHeight', range) - ) - -} - -const getBrowserResolution = async (id, range) => { - - return Record.aggregate( - aggregateTopFieldsMultiple(id, [ 'browserWidth', 'browserHeight' ], range) - ) - -} - -const getScreenWidth = async (id, range) => { + const enhance = (entries) => { - return Record.aggregate( - aggregateTopFields(id, 'screenWidth', range) - ) - -} - -const getScreenHeight = async (id, range) => { - - return Record.aggregate( - aggregateTopFields(id, 'screenHeight', range) - ) - -} + return entries.map((entry) => ({ + id: bestMatch([ + [ `${ entry._id.screenWidth }px x ${ entry._id.screenHeight }px`, [ entry._id.screenWidth, entry._id.screenHeight ]], + [ `${ entry._id.browserWidth }px x ${ entry._id.browserHeight }px`, [ entry._id.browserWidth, entry._id.browserHeight ]], + [ `${ entry._id.screenWidth }px`, [ entry._id.screenWidth ]], + [ `${ entry._id.screenHeight }px`, [ entry._id.screenHeight ]], + [ `${ entry._id.browserWidth }px`, [ entry._id.browserWidth ]], + [ `${ entry._id.browserHeight }px`, [ entry._id.browserHeight ]] + ]), + count: entry.count, + created: entry.created + })) -const getScreenResolution = async (id, range) => { + } - return Record.aggregate( - aggregateTopFieldsMultiple(id, [ 'screenWidth', 'screenHeight' ], range) + const aggregation = (() => { + + if (sorting === sortings.SORTINGS_TOP) { + if (type === constants.SIZES_TYPE_BROWSER_WIDTH) return aggregateTopFields(ids, [ 'browserWidth' ], range, limit, dateDetails) + if (type === constants.SIZES_TYPE_BROWSER_HEIGHT) return aggregateTopFields(ids, [ 'browserHeight' ], range, limit, dateDetails) + if (type === constants.SIZES_TYPE_BROWSER_RESOLUTION) return aggregateTopFields(ids, [ 'browserWidth', 'browserHeight' ], range, limit, dateDetails) + if (type === constants.SIZES_TYPE_SCREEN_WIDTH) return aggregateTopFields(ids, [ 'screenWidth' ], range, limit, dateDetails) + if (type === constants.SIZES_TYPE_SCREEN_HEIGHT) return aggregateTopFields(ids, [ 'screenHeight' ], range, limit, dateDetails) + if (type === constants.SIZES_TYPE_SCREEN_RESOLUTION) return aggregateTopFields(ids, [ 'screenWidth', 'screenHeight' ], range, limit, dateDetails) + } + if (sorting === sortings.SORTINGS_NEW) { + if (type === constants.SIZES_TYPE_BROWSER_WIDTH) return aggregateNewFields(ids, [ 'browserWidth' ], limit) + if (type === constants.SIZES_TYPE_BROWSER_HEIGHT) return aggregateNewFields(ids, [ 'browserHeight' ], limit) + if (type === constants.SIZES_TYPE_BROWSER_RESOLUTION) return aggregateNewFields(ids, [ 'browserWidth', 'browserHeight' ], limit) + if (type === constants.SIZES_TYPE_SCREEN_WIDTH) return aggregateNewFields(ids, [ 'screenWidth' ], limit) + if (type === constants.SIZES_TYPE_SCREEN_HEIGHT) return aggregateNewFields(ids, [ 'screenHeight' ], limit) + if (type === constants.SIZES_TYPE_SCREEN_RESOLUTION) return aggregateNewFields(ids, [ 'screenWidth', 'screenHeight' ], limit) + } + if (sorting === sortings.SORTINGS_RECENT) { + if (type === constants.SIZES_TYPE_BROWSER_WIDTH) return aggregateRecentFields(ids, [ 'browserWidth' ], limit) + if (type === constants.SIZES_TYPE_BROWSER_HEIGHT) return aggregateRecentFields(ids, [ 'browserHeight' ], limit) + if (type === constants.SIZES_TYPE_BROWSER_RESOLUTION) return aggregateRecentFields(ids, [ 'browserWidth', 'browserHeight' ], limit) + if (type === constants.SIZES_TYPE_SCREEN_WIDTH) return aggregateRecentFields(ids, [ 'screenWidth' ], limit) + if (type === constants.SIZES_TYPE_SCREEN_HEIGHT) return aggregateRecentFields(ids, [ 'screenHeight' ], limit) + if (type === constants.SIZES_TYPE_SCREEN_RESOLUTION) return aggregateRecentFields(ids, [ 'screenWidth', 'screenHeight' ], limit) + } + + })() + + return enhance( + await Record.aggregate(aggregation) ) } -const get = async (id, type, range) => { - - switch (type) { - case constants.SIZES_TYPE_BROWSER_HEIGHT: return getBrowserHeight(id, range) - case constants.SIZES_TYPE_BROWSER_RESOLUTION: return getBrowserResolution(id, range) - case constants.SIZES_TYPE_BROWSER_WIDTH: return getBrowserWidth(id, range) - case constants.SIZES_TYPE_SCREEN_HEIGHT: return getScreenHeight(id, range) - case constants.SIZES_TYPE_SCREEN_RESOLUTION: return getScreenResolution(id, range) - case constants.SIZES_TYPE_SCREEN_WIDTH: return getScreenWidth(id, range) - } - -} - module.exports = { get } \ No newline at end of file diff --git a/src/database/systems.js b/src/database/systems.js index c0ae0f50..f561f293 100644 --- a/src/database/systems.js +++ b/src/database/systems.js @@ -1,49 +1,46 @@ 'use strict' const Record = require('../schemas/Record') -const aggregateRecentFieldsMultiple = require('../aggregations/aggregateRecentFieldsMultiple') -const aggregateTopFieldsMultiple = require('../aggregations/aggregateTopFieldsMultiple') const aggregateTopFields = require('../aggregations/aggregateTopFields') +const aggregateNewFields = require('../aggregations/aggregateNewFields') const aggregateRecentFields = require('../aggregations/aggregateRecentFields') +const sortings = require('../constants/sortings') const constants = require('../constants/systems') +const bestMatch = require('../utils/bestMatch') -const getTopWithVersion = async (id, range) => { +const get = async (ids, sorting, type, range, limit, dateDetails) => { - return Record.aggregate( - aggregateTopFieldsMultiple(id, [ 'osName', 'osVersion' ], range) - ) -} + const enhance = (entries) => { -const getRecentWithVersion = async (id) => { + return entries.map((entry) => ({ + id: bestMatch([ + [ `${ entry._id.osName } ${ entry._id.osVersion }`, [ entry._id.osName, entry._id.osVersion ]], + [ `${ entry._id.osName }`, [ entry._id.osName ]] + ]), + count: entry.count, + created: entry.created + })) - return Record.aggregate( - aggregateRecentFieldsMultiple(id, [ 'osName', 'osVersion' ]) - ) -} + } -const getTopNoVersion = async (id, range) => { + const aggregation = (() => { - return Record.aggregate( - aggregateTopFields(id, 'osName', range) - ) -} + if (type === constants.SYSTEMS_TYPE_NO_VERSION) { + if (sorting === sortings.SORTINGS_TOP) return aggregateTopFields(ids, [ 'osName' ], range, limit, dateDetails) + if (sorting === sortings.SORTINGS_NEW) return aggregateNewFields(ids, [ 'osName' ], limit) + if (sorting === sortings.SORTINGS_RECENT) return aggregateRecentFields(ids, [ 'osName' ], limit) + } + if (type === constants.SYSTEMS_TYPE_WITH_VERSION) { + if (sorting === sortings.SORTINGS_TOP) return aggregateTopFields(ids, [ 'osName', 'osVersion' ], range, limit, dateDetails) + if (sorting === sortings.SORTINGS_NEW) return aggregateNewFields(ids, [ 'osName', 'osVersion' ], limit) + if (sorting === sortings.SORTINGS_RECENT) return aggregateRecentFields(ids, [ 'osName', 'osVersion' ], limit) + } -const getRecentNoVersion = async (id) => { + })() - return Record.aggregate( - aggregateRecentFields(id, 'osName') + return enhance( + await Record.aggregate(aggregation) ) -} - - -const get = async (id, sorting, type, range) => { - - switch (sorting) { - case constants.SYSTEMS_SORTING_TOP: - return type === constants.SYSTEMS_TYPE_NO_VERSION ? getTopNoVersion(id, range) : getTopWithVersion(id, range) - case constants.SYSTEMS_SORTING_RECENT: - return type === constants.SYSTEMS_TYPE_NO_VERSION ? getRecentNoVersion(id) : getRecentWithVersion(id) - } } diff --git a/src/database/tokens.js b/src/database/tokens.js index 026c6c6f..28526d13 100644 --- a/src/database/tokens.js +++ b/src/database/tokens.js @@ -1,25 +1,54 @@ 'use strict' const Token = require('../schemas/Token') -const runUpdate = require('../utils/runUpdate') + +const response = (entry) => ({ + id: entry.id, + created: entry.created, + updated: entry.updated +}) const add = async () => { - return Token.create({}) + const enhance = (entry) => { + return entry == null ? entry : response(entry) + } + + return enhance( + await Token.create({}) + ) } const get = async (id) => { - return Token.findOne({ - id - }) + const enhance = (entry) => { + return entry == null ? entry : response(entry) + } + + return enhance( + await Token.findOne({ id }) + ) } const update = async (id) => { - return runUpdate(Token, id) + const enhance = (entry) => { + return entry == null ? entry : response(entry) + } + + return enhance( + await Token.findOneAndUpdate({ + id + }, { + $set: { + updated: Date.now() + } + }, { + new: true + }) + ) } diff --git a/src/database/views.js b/src/database/views.js index f98524ce..d81d1301 100644 --- a/src/database/views.js +++ b/src/database/views.js @@ -1,50 +1,71 @@ 'use strict' +const { utcToZonedTime } = require('date-fns-tz') + const Record = require('../schemas/Record') -const aggregateDailyViews = require('../aggregations/aggregateDailyViews') -const aggregateMonthlyViews = require('../aggregations/aggregateMonthlyViews') -const aggregateYearlyViews = require('../aggregations/aggregateYearlyViews') +const aggregateViews = require('../aggregations/aggregateViews') const constants = require('../constants/views') +const intervals = require('../constants/intervals') +const createArray = require('../utils/createArray') +const matchesDate = require('../utils/matchesDate') -const getUnique = async (id, interval) => { +const includeFn = (dateDetails, interval) => { switch (interval) { - case constants.VIEWS_INTERVAL_DAILY: return Record.aggregate( - aggregateDailyViews(id, true) - ) - case constants.VIEWS_INTERVAL_MONTHLY: return Record.aggregate( - aggregateMonthlyViews(id, true) - ) - case constants.VIEWS_INTERVAL_YEARLY: return Record.aggregate( - aggregateYearlyViews(id, true) - ) + case intervals.INTERVALS_DAILY: return dateDetails.lastDays + case intervals.INTERVALS_MONTHLY: return dateDetails.lastMonths + case intervals.INTERVALS_YEARLY: return dateDetails.lastYears } } -const getTotal = async (id, interval) => { +const get = async (ids, type, interval, limit, dateDetails) => { - switch (interval) { - case constants.VIEWS_INTERVAL_DAILY: return Record.aggregate( - aggregateDailyViews(id, false) - ) - case constants.VIEWS_INTERVAL_MONTHLY: return Record.aggregate( - aggregateMonthlyViews(id, false) - ) - case constants.VIEWS_INTERVAL_YEARLY: return Record.aggregate( - aggregateYearlyViews(id, false) - ) - } + const enhance = (entries) => { -} + const matchDay = [ intervals.INTERVALS_DAILY ].includes(interval) + const matchMonth = [ intervals.INTERVALS_DAILY, intervals.INTERVALS_MONTHLY ].includes(interval) + const matchYear = [ intervals.INTERVALS_DAILY, intervals.INTERVALS_MONTHLY, intervals.INTERVALS_YEARLY ].includes(interval) + + return createArray(limit).map((_, index) => { + + const date = includeFn(dateDetails, interval)(index) + + // Views and durations are returning day, month and year in the + // timezone of the user. We therefore need to match it against a + // date in the timezone of the user. + const userZonedDate = utcToZonedTime(date, dateDetails.userTimeZone) -const get = async (id, type, interval) => { + // Find a entry that matches the date + const entry = entries.find((entry) => { + return matchesDate( + matchDay === true ? entry._id.day : undefined, + matchMonth === true ? entry._id.month : undefined, + matchYear === true ? entry._id.year : undefined, + userZonedDate + ) + }) + + return { + id: date, + count: entry == null ? 0 : entry.count + } + + }) - switch (type) { - case constants.VIEWS_TYPE_UNIQUE: return getUnique(id, interval) - case constants.VIEWS_TYPE_TOTAL: return getTotal(id, interval) } + const aggregation = (() => { + + if (type === constants.VIEWS_TYPE_UNIQUE) return aggregateViews(ids, true, interval, limit, dateDetails) + if (type === constants.VIEWS_TYPE_TOTAL) return aggregateViews(ids, false, interval, limit, dateDetails) + + })() + + return enhance( + await Record.aggregate(aggregation) + ) + } module.exports = { diff --git a/src/index.js b/src/index.js index da417698..9a23a044 100644 --- a/src/index.js +++ b/src/index.js @@ -1,13 +1,13 @@ #!/usr/bin/env node 'use strict' - require('dotenv').config() const mongoose = require('mongoose') const server = require('./server') const signale = require('./utils/signale') -const isDemo = require('./utils/isDemo') +const isDemoMode = require('./utils/isDemoMode') +const isDevelopmentMode = require('./utils/isDevelopmentMode') const fillDatabase = require('./utils/fillDatabase') const stripUrlAuth = require('./utils/stripUrlAuth') @@ -28,12 +28,9 @@ if (dbUrl == null) { signale.await(`Connecting to ${ stripUrlAuth(dbUrl) }`) mongoose.connect(dbUrl, { - useNewUrlParser: true, useCreateIndex: true, - reconnectTries: Number.MAX_VALUE, - reconnectInterval: 1000 - + useUnifiedTopology: true }).then(() => { signale.success(`Connected to ${ stripUrlAuth(dbUrl) }`) @@ -41,7 +38,13 @@ mongoose.connect(dbUrl, { server.listen(port) - if (isDemo === true) { + if (isDevelopmentMode === true) { + + signale.info('Development mode enabled') + + } + + if (isDemoMode === true) { const job = fillDatabase(serverUrl) const date = job.nextInvocation() @@ -60,4 +63,4 @@ mongoose.connect(dbUrl, { signale.fatal(err) process.exit(1) -}) +}) \ No newline at end of file diff --git a/src/middlewares/blockDemo.js b/src/middlewares/blockDemo.js deleted file mode 100644 index 545a4d07..00000000 --- a/src/middlewares/blockDemo.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict' - -const { createError } = require('micro') - -const isDemo = require('../utils/isDemo') - -module.exports = async () => { - - if (isDemo === true) { - throw createError(403, 'Forbidden in demo mode') - } - -} \ No newline at end of file diff --git a/src/middlewares/blockDemoMode.js b/src/middlewares/blockDemoMode.js new file mode 100644 index 00000000..a2883a94 --- /dev/null +++ b/src/middlewares/blockDemoMode.js @@ -0,0 +1,11 @@ +'use strict' + +const KnownError = require('../utils/KnownError') + +module.exports = (parent, args, { isDemoMode }) => { + + if (isDemoMode === true) { + throw new KnownError('Forbidden in demo mode') + } + +} \ No newline at end of file diff --git a/src/middlewares/requireAuth.js b/src/middlewares/requireAuth.js index 337d45e5..5e3eb902 100644 --- a/src/middlewares/requireAuth.js +++ b/src/middlewares/requireAuth.js @@ -1,39 +1,9 @@ 'use strict' -const { createError } = require('micro') -const { Bearer } = require('permit') +module.exports = (parent, args, { isAuthenticated }) => { -const ttl = require('../utils/ttl') -const tokens = require('../database/tokens') - -const permit = new Bearer({ query: 'token' }) - -module.exports = async (req, res) => { - - const token = permit.check(req) - - // Token not in request - if (token == null) { - permit.fail(res) - throw createError(400, 'Token missing') + if (isAuthenticated !== true) { + throw isAuthenticated } - const entry = await tokens.get(token) - - // Token not in database - if (entry == null) { - permit.fail(res) - throw createError(400, 'Token invalid') - } - - const valid = ttl(entry.updated, process.env.ACKEE_TTL) - - // Token too old - if (valid === false) { - permit.fail(res) - throw createError(400, 'Token invalid') - } - - await tokens.update(token) - } \ No newline at end of file diff --git a/src/resolvers/domains.js b/src/resolvers/domains.js new file mode 100644 index 00000000..16738b2c --- /dev/null +++ b/src/resolvers/domains.js @@ -0,0 +1,92 @@ +'use strict' + +const records = require('../database/records') +const domains = require('../database/domains') +const KnownError = require('../utils/KnownError') +const messages = require('../utils/messages') +const pipe = require('../utils/pipe') +const requireAuth = require('../middlewares/requireAuth') +const blockDemoMode = require('../middlewares/blockDemoMode') + +module.exports = { + Domain: { + facts: (obj) => obj, + statistics: (obj) => obj + }, + Query: { + domain: pipe(requireAuth, async (parent, { id }) => { + + return domains.get(id) + + }), + domains: pipe(requireAuth, async () => { + + return domains.all() + + }) + }, + Mutation: { + createDomain: pipe(requireAuth, blockDemoMode, async (parent, { input }) => { + + let entry + + try { + + entry = await domains.add(input) + + } catch (err) { + + if (err.name === 'ValidationError') { + throw new KnownError(messages(err.errors)) + } + + throw err + + } + + return { + payload: entry, + success: true + } + + }), + updateDomain: pipe(requireAuth, blockDemoMode, async (parent, { id, input }) => { + + let entry + + try { + + entry = await domains.update(id, input) + + } catch (err) { + + if (err.name === 'ValidationError') { + throw new KnownError(messages(err.errors)) + } + + throw err + + } + + if (entry == null) { + throw new KnownError('Unknown domain') + } + + return { + payload: entry, + success: true + } + + }), + deleteDomain: pipe(requireAuth, blockDemoMode, async (parent, { id }) => { + + await records.del(id) + await domains.del(id) + + return { + success: true + } + + }) + } +} \ No newline at end of file diff --git a/src/resolvers/facts.js b/src/resolvers/facts.js new file mode 100644 index 00000000..5fb2a3b0 --- /dev/null +++ b/src/resolvers/facts.js @@ -0,0 +1,68 @@ +'use strict' + +const facts = require('../database/facts') +const pipe = require('../utils/pipe') +const requireAuth = require('../middlewares/requireAuth') +const views = require('../database/views') +const viewsType = require('../constants/views') +const durations = require('../database/durations') +const domainIds = require('../utils/domainIds') +const intervals = require('../constants/intervals') + +module.exports = { + Facts: { + activeVisitors: pipe(requireAuth, async (domain, _, { dateDetails }) => { + + const ids = await domainIds(domain) + const activeVisitors = await facts.getActiveVisitors(ids, dateDetails) + + return activeVisitors + + }), + averageViews: pipe(requireAuth, async (domain, _, { dateDetails }) => { + + const ids = await domainIds(domain) + const entries = await views.get(ids, viewsType.VIEWS_TYPE_UNIQUE, intervals.INTERVALS_DAILY, 14, dateDetails) + const totalCount = entries.reduce((acc, entry) => acc + entry.count, 0) + + return totalCount / entries.length + + }), + averageDuration: pipe(requireAuth, async (domain, _, { dateDetails }) => { + + const ids = await domainIds(domain) + const entries = await durations.get(ids, intervals.INTERVALS_DAILY, 14, dateDetails) + const totalCount = entries.reduce((acc, entry) => acc + entry.count, 0) + + return totalCount / entries.length + + }), + viewsToday: pipe(requireAuth, async (domain, _, { dateDetails }) => { + + const ids = await domainIds(domain) + const entries = await views.get(ids, viewsType.VIEWS_TYPE_UNIQUE, intervals.INTERVALS_DAILY, 1, dateDetails) + + return entries[0].count + + }), + viewsMonth: pipe(requireAuth, async (domain, _, { dateDetails }) => { + + const ids = await domainIds(domain) + const entries = await views.get(ids, viewsType.VIEWS_TYPE_UNIQUE, intervals.INTERVALS_MONTHLY, 1, dateDetails) + + return entries[0].count + + }), + viewsYear: pipe(requireAuth, async (domain, _, { dateDetails }) => { + + const ids = await domainIds(domain) + const entries = await views.get(ids, viewsType.VIEWS_TYPE_UNIQUE, intervals.INTERVALS_YEARLY, 1, dateDetails) + + return entries[0].count + + }) + }, + Query: { + facts: () => ({}) + } +} \ No newline at end of file diff --git a/src/resolvers/index.js b/src/resolvers/index.js new file mode 100644 index 00000000..bd7d5993 --- /dev/null +++ b/src/resolvers/index.js @@ -0,0 +1,25 @@ +'use strict' + +const tokens = require('./tokens') +const records = require('./records') +const domains = require('./domains') +const facts = require('./facts') +const statistics = require('./statistics') + +module.exports = { + ...tokens, + ...records, + ...domains, + ...facts, + ...statistics, + Query: { + ...domains.Query, + ...facts.Query, + ...statistics.Query + }, + Mutation: { + ...tokens.Mutation, + ...records.Mutation, + ...domains.Mutation + } +} \ No newline at end of file diff --git a/src/resolvers/records.js b/src/resolvers/records.js new file mode 100644 index 00000000..3262b7ae --- /dev/null +++ b/src/resolvers/records.js @@ -0,0 +1,131 @@ +'use strict' + +const KnownError = require('../utils/KnownError') +const normalizeUrl = require('../utils/normalizeUrl') +const identifier = require('../utils/identifier') +const messages = require('../utils/messages') +const domains = require('../database/domains') +const records = require('../database/records') + +const normalizeSiteLocation = (siteLocation) => { + + if (siteLocation == null) { + + // Pre-validate siteLocation and imitate MongoDB error + throw new KnownError(`Path \`siteLocation\` is required`) + + } + + try { + + return normalizeUrl(siteLocation) + + } catch (err) { + + throw new KnownError(`Failed to normalize \`siteLocation\``, err) + + } + +} + +const normalizeSiteReferrer = (siteReferrer) => { + + // The siteReferrer is optional + if (siteReferrer == null) return siteReferrer + + try { + + return normalizeUrl(siteReferrer) + + } catch (err) { + + throw new KnownError(`Failed to normalize \`siteReferrer\``, err) + + } + +} + +const polish = (obj) => { + + return Object.entries(obj).reduce((acc, [ key, value ]) => { + + value = typeof value === 'string' ? value.trim() : value + value = value == null ? undefined : value + value = value === '' ? undefined : value + + if (key === 'siteLocation') value = normalizeSiteLocation(value) + if (key === 'siteReferrer') value = normalizeSiteReferrer(value) + + acc[key] = value + return acc + + }, {}) + +} + +module.exports = { + Mutation: { + createRecord: async (parent, { domainId, input }, { req }) => { + + const clientId = identifier(req, domainId) + const data = polish({ ...input, clientId, domainId }) + + const domain = await domains.get(domainId) + + if (domain == null) throw new KnownError('Unknown domain') + + let entry + + try { + + entry = await records.add(data) + + } catch (err) { + + if (err.name === 'ValidationError') { + throw new KnownError(messages(err.errors)) + } + + throw err + + } + + // Anonymize old entries with the same clientId to prevent that the browsing history + // of a user is reconstructible. Will be skipped when there're no previous entries. + await records.anonymize(clientId, entry.id) + + return { + success: true, + payload: entry + } + + }, + updateRecord: async (parent, { id }) => { + + let entry + + try { + + entry = await records.update(id) + + } catch (err) { + + if (err.name === 'ValidationError') { + throw new KnownError(messages(err.errors)) + } + + throw err + + } + + if (entry == null) { + throw new KnownError('Unknown record') + } + + return { + success: true + } + + } + } +} \ No newline at end of file diff --git a/src/resolvers/statistics.js b/src/resolvers/statistics.js new file mode 100644 index 00000000..e389c60b --- /dev/null +++ b/src/resolvers/statistics.js @@ -0,0 +1,76 @@ +'use strict' + +const views = require('../database/views') +const pages = require('../database/pages') +const referrers = require('../database/referrers') +const durations = require('../database/durations') +const systems = require('../database/systems') +const devices = require('../database/devices') +const browsers = require('../database/browsers') +const sizes = require('../database/sizes') +const languages = require('../database/languages') +const pipe = require('../utils/pipe') +const domainIds = require('../utils/domainIds') +const requireAuth = require('../middlewares/requireAuth') + +module.exports = { + Statistics: { + views: pipe(requireAuth, async (domain, { type, interval, limit }, { dateDetails }) => { + + const ids = await domainIds(domain) + return views.get(ids, type, interval, limit, dateDetails) + + }), + pages: pipe(requireAuth, async (domain, { sorting, range, limit }, { dateDetails }) => { + + const ids = await domainIds(domain) + return pages.get(ids, sorting, range, limit, dateDetails) + + }), + referrers: pipe(requireAuth, async (domain, { sorting, range, limit }, { dateDetails }) => { + + const ids = await domainIds(domain) + return referrers.get(ids, sorting, range, limit, dateDetails) + + }), + durations: pipe(requireAuth, async (domain, { interval, limit }, { dateDetails }) => { + + const ids = await domainIds(domain) + return durations.get(ids, interval, limit, dateDetails) + + }), + systems: pipe(requireAuth, async (domain, { sorting, type, range, limit }, { dateDetails }) => { + + const ids = await domainIds(domain) + return systems.get(ids, sorting, type, range, limit, dateDetails) + + }), + devices: pipe(requireAuth, async (domain, { sorting, type, range, limit }, { dateDetails }) => { + + const ids = await domainIds(domain) + return devices.get(ids, sorting, type, range, limit, dateDetails) + + }), + browsers: pipe(requireAuth, async (domain, { sorting, type, range, limit }, { dateDetails }) => { + + const ids = await domainIds(domain) + return browsers.get(ids, sorting, type, range, limit, dateDetails) + + }), + sizes: pipe(requireAuth, async (domain, { sorting, type, range, limit }, { dateDetails }) => { + + const ids = await domainIds(domain) + return sizes.get(ids, sorting, type, range, limit, dateDetails) + + }), + languages: pipe(requireAuth, async (domain, { sorting, range, limit }, { dateDetails }) => { + + const ids = await domainIds(domain) + return languages.get(ids, sorting, range, limit, dateDetails) + + }) + }, + Query: { + statistics: () => ({}) + } +} \ No newline at end of file diff --git a/src/resolvers/tokens.js b/src/resolvers/tokens.js new file mode 100644 index 00000000..31d0d04a --- /dev/null +++ b/src/resolvers/tokens.js @@ -0,0 +1,42 @@ +'use strict' + +const tokens = require('../database/tokens') +const KnownError = require('../utils/KnownError') + +const response = (entry) => ({ + id: entry.id, + created: entry.created, + updated: entry.updated +}) + +module.exports = { + Mutation: { + createToken: async (parent, { input }) => { + + const { username, password } = input + + if (process.env.ACKEE_USERNAME == null) throw new KnownError('Ackee username missing in environment') + if (process.env.ACKEE_PASSWORD == null) throw new KnownError('Ackee username missing in environment') + + if (username !== process.env.ACKEE_USERNAME) throw new KnownError('Username or password incorrect') + if (password !== process.env.ACKEE_PASSWORD) throw new KnownError('Username or password incorrect') + + const entry = await tokens.add() + + return { + success: true, + payload: response(entry) + } + + }, + deleteToken: async (parent, { id }) => { + + await tokens.del(id) + + return { + success: true + } + + } + } +} \ No newline at end of file diff --git a/src/routes/browsers.js b/src/routes/browsers.js deleted file mode 100644 index a46f14e4..00000000 --- a/src/routes/browsers.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict' - -const { createError } = require('micro') - -const browsers = require('../database/browsers') -const constants = require('../constants/browsers') -const ranges = require('../constants/ranges') - -const response = (entry) => ({ - type: 'browser', - data: { - id: entry._id, - count: entry.count, - created: entry.created - } -}) - -const responses = (entries) => ({ - type: 'browsers', - data: entries.map(response) -}) - -const get = async (req) => { - - const { domainId } = req.params - const { sorting, type, range = ranges.RANGES_LAST_7_DAYS } = req.query - - const sortings = [ - constants.BROWSERS_SORTING_TOP, - constants.BROWSERS_SORTING_RECENT - ] - - const types = [ - constants.BROWSERS_TYPE_WITH_VERSION, - constants.BROWSERS_TYPE_NO_VERSION - ] - - if (sortings.includes(sorting) === false) throw createError(400, 'Unknown sorting') - if (types.includes(type) === false) throw createError(400, 'Unknown type') - if (ranges.toArray().includes(range) === false) throw createError(400, 'Unknown range') - - const entries = await browsers.get(domainId, sorting, type, range) - - return responses(entries) - -} - -module.exports = { - get -} \ No newline at end of file diff --git a/src/routes/devices.js b/src/routes/devices.js deleted file mode 100644 index e9b99a58..00000000 --- a/src/routes/devices.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict' - -const { createError } = require('micro') - -const devices = require('../database/devices') -const constants = require('../constants/devices') -const ranges = require('../constants/ranges') - -const response = (entry) => ({ - type: 'device', - data: { - id: entry._id, - count: entry.count, - created: entry.created - } -}) - -const responses = (entries) => ({ - type: 'devices', - data: entries.map(response) -}) - -const get = async (req) => { - - const { domainId } = req.params - const { sorting, type, range = ranges.RANGES_LAST_7_DAYS } = req.query - - const sortings = [ - constants.DEVICES_SORTING_TOP, - constants.DEVICES_SORTING_RECENT - ] - - const types = [ - constants.DEVICES_TYPE_WITH_MODEL, - constants.DEVICES_TYPE_NO_MODEL - ] - - if (sortings.includes(sorting) === false) throw createError(400, 'Unknown sorting') - if (types.includes(type) === false) throw createError(400, 'Unknown type') - if (ranges.toArray().includes(range) === false) throw createError(400, 'Unknown range') - - const entries = await devices.get(domainId, sorting, type, range) - - return responses(entries) - -} - -module.exports = { - get -} \ No newline at end of file diff --git a/src/routes/domains.js b/src/routes/domains.js deleted file mode 100644 index bf8d855c..00000000 --- a/src/routes/domains.js +++ /dev/null @@ -1,97 +0,0 @@ -'use strict' - -const { send, json, createError } = require('micro') - -const messages = require('../utils/messages') -const domains = require('../database/domains') - -const response = (entry) => ({ - type: 'domain', - data: { - id: entry.id, - title: entry.title, - created: entry.created, - updated: entry.updated - } -}) - -const responses = (entries) => ({ - type: 'domains', - data: entries.map(response) -}) - -const add = async (req, res) => { - - const data = await json(req) - - let entry - - try { - - entry = await domains.add(data) - - } catch (err) { - - if (err.name === 'ValidationError') { - throw createError(400, messages(err.errors), err) - } - - throw err - - } - - return send(res, 201, response(entry)) - -} - -const all = async () => { - - const entries = await domains.all() - - return responses(entries) - -} - -const update = async (req) => { - - const { domainId } = req.params - const data = await json(req) - - let entry - - try { - - entry = await domains.update(domainId, data) - - } catch (err) { - - if (err.name === 'ValidationError') { - throw createError(400, messages(err.errors), err) - } - - throw err - - } - - if (entry == null) throw createError(404, 'Unknown domain') - - return response(entry) - -} - -const del = async (req, res) => { - - const { domainId } = req.params - - await domains.del(domainId) - - send(res, 204) - -} - -module.exports = { - add, - all, - update, - del -} \ No newline at end of file diff --git a/src/routes/durations.js b/src/routes/durations.js deleted file mode 100644 index 4ccdbeb4..00000000 --- a/src/routes/durations.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict' - -const { createError } = require('micro') - -const durations = require('../database/durations') -const constants = require('../constants/durations') - -const response = (entry) => ({ - type: 'duration', - data: { - id: entry._id, - average: entry.average, - count: entry.count - } -}) - -const responses = (entries) => ({ - type: 'durations', - data: entries.map(response) -}) - -const get = async (req) => { - - const { domainId } = req.params - const { type } = req.query - - const types = [ - constants.DURATIONS_TYPE_AVERAGE, - constants.DURATIONS_TYPE_DETAILED - ] - - if (types.includes(type) === false) throw createError(400, 'Unknown type') - - const entries = await durations.get(domainId, type) - - return responses(entries) - -} - -module.exports = { - get -} \ No newline at end of file diff --git a/src/routes/languages.js b/src/routes/languages.js deleted file mode 100644 index 8ba5d2d0..00000000 --- a/src/routes/languages.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict' - -const { createError } = require('micro') - -const languages = require('../database/languages') -const constants = require('../constants/languages') -const ranges = require('../constants/ranges') - -const response = (entry) => ({ - type: 'language', - data: { - id: entry._id, - count: entry.count, - created: entry.created - } -}) - -const responses = (entries) => ({ - type: 'languages', - data: entries.map(response) -}) - -const get = async (req) => { - - const { domainId } = req.params - const { sorting, range = ranges.RANGES_LAST_7_DAYS } = req.query - - const sortings = [ - constants.LANGUAGES_SORTING_TOP, - constants.LANGUAGES_SORTING_RECENT - ] - - if (sortings.includes(sorting) === false) throw createError(400, 'Unknown sorting') - if (ranges.toArray().includes(range) === false) throw createError(400, 'Unknown range') - - const entries = await languages.get(domainId, sorting, range) - - return responses(entries) - -} - -module.exports = { - get -} \ No newline at end of file diff --git a/src/routes/pages.js b/src/routes/pages.js deleted file mode 100644 index b8fd019f..00000000 --- a/src/routes/pages.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict' - -const { createError } = require('micro') - -const pages = require('../database/pages') -const constants = require('../constants/pages') -const ranges = require('../constants/ranges') - -const response = (entry) => ({ - type: 'page', - data: { - id: entry._id, - count: entry.count, - created: entry.created - } -}) - -const responses = (entries) => ({ - type: 'pages', - data: entries.map(response) -}) - -const get = async (req) => { - - const { domainId } = req.params - const { sorting, range = ranges.RANGES_LAST_7_DAYS } = req.query - - const sortings = [ - constants.PAGES_SORTING_TOP, - constants.PAGES_SORTING_RECENT - ] - - if (sortings.includes(sorting) === false) throw createError(400, 'Unknown sorting') - if (ranges.toArray().includes(range) === false) throw createError(400, 'Unknown range') - - const entries = await pages.get(domainId, sorting, range) - - return responses(entries) - -} - -module.exports = { - get -} \ No newline at end of file diff --git a/src/routes/records.js b/src/routes/records.js deleted file mode 100644 index a897359e..00000000 --- a/src/routes/records.js +++ /dev/null @@ -1,139 +0,0 @@ -'use strict' - -const { send, json, createError } = require('micro') - -const normalizeUrl = require('../utils/normalizeUrl') -const identifier = require('../utils/identifier') -const messages = require('../utils/messages') -const domains = require('../database/domains') -const records = require('../database/records') - -const response = (entry) => ({ - type: 'record', - data: { - id: entry.id, - domainId: entry.domainId, - siteLocation: entry.siteLocation, - siteReferrer: entry.siteReferrer, - siteLanguage: entry.siteLanguage, - screenWidth: entry.screenWidth, - screenHeight: entry.screenHeight, - screenColorDepth: entry.screenColorDepth, - deviceName: entry.deviceName, - deviceManufacturer: entry.deviceManufacturer, - osName: entry.osName, - osVersion: entry.osVersion, - browserName: entry.browserName, - browserVersion: entry.browserVersion, - browserWidth: entry.browserWidth, - browserHeight: entry.browserHeight, - created: entry.created, - updated: entry.updated - } -}) - -const normalizeSiteLocation = (siteLocation) => { - - if (siteLocation == null) { - - // Pre-validate siteLocation and imitate MongoDB error - throw createError(400, `Path \`siteLocation\` is required`) - - } - - try { - - return normalizeUrl(siteLocation) - - } catch (err) { - - throw createError(400, `Failed to normalize \`siteLocation\``, err) - - } - -} - -const normalizeSiteReferrer = (siteReferrer) => { - - // The siteReferrer is optional - if (siteReferrer == null) return siteReferrer - - try { - - return normalizeUrl(siteReferrer) - - } catch (err) { - - throw createError(400, `Failed to normalize \`siteReferrer\``, err) - - } - -} - -const add = async (req, res) => { - - const { domainId } = req.params - const clientId = identifier(req, domainId) - const data = { ...await json(req), clientId, domainId } - - const domain = await domains.get(domainId) - - if (domain == null) throw createError(404, 'Unknown domain') - - data.siteLocation = normalizeSiteLocation(data.siteLocation) - data.siteReferrer = normalizeSiteReferrer(data.siteReferrer) - - let entry - - try { - - entry = await records.add(data) - - } catch (err) { - - if (err.name === 'ValidationError') { - throw createError(400, messages(err.errors), err) - } - - throw err - - } - - // Anonymize old entries with the same clientId to prevent that the browsing history - // of a user is reconstructible. Will be skipped when there're no previous entries. - await records.anonymize(clientId, entry.id) - - return send(res, 201, response(entry)) - -} - -const update = async (req) => { - - const { recordId } = req.params - - let entry - - try { - - entry = await records.update(recordId) - - } catch (err) { - - if (err.name === 'ValidationError') { - throw createError(400, messages(err.errors), err) - } - - throw err - - } - - if (entry == null) throw createError(404, 'Unknown record') - - return response(entry) - -} - -module.exports = { - add, - update -} \ No newline at end of file diff --git a/src/routes/referrers.js b/src/routes/referrers.js deleted file mode 100644 index 9e33e07e..00000000 --- a/src/routes/referrers.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict' - -const { createError } = require('micro') - -const referrers = require('../database/referrers') -const constants = require('../constants/referrers') -const ranges = require('../constants/ranges') - -const response = (entry) => ({ - type: 'referrer', - data: { - id: entry._id, - count: entry.count, - created: entry.created - } -}) - -const responses = (entries) => ({ - type: 'referrers', - data: entries.map(response) -}) - -const get = async (req) => { - - const { domainId } = req.params - const { sorting, range = ranges.RANGES_LAST_7_DAYS } = req.query - - const sortings = [ - constants.REFERRERS_SORTING_TOP, - constants.REFERRERS_SORTING_NEW, - constants.REFERRERS_SORTING_RECENT - ] - - if (sortings.includes(sorting) === false) throw createError(400, 'Unknown sorting') - if (ranges.toArray().includes(range) === false) throw createError(400, 'Unknown range') - - const entries = await referrers.get(domainId, sorting, range) - - return responses(entries) - -} - -module.exports = { - get -} \ No newline at end of file diff --git a/src/routes/sizes.js b/src/routes/sizes.js deleted file mode 100644 index 09c02109..00000000 --- a/src/routes/sizes.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict' - -const { createError } = require('micro') - -const sizes = require('../database/sizes') -const constants = require('../constants/sizes') -const ranges = require('../constants/ranges') - -const response = (entry) => ({ - type: 'size', - data: { - id: entry._id, - count: entry.count, - created: entry.created - } -}) - -const responses = (entries) => ({ - type: 'sizes', - data: entries.map(response) -}) - -const get = async (req) => { - - const { domainId } = req.params - const { type, range = ranges.RANGES_LAST_7_DAYS } = req.query - - const types = [ - constants.SIZES_TYPE_BROWSER_HEIGHT, - constants.SIZES_TYPE_BROWSER_RESOLUTION, - constants.SIZES_TYPE_BROWSER_WIDTH, - constants.SIZES_TYPE_SCREEN_HEIGHT, - constants.SIZES_TYPE_SCREEN_RESOLUTION, - constants.SIZES_TYPE_SCREEN_WIDTH - ] - - if (types.includes(type) === false) throw createError(400, 'Unknown type') - if (ranges.toArray().includes(range) === false) throw createError(400, 'Unknown range') - - const entries = await sizes.get(domainId, type, range) - - return responses(entries) - -} - -module.exports = { - get -} \ No newline at end of file diff --git a/src/routes/systems.js b/src/routes/systems.js deleted file mode 100644 index 036b0fd5..00000000 --- a/src/routes/systems.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict' - -const { createError } = require('micro') - -const systems = require('../database/systems') -const constants = require('../constants/systems') -const ranges = require('../constants/ranges') - -const response = (entry) => ({ - type: 'systems', - data: { - id: entry._id, - count: entry.count, - created: entry.created - } -}) - -const responses = (entries) => ({ - type: 'system', - data: entries.map(response) -}) - -const get = async (req) => { - - const { domainId } = req.params - const { sorting, type, range = ranges.RANGES_LAST_7_DAYS } = req.query - - const sortings = [ - constants.SYSTEMS_SORTING_TOP, - constants.SYSTEMS_SORTING_RECENT - ] - - const types = [ - constants.SYSTEMS_TYPE_WITH_VERSION, - constants.SYSTEMS_TYPE_NO_VERSION - ] - - if (sortings.includes(sorting) === false) throw createError(400, 'Unknown sorting') - if (types.includes(type) === false) throw createError(400, 'Unknown type') - if (ranges.toArray().includes(range) === false) throw createError(400, 'Unknown range') - - const entries = await systems.get(domainId, sorting, type, range) - - return responses(entries) - -} - -module.exports = { - get -} \ No newline at end of file diff --git a/src/routes/tokens.js b/src/routes/tokens.js deleted file mode 100644 index 3344565f..00000000 --- a/src/routes/tokens.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict' - -const { send, json, createError } = require('micro') - -const tokens = require('../database/tokens') - -const response = (entry) => ({ - type: 'token', - data: { - id: entry.id, - created: entry.created, - updated: entry.updated - } -}) - -const add = async (req, res) => { - - const { username, password } = await json(req) - - if (username == null) throw createError(400, 'Username missing') - if (password == null) throw createError(400, 'Password missing') - - if (process.env.ACKEE_USERNAME == null) throw createError(500, 'Ackee username missing in environment') - if (process.env.ACKEE_PASSWORD == null) throw createError(500, 'Ackee password missing in environment') - - if (username !== process.env.ACKEE_USERNAME) throw createError(400, 'Username or password incorrect') - if (password !== process.env.ACKEE_PASSWORD) throw createError(400, 'Username or password incorrect') - - const entry = await tokens.add() - - return send(res, 201, response(entry)) - -} - -const del = async (req, res) => { - - const { tokenId } = req.params - - await tokens.del(tokenId) - - send(res, 204) - -} - -module.exports = { - add, - del -} \ No newline at end of file diff --git a/src/routes/ui.js b/src/routes/ui.js index 90a97ed2..2057b8df 100644 --- a/src/routes/ui.js +++ b/src/routes/ui.js @@ -7,8 +7,8 @@ const js = require('rosid-handler-js') const html = require('../ui/index') -const isDemo = require('../utils/isDemo') -const isProductionEnv = require('../utils/isProductionEnv') +const isDemoMode = require('../utils/isDemoMode') +const isDevelopmentMode = require('../utils/isDevelopmentMode') const index = () => { @@ -40,7 +40,7 @@ const favicon = () => { const styles = () => { const filePath = resolve(__dirname, '../ui/styles/index.scss') - const data = sass(filePath, { optimize: isProductionEnv === true }) + const data = sass(filePath, { optimize: isDevelopmentMode === false }) return async (req, res) => { @@ -74,11 +74,11 @@ const scripts = () => { } const data = js(filePath, { - optimize: isProductionEnv === true, + optimize: isDevelopmentMode === false, env: { ACKEE_TRACKER: process.env.ACKEE_TRACKER, - ACKEE_DEMO: isDemo === true ? 'true' : 'false', - NODE_ENV: isProductionEnv === true ? 'production' : 'development' + ACKEE_DEMO: isDemoMode === true ? 'true' : 'false', + NODE_ENV: isDevelopmentMode === true ? 'development' : 'production' }, babel }) @@ -107,9 +107,9 @@ const tracker = () => { } module.exports = { - index: isProductionEnv === true ? index() : (req, res) => index()(req, res), - favicon: isProductionEnv === true ? favicon() : (req, res) => favicon()(req, res), - styles: isProductionEnv === true ? styles() : (req, res) => styles()(req, res), - scripts: isProductionEnv === true ? scripts() : (req, res) => scripts()(req, res), - tracker: isProductionEnv === true ? tracker() : (req, res) => tracker()(req, res) + index: isDevelopmentMode === true ? (req, res) => index()(req, res) : index(), + favicon: isDevelopmentMode === true ? (req, res) => favicon()(req, res) : favicon(), + styles: isDevelopmentMode === true ? (req, res) => styles()(req, res) : styles(), + scripts: isDevelopmentMode === true ? (req, res) => scripts()(req, res) : scripts(), + tracker: isDevelopmentMode === true ? (req, res) => tracker()(req, res) : tracker() } \ No newline at end of file diff --git a/src/routes/views.js b/src/routes/views.js deleted file mode 100644 index 5ba773e1..00000000 --- a/src/routes/views.js +++ /dev/null @@ -1,52 +0,0 @@ -'use strict' - -const { createError } = require('micro') - -const views = require('../database/views') -const constants = require('../constants/views') - -const response = (entry) => ({ - type: 'view', - data: { - id: { - day: entry._id.day, - month: entry._id.month, - year: entry._id.year - }, - count: entry.count - } -}) - -const responses = (entries) => ({ - type: 'views', - data: entries.map(response) -}) - -const get = async (req) => { - - const { domainId } = req.params - const { type, interval } = req.query - - const types = [ - constants.VIEWS_TYPE_UNIQUE, - constants.VIEWS_TYPE_TOTAL - ] - - const intervals = [ - constants.VIEWS_INTERVAL_DAILY, - constants.VIEWS_INTERVAL_MONTHLY, - constants.VIEWS_INTERVAL_YEARLY - ] - - if (types.includes(type) === false) throw createError(400, 'Unknown type') - if (intervals.includes(interval) === false) throw createError(400, 'Unknown interval') - - const entries = await views.get(domainId, type, interval) - - return responses(entries) - -} - -module.exports = { - get -} \ No newline at end of file diff --git a/src/schemas/Record.js b/src/schemas/Record.js index 2050cda2..3a90facf 100644 --- a/src/schemas/Record.js +++ b/src/schemas/Record.js @@ -14,11 +14,13 @@ const schema = new mongoose.Schema({ default: uuid }, clientId: { - type: String + type: String, + index: true }, domainId: { type: String, - required: true + required: true, + index: true }, siteLocation: { type: String, @@ -80,11 +82,13 @@ const schema = new mongoose.Schema({ created: { type: Date, required: true, + index: true, default: Date.now }, updated: { type: Date, required: true, + index: true, default: Date.now } }) diff --git a/src/server.js b/src/server.js index 064b32ad..6417341d 100644 --- a/src/server.js +++ b/src/server.js @@ -1,49 +1,71 @@ 'use strict' +const { ApolloServer } = require('apollo-server-micro') +const { UnsignedIntResolver, UnsignedIntTypeDefinition, DateTimeResolver, DateTimeTypeDefinition } = require('graphql-scalars') const micro = require('micro') const { send, createError } = require('micro') const { router, get, post, put, patch, del } = require('microrouter') +const KnownError = require('./utils/KnownError') const signale = require('./utils/signale') -const pipe = require('./utils/pipe') const isDefined = require('./utils/isDefined') +const isAuthenticated = require('./utils/isAuthenticated') +const isDemoMode = require('./utils/isDemoMode') +const isDevelopmentMode = require('./utils/isDevelopmentMode') const customTrackerUrl = require('./utils/customTrackerUrl') -const requireAuth = require('./middlewares/requireAuth') -const blockDemo = require('./middlewares/blockDemo') +const createDate = require('./utils/createDate') const ui = require('./routes/ui') -const tokens = require('./routes/tokens') -const domains = require('./routes/domains') -const records = require('./routes/records') -const views = require('./routes/views') -const pages = require('./routes/pages') -const referrers = require('./routes/referrers') -const languages = require('./routes/languages') -const durations = require('./routes/durations') -const sizes = require('./routes/sizes') -const systems = require('./routes/systems') -const devices = require('./routes/devices') -const browsers = require('./routes/browsers') -const catchError = (fn) => async (req, res) => { +const handleMicroError = (err, res) => { - try { + // This part is for micro errors and errors outside of GraphQL. + // Most errors won't be caught here, but some error can still + // happen outside of GraphQL. In this case wer distinguish + // between unknown errors and known errors. Known errors are + // created with the createError function while unknown errors + // are simply errors thrown somewhere in the application. - return await fn(req, res) + const isUnknownError = err.statusCode == null + const hasOriginalError = err.originalError != null - } catch (err) { + // Only log the full error stack when the error isn't a known response + if (isUnknownError === true) { + signale.fatal(err) + return send(res, 500, err.message) + } - const isUnknownError = err.statusCode == null - const hasOriginalError = err.originalError != null + signale.warn(hasOriginalError === true ? err.originalError.message : err.message) + send(res, err.statusCode, err.message) - // Only log the full error stack when the error isn't a known API response - if (isUnknownError === true) { - signale.fatal(err) - return send(res, 500, err.message) - } +} + +const handleGraphError = (err) => { - signale.warn(hasOriginalError === true ? err.originalError.message : err.message) - send(res, err.statusCode, err.message) + // This part is for error that happen inside GraphQL resolvers. + // All known errors should be thrown as a KnownError as those + // errors will only show up in the response and as a warning + // in the console output. + const originalError = err.originalError + const isKnownError = originalError instanceof KnownError + + // Only log the full error stack when the error isn't a known response + if (isKnownError === false) { + signale.fatal(originalError) + return err + } + + signale.warn(err.originalError.message) + return err + +} + +const catchError = (fn) => async (req, res) => { + + try { + return await fn(req, res) + } catch (err) { + handleMicroError(err, res) } } @@ -79,6 +101,32 @@ const notFound = async (req) => { } +const apolloServer = new ApolloServer({ + introspection: isDemoMode === true || isDevelopmentMode === true, + playground: isDemoMode === true || isDevelopmentMode === true, + debug: isDevelopmentMode === true, + formatError: handleGraphError, + typeDefs: [ + UnsignedIntTypeDefinition, + DateTimeTypeDefinition, + require('./types') + ], + resolvers: { + UnsignedInt: UnsignedIntResolver, + DateTime: DateTimeResolver, + ...require('./resolvers') + }, + context: async (integrationContext) => ({ + isDemoMode, + isAuthenticated: await isAuthenticated(integrationContext.req), + dateDetails: createDate(integrationContext.req.headers['time-zone']), + req: integrationContext.req + }) +}) + +const graphqlPath = '/api' +const graphqlHandler = apolloServer.createHandler({ path: graphqlPath }) + const routes = [ get('/', ui.index), @@ -89,34 +137,8 @@ const routes = [ get('/tracker.js', ui.tracker), customTrackerUrl != null ? get(customTrackerUrl, ui.tracker) : undefined, - post('/tokens', tokens.add), - del('/tokens/:tokenId', tokens.del), - - post('/domains', pipe(requireAuth, blockDemo, domains.add)), - get('/domains', pipe(requireAuth, domains.all)), - put('/domains/:domainId', pipe(requireAuth, blockDemo, domains.update)), - del('/domains/:domainId', pipe(requireAuth, blockDemo, domains.del)), - - post('/domains/:domainId/records', records.add), - patch('/domains/:domainId/records/:recordId', records.update), - - get('/domains/:domainId/views', pipe(requireAuth, views.get)), - - get('/domains/:domainId/pages', pipe(requireAuth, pages.get)), - - get('/domains/:domainId/referrers', pipe(requireAuth, referrers.get)), - - get('/domains/:domainId/languages', pipe(requireAuth, languages.get)), - - get('/domains/:domainId/durations', pipe(requireAuth, durations.get)), - - get('/domains/:domainId/sizes', pipe(requireAuth, sizes.get)), - - get('/domains/:domainId/systems', pipe(requireAuth, systems.get)), - - get('/domains/:domainId/devices', pipe(requireAuth, devices.get)), - - get('/domains/:domainId/browsers', pipe(requireAuth, browsers.get)), + post(graphqlPath, graphqlHandler), + get(graphqlPath, graphqlHandler), get('/*', notFound), post('/*', notFound), diff --git a/src/stages/matchDomains.js b/src/stages/matchDomains.js new file mode 100644 index 00000000..37eb5a18 --- /dev/null +++ b/src/stages/matchDomains.js @@ -0,0 +1,17 @@ +'use strict' + +module.exports = (ids) => { + + const stage = { + $match: {} + } + + if (ids != null) { + stage.$match.domainId = { + $in: ids + } + } + + return stage + +} \ No newline at end of file diff --git a/src/stages/matchLimit.js b/src/stages/matchLimit.js new file mode 100644 index 00000000..b212d24b --- /dev/null +++ b/src/stages/matchLimit.js @@ -0,0 +1,17 @@ +'use strict' + +const { DURATIONS_LIMIT } = require('../constants/durations') + +module.exports = () => { + + // Some visitors keep sites open in the background. Their duration is often + // way above the limit. This distorts the average and should be omitted. + return { + $match: { + duration: { + $lt: DURATIONS_LIMIT + } + } + } + +} \ No newline at end of file diff --git a/src/stages/projectDuration.js b/src/stages/projectDuration.js new file mode 100644 index 00000000..2e210cc7 --- /dev/null +++ b/src/stages/projectDuration.js @@ -0,0 +1,15 @@ +'use strict' + +module.exports = () => { + + // The time that elapsed between the creation and updating of records. + return { + $project: { + created: '$created', + duration: { + $subtract: [ '$updated', '$created' ] + } + } + } + +} \ No newline at end of file diff --git a/src/stages/projectMinInterval.js b/src/stages/projectMinInterval.js new file mode 100644 index 00000000..ca4915f6 --- /dev/null +++ b/src/stages/projectMinInterval.js @@ -0,0 +1,26 @@ +'use strict' + +const { DURATIONS_INTERVAL } = require('../constants/durations') + +module.exports = () => { + + // Visits below the tracking interval will have a duration of zero. That's + // incorrect as visitors spent time on the site, but just not enough. This + // step sets the minimum duration to the half of the tracking interval. + // This value is a compromise that doesn't influence the average too much. + return { + $project: { + created: '$created', + duration: { + $cond: { + if: { + $lt: [ '$duration', DURATIONS_INTERVAL ] + }, + then: DURATIONS_INTERVAL / 2, + else: '$duration' + } + } + } + } + +} \ No newline at end of file diff --git a/src/types/domains.graphql b/src/types/domains.graphql new file mode 100644 index 00000000..8d38bf1d --- /dev/null +++ b/src/types/domains.graphql @@ -0,0 +1,98 @@ +""" +Domains are required to track views. You can create as many domains as you want, but it's recommended to create on domain per project/site. This allows you to view facts and statistics separately. +""" +type Domain { + """ + Domain identifier. + """ + id: ID! + """ + Title of the domain. + """ + title: String! + """ + Facts about a domain. Usually simple data that can be represented in one value. + """ + facts: Facts! + """ + Statistics of a domain. Usually data that needs to be represented in a list or chart. + """ + statistics: Statistics! + """ + Identifies the date and time when the object was created. + """ + created: DateTime! + """ + Identifies the date and time when the object was updated. + """ + updated: DateTime! +} + +input CreateDomainInput { + """ + Title of the domain. + """ + title: String! +} + +type CreateDomainPayload { + """ + Indicates that the domain creation was successful. Might be `null` otherwise. + """ + success: Boolean + """ + The newly created domain. + """ + payload: Domain +} + +input UpdateDomainInput { + """ + Title of the domain. + """ + title: String! +} + +type UpdateDomainPayload { + """ + Indicates that the domain update was successful. Might be `null` otherwise. + """ + success: Boolean + """ + The updated domain. + """ + payload: Domain +} + +type DeleteDomainPayload { + """ + Indicates that the domain deletion was successful. Might be `null` otherwise. + """ + success: Boolean +} + +type Query { + """ + Data of a specific domain. + """ + domain(id: ID!): Domain + """ + Data of all existing domains. + """ + domains: [Domain!] +} + +type Mutation { + """ + Create a new domain. + """ + createDomain(input: CreateDomainInput!): CreateDomainPayload! + """ + Update an existing domain. + """ + updateDomain(id: ID!, input: UpdateDomainInput!): UpdateDomainPayload! + """ + Delete an existing domain. + """ + deleteDomain(id: ID!): DeleteDomainPayload! +} \ No newline at end of file diff --git a/src/types/facts.graphql b/src/types/facts.graphql new file mode 100644 index 00000000..eb33181e --- /dev/null +++ b/src/types/facts.graphql @@ -0,0 +1,36 @@ +""" +Facts about a domain. Usually simple data that can be represented in one value. +""" +type Facts { + """ + Number of visitors currently on your site. + """ + activeVisitors: UnsignedInt! + """ + Average number of visitors per day during the last 14 days. + """ + averageViews: UnsignedInt! + """ + Average visit duration of the last 14 days in milliseconds. + """ + averageDuration: UnsignedInt! + """ + Number of unique views today. + """ + viewsToday: UnsignedInt! + """ + Number of unique views this month. + """ + viewsMonth: UnsignedInt! + """ + Number of unique views this year. + """ + viewsYear: UnsignedInt! +} + +type Query { + """ + Facts of all domains combined. Usually simple data that can be represented in one value. + """ + facts: Facts! +} \ No newline at end of file diff --git a/src/types/index.js b/src/types/index.js new file mode 100644 index 00000000..c7264e45 --- /dev/null +++ b/src/types/index.js @@ -0,0 +1,7 @@ +'use strict' + +const { loadFilesSync, mergeTypeDefs } = require('graphql-tools') + +const typesArray = loadFilesSync(__dirname) + +module.exports = mergeTypeDefs(typesArray, { all: true }) \ No newline at end of file diff --git a/src/types/miscellaneous.graphql b/src/types/miscellaneous.graphql new file mode 100644 index 00000000..77fdd886 --- /dev/null +++ b/src/types/miscellaneous.graphql @@ -0,0 +1 @@ +scalar URL \ No newline at end of file diff --git a/src/types/records.graphql b/src/types/records.graphql new file mode 100644 index 00000000..5ee5d73d --- /dev/null +++ b/src/types/records.graphql @@ -0,0 +1,161 @@ +""" +Page views will be stored in records. They contain data about the visit and user. Ackee tries its best to keep tracked data anonymized. Several steps are used to avoid that users are identifiable, while still providing helpful analytics. +""" +type Record { + """ + Record identifier. + """ + id: ID! + """ + URL of the page. + """ + siteLocation: URL! + """ + Where the user came from. Either unknown, a specific page or just the domain. This depends on the browser of the user. + """ + siteReferrer: URL + """ + Preferred language of the user. ISO 639-1 formatted. + """ + siteLanguage: String + """ + Width of the screen used by the user to visit the site. + """ + screenWidth: UnsignedInt + """ + Height of the screen used by the user to visit the site. + """ + screenHeight: UnsignedInt + """ + Color depth of the screen used by the user to visit the site. + """ + screenColorDepth: UnsignedInt + """ + Device used by the user to visit the site. + """ + deviceName: String + """ + Manufacturer of the device used by the user to visit the site. + """ + deviceManufacturer: String + """ + Operating system used by the user to visit the site. + """ + osName: String + """ + Operating system version used by the user to visit the site. + """ + osVersion: String + """ + Browser used by the user to visit the site. + """ + browserName: String + """ + Version of the browser used by the user to visit the site. + """ + browserVersion: String + """ + Width of the browser used by the user to visit the site. + """ + browserWidth: UnsignedInt + """ + Height of the browser used by the user to visit the site. + """ + browserHeight: UnsignedInt + """ + Identifies the date and time when the object was created. + """ + created: DateTime! + """ + Identifies the date and time when the object was updated. + """ + updated: DateTime! +} + +input CreateRecordInput { + """ + URL of the page. + """ + siteLocation: URL! + """ + Where the user came from. Either unknown, a specific page or just the domain. This depends on the browser of the user. + """ + siteReferrer: URL + """ + Preferred language of the user. ISO 639-1 formatted. + """ + siteLanguage: String + """ + Width of the screen used by the user to visit the site. + """ + screenWidth: UnsignedInt + """ + Height of the screen used by the user to visit the site. + """ + screenHeight: UnsignedInt + """ + Color depth of the screen used by the user to visit the site. + """ + screenColorDepth: UnsignedInt + """ + Device used by the user to visit the site. + """ + deviceName: String + """ + Manufacturer of the device used by the user to visit the site. + """ + deviceManufacturer: String + """ + Operating system used by the user to visit the site. + """ + osName: String + """ + Operating system version used by the user to visit the site. + """ + osVersion: String + """ + Browser used by the user to visit the site. + """ + browserName: String + """ + Version of the browser used by the user to visit the site. + """ + browserVersion: String + """ + Width of the browser used by the user to visit the site. + """ + browserWidth: UnsignedInt + """ + Height of the browser used by the user to visit the site. + """ + browserHeight: UnsignedInt +} + +type CreateRecordPayload { + """ + Indicates that the record creation was successful. Might be `null` otherwise. + """ + success: Boolean + """ + The newly created record. + """ + payload: Record +} + +type UpdateRecordPayload { + """ + Indicates that the record update was successful. Might be `null` otherwise. + """ + success: Boolean +} + +type Mutation { + """ + Create a new record to track a page visit. + """ + createRecord(domainId: ID!, input: CreateRecordInput!): CreateRecordPayload! + """ + Update an existing record to track the duration of a visit. + """ + updateRecord(id: ID!): UpdateRecordPayload! +} \ No newline at end of file diff --git a/src/types/statistics.graphql b/src/types/statistics.graphql new file mode 100644 index 00000000..2b11d8c1 --- /dev/null +++ b/src/types/statistics.graphql @@ -0,0 +1,361 @@ +enum Interval { + """ + Group by day. + """ + DAILY + """ + Group by month. + """ + MONTHLY + """ + Group by year. + """ + YEARLY +} + +enum Sorting { + """ + Entries with the most occurrences will be shown at the top. + """ + TOP + """ + Entries sorted by time. The newest entries will be shown at the top. + """ + RECENT + """ + Entries that appeared for the first time will be shown at the top. + """ + NEW +} + +enum Range { + """ + Data of the last 24 hours. + """ + LAST_24_HOURS + """ + Data of the last 7 days. + """ + LAST_7_DAYS + """ + Data of the last 30 days. + """ + LAST_30_DAYS + """ + Data of the last 6 months. + """ + LAST_6_MONTHS +} + +enum ViewType { + """ + Unique site views. + """ + UNIQUE + """ + Total page views. + """ + TOTAL +} + +type View { + """ + Date of visits. + """ + id: DateTime! + """ + Amount of occurrences. + """ + count: UnsignedInt! +} + +type Page { + """ + URL of the page. + """ + id: URL! + """ + Amount of occurrences. + """ + count: UnsignedInt + """ + Identifies the date and time when the object was created. + """ + created: DateTime +} + +type Referrer { + """ + URL of the page. + """ + id: URL! + """ + Amount of occurrences. + """ + count: UnsignedInt + """ + Identifies the date and time when the object was created. + """ + created: DateTime +} + +type Duration { + """ + Date of average duration. + """ + id: DateTime! + """ + Average duration in milliseconds. + """ + count: UnsignedInt! +} + +enum SystemType { + """ + Include system version. + """ + WITH_VERSION + """ + Omit system version. + """ + NO_VERSION +} + +type System { + """ + Name of the system. With or without the version. + """ + id: String! + """ + Amount of occurrences. + """ + count: UnsignedInt + """ + Identifies the date and time when the object was created. + """ + created: DateTime +} + +enum DeviceType { + """ + Include model name. + """ + WITH_MODEL + """ + Omit model name. + """ + NO_MODEL +} + +type Device { + """ + Name of the device. With or without the model. + """ + id: String! + """ + Amount of occurrences. + """ + count: UnsignedInt + """ + Identifies the date and time when the object was created. + """ + created: DateTime +} + +enum BrowserType { + """ + Include browser version. + """ + WITH_VERSION + """ + Omit browser version. + """ + NO_VERSION +} + +type Browser { + """ + Name of the browser. With or without the version. + """ + id: String! + """ + Amount of occurrences. + """ + count: UnsignedInt + """ + Identifies the date and time when the object was created. + """ + created: DateTime +} + +enum SizeType { + """ + Browser height in pixels. + """ + BROWSER_WIDTH + """ + Browser width in pixels. + """ + BROWSER_HEIGHT + """ + Browser width and height in pixels. + """ + BROWSER_RESOLUTION + """ + Browser height in pixels. + """ + SCREEN_WIDTH + """ + Browser width in pixels. + """ + SCREEN_HEIGHT + """ + Browser width and height in pixels. + """ + SCREEN_RESOLUTION +} + +type Size { + """ + Screen or browser width, height or resolution. + """ + id: String! + """ + Amount of occurrences. + """ + count: UnsignedInt + """ + Identifies the date and time when the object was created. + """ + created: DateTime +} + +type Language { + """ + Name of the language or language code when unknown. + """ + id: String! + """ + Amount of occurrences. + """ + count: UnsignedInt + """ + Identifies the date and time when the object was created. + """ + created: DateTime +} + +""" +Statistics of a domain. Usually data that needs to be represented in a list or chart. +""" +type Statistics { + """ + Amount of views grouped by day, month or year. + """ + views( + interval: Interval!, + type: ViewType!, + """ + Number of entries to return. Starts with the current day, month or year depending on the chosen interval. + """ + limit: Int = 14 + ): [View!] + """ + Pages viewed by your visitors. + """ + pages( + sorting: Sorting!, + range: Range = LAST_7_DAYS, + """ + Number of entries to return. + """ + limit: Int = 30 + ): [Page!] + """ + Where your visitors are coming from. + """ + referrers( + sorting: Sorting!, + range: Range = LAST_7_DAYS, + """ + Number of entries to return. + """ + limit: Int = 30 + ): [Referrer!] + """ + Average visit duration by day, month or year. + """ + durations( + interval: Interval!, + """ + Number of entries to return. Starts with the current day, month or year depending on the chosen interval. + """ + limit: Int = 14 + ): [Duration!] + """ + Systems used by your visitors. + """ + systems( + sorting: Sorting!, + type: SystemType!, + range: Range = LAST_7_DAYS, + """ + Number of entries to return. + """ + limit: Int = 30 + ): [System!] + """ + Devices used by your visitors. + """ + devices( + sorting: Sorting!, + type: DeviceType!, + range: Range = LAST_7_DAYS, + """ + Number of entries to return. + """ + limit: Int = 30 + ): [Device!] + """ + Browsers used by your visitors. + """ + browsers( + sorting: Sorting!, + type: BrowserType!, + range: Range = LAST_7_DAYS, + """ + Number of entries to return. + """ + limit: Int = 30 + ): [Browser!] + """ + Screen or browser sizes used by your visitors. + """ + sizes( + sorting: Sorting!, + type: SizeType!, + range: Range = LAST_7_DAYS, + """ + Number of entries to return. + """ + limit: Int = 30 + ): [Size!] + """ + Browser languages used by your visitors. + """ + languages( + sorting: Sorting!, + range: Range = LAST_7_DAYS, + """ + Number of entries to return. + """ + limit: Int = 30 + ): [Language!] +} + +type Query { + """ + Statistics of all domains combined. Usually data that needs to be represented in a list or chart. + """ + statistics: Statistics! +} \ No newline at end of file diff --git a/src/types/tokens.graphql b/src/types/tokens.graphql new file mode 100644 index 00000000..edc68fef --- /dev/null +++ b/src/types/tokens.graphql @@ -0,0 +1,54 @@ +type Token { + """ + Token identifier. Use this value for authentication. + """ + id: ID! + """ + Identifies the date and time when the object was created. + """ + created: DateTime! + """ + Identifies the date and time when the object was updated. + """ + updated: DateTime! +} + +input CreateTokenInput { + """ + Username used to protect the Ackee instance. + """ + username: String! + """ + Password used to protect the Ackee instance. + """ + password: String! +} + +type CreateTokenPayload { + """ + Indicates that the token creation was successful. Might be `null` otherwise. + """ + success: Boolean + """ + The newly created token. + """ + payload: Token +} + +type DeleteTokenPayload { + """ + Indicates that the token deletion was successful. Might be `null` otherwise. + """ + success: Boolean +} + +type Mutation { + """ + Create a new token. The token is required in order to access protected data. + """ + createToken(input: CreateTokenInput!): CreateTokenPayload! + """ + Delete an existing token. The token than can't be used anymore for authentication. + """ + deleteToken(id: ID!): DeleteTokenPayload! +} \ No newline at end of file diff --git a/src/ui/scripts/actions/browsers.js b/src/ui/scripts/actions/browsers.js index d6300f54..d28956a0 100644 --- a/src/ui/scripts/actions/browsers.js +++ b/src/ui/scripts/actions/browsers.js @@ -2,16 +2,10 @@ import api from '../utils/api' import signalHandler from '../utils/signalHandler' export const SET_BROWSERS_TYPE = Symbol() -export const SET_BROWSERS_SORTING = Symbol() export const SET_BROWSERS_VALUE = Symbol() export const SET_BROWSERS_FETCHING = Symbol() export const SET_BROWSERS_ERROR = Symbol() -export const setBrowsersSorting = (payload) => ({ - type: SET_BROWSERS_SORTING, - payload -}) - export const setBrowsersType = (payload) => ({ type: SET_BROWSERS_TYPE, payload @@ -23,38 +17,58 @@ export const setBrowsersValue = (domainId, payload) => ({ payload }) -export const setBrowsersFetching = (domainId, payload) => ({ +export const setBrowsersFetching = (payload) => ({ type: SET_BROWSERS_FETCHING, - domainId, payload }) -export const setBrowsersError = (domainId, payload) => ({ +export const setBrowsersError = (payload) => ({ type: SET_BROWSERS_ERROR, - domainId, payload }) -export const fetchBrowsers = signalHandler((signal) => (props, domainId) => async (dispatch) => { +export const fetchBrowsers = signalHandler((signal) => (props) => async (dispatch) => { - dispatch(setBrowsersFetching(domainId, true)) - dispatch(setBrowsersError(domainId)) + dispatch(setBrowsersFetching(true)) + dispatch(setBrowsersError()) try { - const data = await api(`/domains/${ domainId }/browsers?sorting=${ props.browsers.sorting }&type=${ props.browsers.type }&range=${ props.filter.range }`, { - method: 'get', + const data = await api({ + query: ` + query fetchBrowsers($sorting: Sorting!, $type: BrowserType!, $range: Range) { + domains { + id + statistics { + browsers(sorting: $sorting, type: $type, range: $range) { + id + count + created + } + } + } + } + `, + variables: { + sorting: props.filter.sorting, + type: props.browsers.type, + range: props.filter.range + }, props, - signal: signal(domainId) + signal: signal() }) - dispatch(setBrowsersValue(domainId, data)) - dispatch(setBrowsersFetching(domainId, false)) + data.domains.forEach((domain) => { + dispatch(setBrowsersValue(domain.id, domain.statistics.browsers)) + }) + dispatch(setBrowsersFetching(false)) } catch (err) { - dispatch(setBrowsersError(domainId, err)) - dispatch(setBrowsersFetching(domainId, false)) + if (err.name === 'AbortError') return + dispatch(setBrowsersFetching(false)) + if (err.name === 'HandledError') return + dispatch(setBrowsersError(err)) } diff --git a/src/ui/scripts/actions/devices.js b/src/ui/scripts/actions/devices.js index 874b62f1..2c60f642 100644 --- a/src/ui/scripts/actions/devices.js +++ b/src/ui/scripts/actions/devices.js @@ -2,16 +2,10 @@ import api from '../utils/api' import signalHandler from '../utils/signalHandler' export const SET_DEVICES_TYPE = Symbol() -export const SET_DEVICES_SORTING = Symbol() export const SET_DEVICES_VALUE = Symbol() export const SET_DEVICES_FETCHING = Symbol() export const SET_DEVICES_ERROR = Symbol() -export const setDevicesSorting = (payload) => ({ - type: SET_DEVICES_SORTING, - payload -}) - export const setDevicesType = (payload) => ({ type: SET_DEVICES_TYPE, payload @@ -23,38 +17,58 @@ export const setDevicesValue = (domainId, payload) => ({ payload }) -export const setDevicesFetching = (domainId, payload) => ({ +export const setDevicesFetching = (payload) => ({ type: SET_DEVICES_FETCHING, - domainId, payload }) -export const setDevicesError = (domainId, payload) => ({ +export const setDevicesError = (payload) => ({ type: SET_DEVICES_ERROR, - domainId, payload }) -export const fetchDevices = signalHandler((signal) => (props, domainId) => async (dispatch) => { +export const fetchDevices = signalHandler((signal) => (props) => async (dispatch) => { - dispatch(setDevicesFetching(domainId, true)) - dispatch(setDevicesError(domainId)) + dispatch(setDevicesFetching(true)) + dispatch(setDevicesError()) try { - const data = await api(`/domains/${ domainId }/devices?sorting=${ props.devices.sorting }&type=${ props.devices.type }&range=${ props.filter.range }`, { - method: 'get', + const data = await api({ + query: ` + query fetchDevices($sorting: Sorting!, $type: DeviceType!, $range: Range) { + domains { + id + statistics { + devices(sorting: $sorting, type: $type, range: $range) { + id + count + created + } + } + } + } + `, + variables: { + sorting: props.filter.sorting, + type: props.devices.type, + range: props.filter.range + }, props, - signal: signal(domainId) + signal: signal() }) - dispatch(setDevicesValue(domainId, data)) - dispatch(setDevicesFetching(domainId, false)) + data.domains.forEach((domain) => { + dispatch(setDevicesValue(domain.id, domain.statistics.devices)) + }) + dispatch(setDevicesFetching(false)) } catch (err) { - dispatch(setDevicesError(domainId, err)) - dispatch(setDevicesFetching(domainId, false)) + if (err.name === 'AbortError') return + dispatch(setDevicesFetching(false)) + if (err.name === 'HandledError') return + dispatch(setDevicesError(err)) } diff --git a/src/ui/scripts/actions/domains.js b/src/ui/scripts/actions/domains.js index 06166a24..bd0e83ed 100644 --- a/src/ui/scripts/actions/domains.js +++ b/src/ui/scripts/actions/domains.js @@ -27,19 +27,28 @@ export const fetchDomains = signalHandler((signal) => (props) => async (dispatch try { - const data = await api('/domains', { - method: 'get', + const data = await api({ + query: ` + query fetchDomains { + domains { + id + title + } + } + `, props, signal: signal() }) - dispatch(setDomainsValue(data)) + dispatch(setDomainsValue(data.domains)) dispatch(setDomainsFetching(false)) } catch (err) { - dispatch(setDomainsError(err)) + if (err.name === 'AbortError') return dispatch(setDomainsFetching(false)) + if (err.name === 'HandledError') return + dispatch(setDomainsError(err)) } @@ -52,9 +61,19 @@ export const addDomain = (props, state) => async (dispatch) => { try { - await api(`/domains`, { - method: 'post', - body: JSON.stringify(state), + await api({ + query: ` + mutation createDomain($input: CreateDomainInput!) { + createDomain(input: $input) { + success + } + } + `, + variables: { + input: { + title: state.title + } + }, props }) @@ -63,8 +82,10 @@ export const addDomain = (props, state) => async (dispatch) => { } catch (err) { - dispatch(setDomainsError(err)) + if (err.name === 'AbortError') return dispatch(setDomainsFetching(false)) + if (err.name === 'HandledError') return + dispatch(setDomainsError(err)) } @@ -77,9 +98,20 @@ export const updateDomain = signalHandler((signal) => (props, domainId, state) = try { - await api(`/domains/${ domainId }`, { - method: 'put', - body: JSON.stringify(state), + await api({ + query: ` + mutation updateDomain($id: ID!, $input: UpdateDomainInput!) { + updateDomain(id: $id, input: $input) { + success + } + } + `, + variables: { + id: domainId, + input: { + title: state.title + } + }, props, signal: signal(domainId) }) @@ -89,23 +121,33 @@ export const updateDomain = signalHandler((signal) => (props, domainId, state) = } catch (err) { - dispatch(setDomainsError(err)) + if (err.name === 'AbortError') return dispatch(setDomainsFetching(false)) + if (err.name === 'HandledError') return + dispatch(setDomainsError(err)) } }) -export const deleteDomain = signalHandler((signal) => (props, domainId, state) => async (dispatch) => { +export const deleteDomain = signalHandler((signal) => (props, domainId) => async (dispatch) => { dispatch(setDomainsFetching(true)) dispatch(setDomainsError()) try { - await api(`/domains/${ domainId }`, { - method: 'delete', - body: JSON.stringify(state), + await api({ + query: ` + mutation deleteDomain($id: ID!) { + deleteDomain(id: $id) { + success + } + } + `, + variables: { + id: domainId + }, props, signal: signal(domainId) }) @@ -115,8 +157,10 @@ export const deleteDomain = signalHandler((signal) => (props, domainId, state) = } catch (err) { - dispatch(setDomainsError(err)) + if (err.name === 'AbortError') return dispatch(setDomainsFetching(false)) + if (err.name === 'HandledError') return + dispatch(setDomainsError(err)) } diff --git a/src/ui/scripts/actions/durations.js b/src/ui/scripts/actions/durations.js index b03faa37..2332b697 100644 --- a/src/ui/scripts/actions/durations.js +++ b/src/ui/scripts/actions/durations.js @@ -1,54 +1,65 @@ import api from '../utils/api' import signalHandler from '../utils/signalHandler' -export const SET_DURATIONS_TYPE = Symbol() export const SET_DURATIONS_VALUE = Symbol() export const SET_DURATIONS_FETCHING = Symbol() export const SET_DURATIONS_ERROR = Symbol() -export const setDurationsType = (payload) => ({ - type: SET_DURATIONS_TYPE, - payload -}) - export const setDurationsValue = (domainId, payload) => ({ type: SET_DURATIONS_VALUE, domainId, payload }) -export const setDurationsFetching = (domainId, payload) => ({ +export const setDurationsFetching = (payload) => ({ type: SET_DURATIONS_FETCHING, - domainId, payload }) -export const setDurationsError = (domainId, payload) => ({ +export const setDurationsError = (payload) => ({ type: SET_DURATIONS_ERROR, - domainId, payload }) -export const fetchDurations = signalHandler((signal) => (props, domainId) => async (dispatch) => { +export const fetchDurations = signalHandler((signal) => (props) => async (dispatch) => { - dispatch(setDurationsFetching(domainId, true)) - dispatch(setDurationsError(domainId)) + dispatch(setDurationsFetching(true)) + dispatch(setDurationsError()) try { - const data = await api(`/domains/${ domainId }/durations?type=${ props.durations.type }`, { - method: 'get', + const data = await api({ + query: ` + query fetchDurations($interval: Interval!) { + domains { + id + statistics { + durations(interval: $interval) { + id + count + } + } + } + } + `, + variables: { + interval: props.filter.interval + }, props, - signal: signal(domainId) + signal: signal() }) - dispatch(setDurationsValue(domainId, data)) - dispatch(setDurationsFetching(domainId, false)) + data.domains.forEach((domain) => { + dispatch(setDurationsValue(domain.id, domain.statistics.durations)) + }) + dispatch(setDurationsFetching(false)) } catch (err) { - dispatch(setDurationsError(domainId, err)) - dispatch(setDurationsFetching(domainId, false)) + if (err.name === 'AbortError') return + dispatch(setDurationsFetching(false)) + if (err.name === 'HandledError') return + dispatch(setDurationsError(err)) } diff --git a/src/ui/scripts/actions/filter.js b/src/ui/scripts/actions/filter.js index 1f78cb3a..b0dbc4fd 100644 --- a/src/ui/scripts/actions/filter.js +++ b/src/ui/scripts/actions/filter.js @@ -1,6 +1,18 @@ +export const SET_FILTER_SORTING = Symbol() export const SET_FILTER_RANGE = Symbol() +export const SET_FILTER_INTERVAL = Symbol() + +export const setFilterSorting = (payload) => ({ + type: SET_FILTER_SORTING, + payload +}) export const setFilterRange = (payload) => ({ type: SET_FILTER_RANGE, payload +}) + +export const setFilterInterval = (payload) => ({ + type: SET_FILTER_INTERVAL, + payload }) \ No newline at end of file diff --git a/src/ui/scripts/actions/index.js b/src/ui/scripts/actions/index.js index df4f6ab8..b71ee31f 100644 --- a/src/ui/scripts/actions/index.js +++ b/src/ui/scripts/actions/index.js @@ -3,6 +3,7 @@ export * from './token' export * from './route' export * from './filter' export * from './domains' +export * from './overview' export * from './views' export * from './pages' export * from './referrers' diff --git a/src/ui/scripts/actions/languages.js b/src/ui/scripts/actions/languages.js index eb432a60..90ccdb27 100644 --- a/src/ui/scripts/actions/languages.js +++ b/src/ui/scripts/actions/languages.js @@ -1,54 +1,67 @@ import api from '../utils/api' import signalHandler from '../utils/signalHandler' -export const SET_LANGUAGES_SORTING = Symbol() export const SET_LANGUAGES_VALUE = Symbol() export const SET_LANGUAGES_FETCHING = Symbol() export const SET_LANGUAGES_ERROR = Symbol() -export const setLanguagesSorting = (payload) => ({ - type: SET_LANGUAGES_SORTING, - payload -}) - export const setLanguagesValue = (domainId, payload) => ({ type: SET_LANGUAGES_VALUE, domainId, payload }) -export const setLanguagesFetching = (domainId, payload) => ({ +export const setLanguagesFetching = (payload) => ({ type: SET_LANGUAGES_FETCHING, - domainId, payload }) -export const setLanguagesError = (domainId, payload) => ({ +export const setLanguagesError = (payload) => ({ type: SET_LANGUAGES_ERROR, - domainId, payload }) -export const fetchLanguages = signalHandler((signal) => (props, domainId) => async (dispatch) => { +export const fetchLanguages = signalHandler((signal) => (props) => async (dispatch) => { - dispatch(setLanguagesFetching(domainId, true)) - dispatch(setLanguagesError(domainId)) + dispatch(setLanguagesFetching(true)) + dispatch(setLanguagesError()) try { - const data = await api(`/domains/${ domainId }/languages?sorting=${ props.languages.sorting }&range=${ props.filter.range }`, { - method: 'get', + const data = await api({ + query: ` + query fetchLanguages($sorting: Sorting!, $range: Range) { + domains { + id + statistics { + languages(sorting: $sorting, range: $range) { + id + count + created + } + } + } + } + `, + variables: { + sorting: props.filter.sorting, + range: props.filter.range + }, props, - signal: signal(domainId) + signal: signal() }) - dispatch(setLanguagesValue(domainId, data)) - dispatch(setLanguagesFetching(domainId, false)) + data.domains.forEach((domain) => { + dispatch(setLanguagesValue(domain.id, domain.statistics.languages)) + }) + dispatch(setLanguagesFetching(false)) } catch (err) { - dispatch(setLanguagesError(domainId, err)) - dispatch(setLanguagesFetching(domainId, false)) + if (err.name === 'AbortError') return + dispatch(setLanguagesFetching(false)) + if (err.name === 'HandledError') return + dispatch(setLanguagesError(err)) } diff --git a/src/ui/scripts/actions/overview.js b/src/ui/scripts/actions/overview.js new file mode 100644 index 00000000..09e4ffc0 --- /dev/null +++ b/src/ui/scripts/actions/overview.js @@ -0,0 +1,162 @@ +import api from '../utils/api' +import signalHandler from '../utils/signalHandler' +import { initialState as initialFilterState } from '../reducers/filter' + +export const ALL_DOMAINS = Symbol() + +export const SET_OVERVIEW_FACTS = Symbol() +export const SET_OVERVIEW_STATISTICS = Symbol() +export const SET_OVERVIEW_FETCHING = Symbol() +export const SET_OVERVIEW_ERROR = Symbol() + +export const setOverviewFacts = (domainId, payload) => ({ + type: SET_OVERVIEW_FACTS, + domainId, + payload +}) + +export const setOverviewStatistics = (domainId, payload) => ({ + type: SET_OVERVIEW_STATISTICS, + domainId, + payload +}) + +export const setOverviewFetching = (domainId, payload) => ({ + type: SET_OVERVIEW_FETCHING, + domainId, + payload +}) + +export const setOverviewError = (domainId, payload) => ({ + type: SET_OVERVIEW_ERROR, + domainId, + payload +}) + +export const fetchOverview = signalHandler((signal) => (props, domainId) => async (dispatch) => { + + dispatch(setOverviewFetching(domainId, true)) + dispatch(setOverviewError(domainId)) + + const filterState = initialFilterState() + + try { + + const facts = ` + facts { + activeVisitors + averageViews + averageDuration + viewsToday + viewsMonth + viewsYear + } + ` + + const statistics = ` + statistics { + views(interval: $interval, type: UNIQUE) { + id + count + } + pages(sorting: $sorting, range: $range) { + id + count + created + } + referrers(sorting: $sorting, range: $range) { + id + count + created + } + durations(interval: $interval) { + id + count + } + systems(sorting: $sorting, type: WITH_VERSION, range: $range) { + id + count + created + } + devices(sorting: $sorting, type: WITH_MODEL, range: $range) { + id + count + created + } + browsers(sorting: $sorting, type: WITH_VERSION, range: $range) { + id + count + created + } + sizes(sorting: $sorting, type: BROWSER_RESOLUTION, range: $range) { + id + count + created + } + languages(sorting: $sorting, range: $range) { + id + count + created + } + } + ` + + if (domainId === ALL_DOMAINS) { + + const data = await api({ + query: ` + query fetchOverview($interval: Interval!, $sorting: Sorting!, $range: Range, ) { + ${ facts } + ${ statistics } + } + `, + variables: { + interval: filterState.interval, + sorting: filterState.sorting, + range: filterState.range + }, + props, + signal: signal(domainId) + }) + + dispatch(setOverviewFacts(domainId, data.facts)) + dispatch(setOverviewStatistics(domainId, data.statistics)) + + } else { + + const data = await api({ + query: ` + query fetchOverview($id: ID!, $interval: Interval!, $sorting: Sorting!, $range: Range) { + domain(id: $id) { + ${ facts } + ${ statistics } + } + } + `, + variables: { + id: domainId, + interval: filterState.interval, + sorting: filterState.sorting, + range: filterState.range + }, + props, + signal: signal(domainId) + }) + + dispatch(setOverviewFacts(domainId, data.domain.facts)) + dispatch(setOverviewStatistics(domainId, data.domain.statistics)) + + } + + dispatch(setOverviewFetching(domainId, false)) + + } catch (err) { + + if (err.name === 'AbortError') return + dispatch(setOverviewFetching(domainId, false)) + if (err.name === 'HandledError') return + dispatch(setOverviewError(domainId, err)) + + } + +}) \ No newline at end of file diff --git a/src/ui/scripts/actions/pages.js b/src/ui/scripts/actions/pages.js index 700df80e..b47720c5 100644 --- a/src/ui/scripts/actions/pages.js +++ b/src/ui/scripts/actions/pages.js @@ -1,54 +1,67 @@ import api from '../utils/api' import signalHandler from '../utils/signalHandler' -export const SET_PAGES_SORTING = Symbol() export const SET_PAGES_VALUE = Symbol() export const SET_PAGES_FETCHING = Symbol() export const SET_PAGES_ERROR = Symbol() -export const setPagesSorting = (payload) => ({ - type: SET_PAGES_SORTING, - payload -}) - export const setPagesValue = (domainId, payload) => ({ type: SET_PAGES_VALUE, domainId, payload }) -export const setPagesFetching = (domainId, payload) => ({ +export const setPagesFetching = (payload) => ({ type: SET_PAGES_FETCHING, - domainId, payload }) -export const setPagesError = (domainId, payload) => ({ +export const setPagesError = (payload) => ({ type: SET_PAGES_ERROR, - domainId, payload }) -export const fetchPages = signalHandler((signal) => (props, domainId) => async (dispatch) => { +export const fetchPages = signalHandler((signal) => (props) => async (dispatch) => { - dispatch(setPagesFetching(domainId, true)) - dispatch(setPagesError(domainId)) + dispatch(setPagesFetching(true)) + dispatch(setPagesError()) try { - const data = await api(`/domains/${ domainId }/pages?sorting=${ props.pages.sorting }&range=${ props.filter.range }`, { - method: 'get', + const data = await api({ + query: ` + query fetchPages($sorting: Sorting!, $range: Range) { + domains { + id + statistics { + pages(sorting: $sorting, range: $range) { + id + count + created + } + } + } + } + `, + variables: { + sorting: props.filter.sorting, + range: props.filter.range + }, props, - signal: signal(domainId) + signal: signal() }) - dispatch(setPagesValue(domainId, data)) - dispatch(setPagesFetching(domainId, false)) + data.domains.forEach((domain) => { + dispatch(setPagesValue(domain.id, domain.statistics.pages)) + }) + dispatch(setPagesFetching(false)) } catch (err) { - dispatch(setPagesError(domainId, err)) - dispatch(setPagesFetching(domainId, false)) + if (err.name === 'AbortError') return + dispatch(setPagesFetching(false)) + if (err.name === 'HandledError') return + dispatch(setPagesError(err)) } diff --git a/src/ui/scripts/actions/referrers.js b/src/ui/scripts/actions/referrers.js index e069fbb4..23b89e08 100644 --- a/src/ui/scripts/actions/referrers.js +++ b/src/ui/scripts/actions/referrers.js @@ -1,54 +1,67 @@ import api from '../utils/api' import signalHandler from '../utils/signalHandler' -export const SET_REFERRERS_SORTING = Symbol() export const SET_REFERRERS_VALUE = Symbol() export const SET_REFERRERS_FETCHING = Symbol() export const SET_REFERRERS_ERROR = Symbol() -export const setReferrersSorting = (payload) => ({ - type: SET_REFERRERS_SORTING, - payload -}) - export const setReferrersValue = (domainId, payload) => ({ type: SET_REFERRERS_VALUE, domainId, payload }) -export const setReferrersFetching = (domainId, payload) => ({ +export const setReferrersFetching = (payload) => ({ type: SET_REFERRERS_FETCHING, - domainId, payload }) -export const setReferrersError = (domainId, payload) => ({ +export const setReferrersError = (payload) => ({ type: SET_REFERRERS_ERROR, - domainId, payload }) -export const fetchReferrers = signalHandler((signal) => (props, domainId) => async (dispatch) => { +export const fetchReferrers = signalHandler((signal) => (props) => async (dispatch) => { - dispatch(setReferrersFetching(domainId, true)) - dispatch(setReferrersError(domainId)) + dispatch(setReferrersFetching(true)) + dispatch(setReferrersError()) try { - const data = await api(`/domains/${ domainId }/referrers?sorting=${ props.referrers.sorting }&range=${ props.filter.range }`, { - method: 'get', + const data = await api({ + query: ` + query fetchReferrers($sorting: Sorting!, $range: Range) { + domains { + id + statistics { + referrers(sorting: $sorting, range: $range) { + id + count + created + } + } + } + } + `, + variables: { + sorting: props.filter.sorting, + range: props.filter.range + }, props, - signal: signal(domainId) + signal: signal() }) - dispatch(setReferrersValue(domainId, data)) - dispatch(setReferrersFetching(domainId, false)) + data.domains.forEach((domain) => { + dispatch(setReferrersValue(domain.id, domain.statistics.referrers)) + }) + dispatch(setReferrersFetching(false)) } catch (err) { - dispatch(setReferrersError(domainId, err)) - dispatch(setReferrersFetching(domainId, false)) + if (err.name === 'AbortError') return + dispatch(setReferrersFetching(false)) + if (err.name === 'HandledError') return + dispatch(setReferrersError(err)) } diff --git a/src/ui/scripts/actions/route.js b/src/ui/scripts/actions/route.js index 218cbca8..619e709a 100644 --- a/src/ui/scripts/actions/route.js +++ b/src/ui/scripts/actions/route.js @@ -1,6 +1,7 @@ -export const SET_ROUTE_VALUE = Symbol() +export const SET_ROUTE = Symbol() -export const setRouteValue = (payload) => ({ - type: SET_ROUTE_VALUE, - payload +export const setRoute = (payload) => ({ + type: SET_ROUTE, + key: payload.key, + params: payload.params || {} }) \ No newline at end of file diff --git a/src/ui/scripts/actions/sizes.js b/src/ui/scripts/actions/sizes.js index a2862bc9..410da14a 100644 --- a/src/ui/scripts/actions/sizes.js +++ b/src/ui/scripts/actions/sizes.js @@ -17,38 +17,58 @@ export const setSizesValue = (domainId, payload) => ({ payload }) -export const setSizesFetching = (domainId, payload) => ({ +export const setSizesFetching = (payload) => ({ type: SET_SIZES_FETCHING, - domainId, payload }) -export const setSizesError = (domainId, payload) => ({ +export const setSizesError = (payload) => ({ type: SET_SIZES_ERROR, - domainId, payload }) -export const fetchSizes = signalHandler((signal) => (props, domainId) => async (dispatch) => { +export const fetchSizes = signalHandler((signal) => (props) => async (dispatch) => { - dispatch(setSizesFetching(domainId, true)) - dispatch(setSizesError(domainId)) + dispatch(setSizesFetching(true)) + dispatch(setSizesError()) try { - const data = await api(`/domains/${ domainId }/sizes?type=${ props.sizes.type }&range=${ props.filter.range }`, { - method: 'get', + const data = await api({ + query: ` + query fetchSizes($sorting: Sorting!, $type: SizeType!, $range: Range) { + domains { + id + statistics { + sizes(sorting: $sorting, type: $type, range: $range) { + id + count + created + } + } + } + } + `, + variables: { + sorting: props.filter.sorting, + type: props.sizes.type, + range: props.filter.range + }, props, - signal: signal(domainId) + signal: signal() }) - dispatch(setSizesValue(domainId, data)) - dispatch(setSizesFetching(domainId, false)) + data.domains.forEach((domain) => { + dispatch(setSizesValue(domain.id, domain.statistics.sizes)) + }) + dispatch(setSizesFetching(false)) } catch (err) { - dispatch(setSizesError(domainId, err)) - dispatch(setSizesFetching(domainId, false)) + if (err.name === 'AbortError') return + dispatch(setSizesFetching(false)) + if (err.name === 'HandledError') return + dispatch(setSizesError(err)) } diff --git a/src/ui/scripts/actions/systems.js b/src/ui/scripts/actions/systems.js index def37f5b..e2a1feb2 100644 --- a/src/ui/scripts/actions/systems.js +++ b/src/ui/scripts/actions/systems.js @@ -2,16 +2,10 @@ import api from '../utils/api' import signalHandler from '../utils/signalHandler' export const SET_SYSTEMS_TYPE = Symbol() -export const SET_SYSTEMS_SORTING = Symbol() export const SET_SYSTEMS_VALUE = Symbol() export const SET_SYSTEMS_FETCHING = Symbol() export const SET_SYSTEMS_ERROR = Symbol() -export const setSystemsSorting = (payload) => ({ - type: SET_SYSTEMS_SORTING, - payload -}) - export const setSystemsType = (payload) => ({ type: SET_SYSTEMS_TYPE, payload @@ -23,38 +17,58 @@ export const setSystemsValue = (domainId, payload) => ({ payload }) -export const setSystemsFetching = (domainId, payload) => ({ +export const setSystemsFetching = (payload) => ({ type: SET_SYSTEMS_FETCHING, - domainId, payload }) -export const setSystemsError = (domainId, payload) => ({ +export const setSystemsError = (payload) => ({ type: SET_SYSTEMS_ERROR, - domainId, payload }) -export const fetchSystems = signalHandler((signal) => (props, domainId) => async (dispatch) => { +export const fetchSystems = signalHandler((signal) => (props) => async (dispatch) => { - dispatch(setSystemsFetching(domainId, true)) - dispatch(setSystemsError(domainId)) + dispatch(setSystemsFetching(true)) + dispatch(setSystemsError()) try { - const data = await api(`/domains/${ domainId }/systems?sorting=${ props.systems.sorting }&type=${ props.systems.type }&range=${ props.filter.range }`, { - method: 'get', + const data = await api({ + query: ` + query fetchSystems($sorting: Sorting!, $type: SystemType!, $range: Range) { + domains { + id + statistics { + systems(sorting: $sorting, type: $type, range: $range) { + id + count + created + } + } + } + } + `, + variables: { + sorting: props.filter.sorting, + type: props.systems.type, + range: props.filter.range + }, props, - signal: signal(domainId) + signal: signal() }) - dispatch(setSystemsValue(domainId, data)) - dispatch(setSystemsFetching(domainId, false)) + data.domains.forEach((domain) => { + dispatch(setSystemsValue(domain.id, domain.statistics.systems)) + }) + dispatch(setSystemsFetching(false)) } catch (err) { - dispatch(setSystemsError(domainId, err)) - dispatch(setSystemsFetching(domainId, false)) + if (err.name === 'AbortError') return + dispatch(setSystemsFetching(false)) + if (err.name === 'HandledError') return + dispatch(setSystemsError(err)) } diff --git a/src/ui/scripts/actions/token.js b/src/ui/scripts/actions/token.js index 31f0d142..6530a165 100644 --- a/src/ui/scripts/actions/token.js +++ b/src/ui/scripts/actions/token.js @@ -29,20 +29,36 @@ export const addToken = signalHandler((signal) => (props, state) => async (dispa try { - const data = await api('/tokens', { - method: 'post', - body: JSON.stringify(state), + const data = await api({ + query: ` + mutation createToken($input: CreateTokenInput!) { + createToken(input: $input) { + payload { + id + } + } + } + `, + variables: { + input: { + username: state.username, + password: state.password + } + }, props, signal: signal() }) - dispatch(setTokenValue(data)) + // TODO: Maybe just store the id instead of the payload + dispatch(setTokenValue(data.createToken.payload)) dispatch(setTokenFetching(false)) } catch (err) { - dispatch(setTokenError(err)) + if (err.name === 'AbortError') return dispatch(setTokenFetching(false)) + if (err.name === 'HandledError') return + dispatch(setTokenError(err)) } @@ -54,14 +70,25 @@ export const deleteToken = signalHandler((signal) => (props) => async (dispatch) try { - await api(`/tokens/${ props.token.value.id }`, { - method: 'delete', + await api({ + query: ` + mutation deleteToken($id: ID!) { + deleteToken(id: $id) { + success + } + } + `, + variables: { + id: props.token.value.id + }, props, signal: signal() }) } catch (err) { + if (err.name === 'AbortError') return + if (err.name === 'HandledError') return dispatch(setTokenError(err)) } diff --git a/src/ui/scripts/actions/views.js b/src/ui/scripts/actions/views.js index 0cef7e16..9b8a4a82 100644 --- a/src/ui/scripts/actions/views.js +++ b/src/ui/scripts/actions/views.js @@ -2,7 +2,6 @@ import api from '../utils/api' import signalHandler from '../utils/signalHandler' export const SET_VIEWS_TYPE = Symbol() -export const SET_VIEWS_INTERVAL = Symbol() export const SET_VIEWS_VALUE = Symbol() export const SET_VIEWS_FETCHING = Symbol() export const SET_VIEWS_ERROR = Symbol() @@ -12,49 +11,62 @@ export const setViewsType = (payload) => ({ payload }) -export const setViewsInterval = (payload) => ({ - type: SET_VIEWS_INTERVAL, - payload -}) - export const setViewsValue = (domainId, payload) => ({ type: SET_VIEWS_VALUE, domainId, payload }) -export const setViewsFetching = (domainId, payload) => ({ +export const setViewsFetching = (payload) => ({ type: SET_VIEWS_FETCHING, - domainId, payload }) -export const setViewsError = (domainId, payload) => ({ +export const setViewsError = (payload) => ({ type: SET_VIEWS_ERROR, - domainId, payload }) -export const fetchViews = signalHandler((signal) => (props, domainId) => async (dispatch) => { +export const fetchViews = signalHandler((signal) => (props) => async (dispatch) => { - dispatch(setViewsFetching(domainId, true)) - dispatch(setViewsError(domainId)) + dispatch(setViewsFetching(true)) + dispatch(setViewsError()) try { - const data = await api(`/domains/${ domainId }/views?type=${ props.views.type }&interval=${ props.views.interval }`, { - method: 'get', + const data = await api({ + query: ` + query fetchViews($interval: Interval!, $type: ViewType!) { + domains { + id + statistics { + views(interval: $interval, type: $type) { + id + count + } + } + } + } + `, + variables: { + interval: props.filter.interval, + type: props.views.type + }, props, - signal: signal(domainId) + signal: signal() }) - dispatch(setViewsValue(domainId, data)) - dispatch(setViewsFetching(domainId, false)) + data.domains.forEach((domain) => { + dispatch(setViewsValue(domain.id, domain.statistics.views)) + }) + dispatch(setViewsFetching(false)) } catch (err) { - dispatch(setViewsError(domainId, err)) - dispatch(setViewsFetching(domainId, false)) + if (err.name === 'AbortError') return + dispatch(setViewsFetching(false)) + if (err.name === 'HandledError') return + dispatch(setViewsError(err)) } diff --git a/src/ui/scripts/components/Context.js b/src/ui/scripts/components/Context.js index 2e616e12..b6122dc0 100644 --- a/src/ui/scripts/components/Context.js +++ b/src/ui/scripts/components/Context.js @@ -6,11 +6,53 @@ import { useClickAway } from 'react-use' import useMeasure from '../utils/useMeasure' +import KeyHint from './KeyHint' + export const BUTTON = Symbol() export const SEPARATOR = Symbol() const toPixel = (num) => `${ Math.round(num) }px` +const Button = (props) => { + + const hasKeyHint = props.keyHint != null + const hasKeyDescription = props.description != null + + return ( + h('button', { + className: classNames({ + context__button: true, + active: props.active === true, + link: true + }), + onClick: props.onClick + }, + h('div', { className: 'context__head' }, + h('div', { className: 'context__label' }, props.label), + hasKeyHint === true && h(KeyHint, {}, props.keyHint) + ), + hasKeyDescription === true && h('div', { className: 'context__description' }, props.description) + ) + ) + +} + +Button.propTypes = { + label: PropTypes.string.isRequired, + description: PropTypes.string, + active: PropTypes.bool.isRequired, + onClick: PropTypes.func.isRequired, + keyHint: PropTypes.node +} + +const Separator = () => { + + return ( + h('div', { className: 'context__separator' }) + ) + +} + const Context = (props) => { const ref = useRef() @@ -36,25 +78,17 @@ const Context = (props) => { }, props.items.map((item, index) => { - if (item.type === BUTTON) return h('button', { + if (item.type === BUTTON) return h(Button, { key: item.label + index, - className: classNames({ - context__button: true, - active: item.active === true, - link: true - }), + ...item, onClick: (e) => { item.onClick(e) props.onItemClick(e) } - }, - h('div', {}, item.label), - item.description != null && h('div', { className: 'context__description' }, item.description) - ) - - if (item.type === SEPARATOR) return h('div', { - key: index, - className: 'context__separator' + }) + + if (item.type === SEPARATOR) return h(Separator, { + key: index }) }) diff --git a/src/ui/scripts/components/Dashboard.js b/src/ui/scripts/components/Dashboard.js index cf26fced..f21d9f28 100644 --- a/src/ui/scripts/components/Dashboard.js +++ b/src/ui/scripts/components/Dashboard.js @@ -1,68 +1,95 @@ -import { createElement as h } from 'react' - -import { - ROUTE_VIEWS, - ROUTE_PAGES, - ROUTE_REFERRERS, - ROUTE_DURATIONS, - ROUTE_LANGUAGES, - ROUTE_SIZES, - ROUTE_SYSTEMS, - ROUTE_SETTINGS, - ROUTE_DEVICES, - ROUTE_BROWSERS -} from '../constants/route' - -import Header, { createButton, createDropdown, createDropdownButton } from './Header' -import RouteViews from './routes/RouteViews' -import RoutePages from './routes/RoutePages' -import RouteReferrers from './routes/RouteReferrers' -import RouteDurations from './routes/RouteDurations' -import RouteBrowsers from './routes/RouteBrowsers' -import RouteDevices from './routes/RouteDevices' -import RouteLanguages from './routes/RouteLanguages' -import RouteSystems from './routes/RouteSystems' -import RouteSizes from './routes/RouteSizes' -import RouteSettings from './routes/RouteSettings' +import { createElement as h, useEffect } from 'react' +import { useHotkeys } from 'react-hotkeys-hook' + +import * as route from '../constants/route' +import * as selectDomainsValue from '../selectors/selectDomainsValue' +import routeByKey from '../utils/routeByKey' +import whenBelow from '../utils/whenBelow' +import overviewRoute from '../utils/overviewRoute' +import isDefined from '../../../utils/isDefined' + +import Header, { createButton, createDropdown, createDropdownButton, createDropdownSeparator } from './Header' import Modals from './Modals' -const routesMap = { - [ROUTE_VIEWS]: RouteViews, - [ROUTE_PAGES]: RoutePages, - [ROUTE_REFERRERS]: RouteReferrers, - [ROUTE_DURATIONS]: RouteDurations, - [ROUTE_SYSTEMS]: RouteSystems, - [ROUTE_DEVICES]: RouteDevices, - [ROUTE_BROWSERS]: RouteBrowsers, - [ROUTE_SIZES]: RouteSizes, - [ROUTE_LANGUAGES]: RouteLanguages, - [ROUTE_SETTINGS]: RouteSettings +const gotoDomainWhenDefined = (props, index) => { + + const domain = selectDomainsValue.byIndex(props, index) + if (domain != null) props.setRoute(overviewRoute(domain)) + } const Dashboard = (props) => { + const routeIdentifier = JSON.stringify(props.route) + + useEffect(() => { + + props.fetchDomains(props) + + }, []) + + useEffect(() => { + + document.scrollingElement.scrollTop = 0 + + }, [ routeIdentifier ]) + + useHotkeys('o', () => props.setRoute(route.ROUTE_OVERVIEW)) + + useHotkeys('v', () => props.setRoute(route.ROUTE_VIEWS)) + useHotkeys('p', () => props.setRoute(route.ROUTE_PAGES)) + useHotkeys('r', () => props.setRoute(route.ROUTE_REFERRERS)) + useHotkeys('d', () => props.setRoute(route.ROUTE_DURATIONS)) + + useHotkeys('0', () => gotoDomainWhenDefined(props, 0), [ props ]) + useHotkeys('1', () => gotoDomainWhenDefined(props, 1), [ props ]) + useHotkeys('2', () => gotoDomainWhenDefined(props, 2), [ props ]) + useHotkeys('3', () => gotoDomainWhenDefined(props, 3), [ props ]) + useHotkeys('4', () => gotoDomainWhenDefined(props, 4), [ props ]) + useHotkeys('5', () => gotoDomainWhenDefined(props, 5), [ props ]) + useHotkeys('6', () => gotoDomainWhenDefined(props, 6), [ props ]) + useHotkeys('7', () => gotoDomainWhenDefined(props, 7), [ props ]) + useHotkeys('8', () => gotoDomainWhenDefined(props, 8), [ props ]) + useHotkeys('9', () => gotoDomainWhenDefined(props, 9), [ props ]) + + const hasDomains = props.domains.value.length > 0 + + const domainsLabel = (activeInside) => activeInside === true ? selectDomainsValue.byId(props, props.route.params.domainId).title : 'Domains' + const insightsLabel = (activeInside) => activeInside === true ? routeByKey(props.route.key).title : 'Insights' + + const domainsItems = props.domains.value.map((domain, index) => + createDropdownButton(domain.title, overviewRoute(domain), props, whenBelow(index, 10)) + ) + + const insightsItems = [ + createDropdownButton(route.ROUTE_VIEWS.title, route.ROUTE_VIEWS, props, 'v'), + createDropdownButton(route.ROUTE_PAGES.title, route.ROUTE_PAGES, props, 'p'), + createDropdownButton(route.ROUTE_REFERRERS.title, route.ROUTE_REFERRERS, props, 'r'), + createDropdownButton(route.ROUTE_DURATIONS.title, route.ROUTE_DURATIONS, props, 'd'), + createDropdownSeparator(), + createDropdownButton(route.ROUTE_SYSTEMS.title, route.ROUTE_SYSTEMS, props), + createDropdownButton(route.ROUTE_DEVICES.title, route.ROUTE_DEVICES, props), + createDropdownButton(route.ROUTE_BROWSERS.title, route.ROUTE_BROWSERS, props), + createDropdownButton(route.ROUTE_SIZES.title, route.ROUTE_SIZES, props), + createDropdownButton(route.ROUTE_LANGUAGES.title, route.ROUTE_LANGUAGES, props) + ] + + const items = [ + createButton(route.ROUTE_OVERVIEW.title, route.ROUTE_OVERVIEW, props), + hasDomains === true ? createDropdown(domainsLabel, domainsItems) : undefined, + createDropdown(insightsLabel, insightsItems), + createButton(route.ROUTE_SETTINGS.title, route.ROUTE_SETTINGS, props) + ].filter(isDefined) + return ( h('div', {}, h(Modals, props), h(Header, { fetching: props.fetching, - items: [ - createButton('Views', ROUTE_VIEWS, props), - createButton('Pages', ROUTE_PAGES, props), - createButton('Referrers', ROUTE_REFERRERS, props), - createButton('Durations', ROUTE_DURATIONS, props), - createDropdown('Detailed', [ - createDropdownButton('Systems', ROUTE_SYSTEMS, props), - createDropdownButton('Devices', ROUTE_DEVICES, props), - createDropdownButton('Browsers', ROUTE_BROWSERS, props), - createDropdownButton('Sizes', ROUTE_SIZES, props), - createDropdownButton('Languages', ROUTE_LANGUAGES, props) - ]), - createButton('Settings', ROUTE_SETTINGS, props) - ] + items }), h('main', { className: 'content' }, - h(routesMap[props.route.value], props) + h(routeByKey(props.route.key).component, props) ) ) ) diff --git a/src/ui/scripts/components/Filter.js b/src/ui/scripts/components/Filter.js index 942c6aca..e38f97f4 100644 --- a/src/ui/scripts/components/Filter.js +++ b/src/ui/scripts/components/Filter.js @@ -14,62 +14,88 @@ import { } from '../constants/route' import * as views from '../../../constants/views' -import * as pages from '../../../constants/pages' -import * as referrers from '../../../constants/referrers' -import * as durations from '../../../constants/durations' import * as systems from '../../../constants/systems' import * as devices from '../../../constants/devices' import * as browsers from '../../../constants/browsers' import * as sizes from '../../../constants/sizes' -import * as languages from '../../../constants/languages' +import * as sortings from '../../../constants/sortings' import * as ranges from '../../../constants/ranges' +import * as intervals from '../../../constants/intervals' import Context, { BUTTON, SEPARATOR } from './Context' import IconArrowDown from './icons/IconArrowDown' const labels = { - [ranges.RANGES_LAST_24_HOURS]: '24 hours', - [ranges.RANGES_LAST_7_DAYS]: '7 days', - [ranges.RANGES_LAST_30_DAYS]: '30 days', - [ranges.RANGES_ALL_TIME]: 'All time', - [views.VIEWS_TYPE_UNIQUE]: 'Unique', - [views.VIEWS_TYPE_TOTAL]: 'Total', - [views.VIEWS_INTERVAL_DAILY]: 'Daily', - [views.VIEWS_INTERVAL_MONTHLY]: 'Monthly', - [views.VIEWS_INTERVAL_YEARLY]: 'Yearly', - [pages.PAGES_SORTING_TOP]: 'Top', - [pages.PAGES_SORTING_RECENT]: 'Recent', - [referrers.REFERRERS_SORTING_TOP]: 'Top', - [referrers.REFERRERS_SORTING_NEW]: 'New', - [referrers.REFERRERS_SORTING_RECENT]: 'Recent', - [durations.DURATIONS_TYPE_AVERAGE]: 'Average', - [durations.DURATIONS_TYPE_DETAILED]: 'Detailed', - [systems.SYSTEMS_SORTING_TOP]: 'Top', - [systems.SYSTEMS_SORTING_RECENT]: 'Recent', - [devices.DEVICES_SORTING_TOP]: 'Top', - [devices.DEVICES_SORTING_RECENT]: 'Recent', - [browsers.BROWSERS_SORTING_TOP]: 'Top', - [browsers.BROWSERS_SORTING_RECENT]: 'Recent', - [sizes.SIZES_TYPE_BROWSER_RESOLUTION]: 'Browser sizes', - [sizes.SIZES_TYPE_BROWSER_WIDTH]: 'Browser widths', - [sizes.SIZES_TYPE_BROWSER_HEIGHT]: 'Browser heights', - [sizes.SIZES_TYPE_SCREEN_RESOLUTION]: 'Screen sizes', - [sizes.SIZES_TYPE_SCREEN_WIDTH]: 'Screen widths', - [sizes.SIZES_TYPE_SCREEN_HEIGHT]: 'Screen heights', - [languages.LANGUAGES_SORTING_TOP]: 'Top', - [languages.LANGUAGES_SORTING_RECENT]: 'Recent' + sortings: { + [sortings.SORTINGS_TOP]: 'Top', + [sortings.SORTINGS_NEW]: 'New', + [sortings.SORTINGS_RECENT]: 'Recent' + }, + ranges: { + [ranges.RANGES_LAST_24_HOURS]: '24 hours', + [ranges.RANGES_LAST_7_DAYS]: '7 days', + [ranges.RANGES_LAST_30_DAYS]: '30 days', + [ranges.RANGES_LAST_6_MONTHS]: '6 months' + }, + intervals: { + [intervals.INTERVALS_DAILY]: 'Daily', + [intervals.INTERVALS_MONTHLY]: 'Monthly', + [intervals.INTERVALS_YEARLY]: 'Yearly' + }, + views: { + [views.VIEWS_TYPE_UNIQUE]: 'Unique', + [views.VIEWS_TYPE_TOTAL]: 'Total' + }, + sizes: { + [sizes.SIZES_TYPE_BROWSER_RESOLUTION]: 'Browser sizes', + [sizes.SIZES_TYPE_BROWSER_WIDTH]: 'Browser widths', + [sizes.SIZES_TYPE_BROWSER_HEIGHT]: 'Browser heights', + [sizes.SIZES_TYPE_SCREEN_RESOLUTION]: 'Screen sizes', + [sizes.SIZES_TYPE_SCREEN_WIDTH]: 'Screen widths', + [sizes.SIZES_TYPE_SCREEN_HEIGHT]: 'Screen heights' + } } const calculateX = (measurement) => { - return measurement.target.relative.x + measurement.target.width / 2 - measurement.element.width / 2 + const padding = 10 + + return Math.max( + padding, + Math.min( + // Ensure that the context stays on the screen + measurement.body.width - measurement.element.width - padding, + // Ensure that the context is pinned to the target + measurement.target.relative.x + measurement.target.width / 2 - measurement.element.width / 2 + ) + ) } const calculateY = (measurement) => { - return measurement.target.relative.y - measurement.element.height - 10 +} + +const createItem = (label, items, visible = true) => ({ + label, + items, + visible +}) + +const createButton = (label, description, setter, key, value) => ({ + type: BUTTON, + label, + description, + active: key === value, + onClick: () => setter(value) +}) + +const createSeparator = () => ({ + type: SEPARATOR +}) +const onlyInactiveButton = (...buttons) => { + return buttons.find((button) => button.active === false) } const FilterItem = (props) => { @@ -108,98 +134,86 @@ const FilterItem = (props) => { const Filter = (props) => { - const shouldShowRange = (() => { - - if (props.route.value === ROUTE_PAGES && props.pages.sorting === pages.PAGES_SORTING_TOP) return true - if (props.route.value === ROUTE_REFERRERS && props.referrers.sorting === referrers.REFERRERS_SORTING_TOP) return true - if (props.route.value === ROUTE_SYSTEMS && props.systems.sorting === systems.SYSTEMS_SORTING_TOP) return true - if (props.route.value === ROUTE_DEVICES && props.devices.sorting === devices.DEVICES_SORTING_TOP) return true - if (props.route.value === ROUTE_BROWSERS && props.browsers.sorting === browsers.BROWSERS_SORTING_TOP) return true - if (props.route.value === ROUTE_SIZES) return true - if (props.route.value === ROUTE_LANGUAGES && props.languages.sorting === languages.LANGUAGES_SORTING_TOP) return true - - return false + const routeKey = props.route.key - })() + const sortingButtons = [ + createButton('Top', 'Top entries first', props.setFilterSorting, props.filter.sorting, sortings.SORTINGS_TOP), + createButton('New', 'New entries only', props.setFilterSorting, props.filter.sorting, sortings.SORTINGS_NEW), + createButton('Recent', 'Entries sorted by time', props.setFilterSorting, props.filter.sorting, sortings.SORTINGS_RECENT) + ] - const rangeButton = createItem(labels[props.filter.range], [ + const rangeButtons = [ createButton('24 hours', 'Show last 24 hours', props.setFilterRange, props.filter.range, ranges.RANGES_LAST_24_HOURS), createButton('7 days', 'Show last 7 days', props.setFilterRange, props.filter.range, ranges.RANGES_LAST_7_DAYS), createButton('30 days', 'Show last 30 days', props.setFilterRange, props.filter.range, ranges.RANGES_LAST_30_DAYS), - createButton('All time', 'Show all data', props.setFilterRange, props.filter.range, ranges.RANGES_ALL_TIME) - ], shouldShowRange === true) + createButton('6 months', 'Show last 6 months', props.setFilterRange, props.filter.range, ranges.RANGES_LAST_6_MONTHS) + ] + + const intervalsButtons = [ + createButton('Daily', 'Grouped by day', props.setFilterInterval, props.filter.interval, intervals.INTERVALS_DAILY), + createButton('Monthly', 'Grouped by month', props.setFilterInterval, props.filter.interval, intervals.INTERVALS_MONTHLY), + createButton('Yearly', 'Grouped by year', props.setFilterInterval, props.filter.interval, intervals.INTERVALS_YEARLY) + ] + + const sortingItem = createItem(labels.sortings[props.filter.sorting], sortingButtons) + const rangeItem = createItem(labels.ranges[props.filter.range], rangeButtons, props.filter.sorting === sortings.SORTINGS_TOP) + const intervalsItem = createItem(labels.intervals[props.filter.interval], intervalsButtons) const routesMap = { - [ROUTE_VIEWS]: [ - createItem(labels[props.views.type], [ + [ROUTE_VIEWS.key]: [ + createItem(labels.views[props.views.type], [ createButton('Unique', 'Unique site views', props.setViewsType, props.views.type, views.VIEWS_TYPE_UNIQUE), createButton('Total', 'Total page views', props.setViewsType, props.views.type, views.VIEWS_TYPE_TOTAL) ]), - createItem(labels[props.views.interval], [ - createButton('Daily', 'Grouped by day', props.setViewsInterval, props.views.interval, views.VIEWS_INTERVAL_DAILY), - createButton('Monthly', 'Grouped by month', props.setViewsInterval, props.views.interval, views.VIEWS_INTERVAL_MONTHLY), - createButton('Yearly', 'Grouped by year', props.setViewsInterval, props.views.interval, views.VIEWS_INTERVAL_YEARLY) - ]) + intervalsItem ], - [ROUTE_PAGES]: [ - createItem(labels[props.pages.sorting], [ - createButton('Top', 'Top page visits', props.setPagesSorting, props.pages.sorting, pages.PAGES_SORTING_TOP), - createButton('Recent', 'Recent page visits', props.setPagesSorting, props.pages.sorting, pages.PAGES_SORTING_RECENT) - ]), - rangeButton + [ROUTE_PAGES.key]: [ + sortingItem, + rangeItem ], - [ROUTE_REFERRERS]: [ - createItem(labels[props.referrers.sorting], [ - createButton('Top', 'Top referrers', props.setReferrersSorting, props.referrers.sorting, referrers.REFERRERS_SORTING_TOP), - createButton('New', 'New referrers', props.setReferrersSorting, props.referrers.sorting, referrers.REFERRERS_SORTING_NEW), - createButton('Recent', 'Recent referrers', props.setReferrersSorting, props.referrers.sorting, referrers.REFERRERS_SORTING_RECENT) - ]), - rangeButton + [ROUTE_REFERRERS.key]: [ + sortingItem, + rangeItem ], - [ROUTE_DURATIONS]: [ - createItem(labels[props.durations.type], [ - createButton('Average', 'Average durations', props.setDurationsType, props.durations.type, durations.DURATIONS_TYPE_AVERAGE), - createButton('Detailed', 'Detailed durations', props.setDurationsType, props.durations.type, durations.DURATIONS_TYPE_DETAILED) - ]) + [ROUTE_DURATIONS.key]: [ + intervalsItem ], - [ROUTE_SYSTEMS]: [ - createItem(labels[props.systems.sorting], [ - createButton('Top', 'Top systems', props.setSystemsSorting, props.systems.sorting, systems.SYSTEMS_SORTING_TOP), - createButton('Recent', 'Recent systems', props.setSystemsSorting, props.systems.sorting, systems.SYSTEMS_SORTING_RECENT), + [ROUTE_SYSTEMS.key]: [ + createItem(labels.sortings[props.filter.sorting], [ + ...sortingButtons, createSeparator(), onlyInactiveButton( createButton('Show version', 'Include system version', props.setSystemsType, props.systems.type, systems.SYSTEMS_TYPE_WITH_VERSION), createButton('Hide version', 'Don\'t include version', props.setSystemsType, props.systems.type, systems.SYSTEMS_TYPE_NO_VERSION) ) ]), - rangeButton + rangeItem ], - [ROUTE_DEVICES]: [ - createItem(labels[props.devices.sorting], [ - createButton('Top', 'Top systems', props.setDevicesSorting, props.devices.sorting, devices.DEVICES_SORTING_TOP), - createButton('Recent', 'Recent systems', props.setDevicesSorting, props.devices.sorting, devices.DEVICES_SORTING_RECENT), + [ROUTE_DEVICES.key]: [ + createItem(labels.sortings[props.filter.sorting], [ + ...sortingButtons, createSeparator(), onlyInactiveButton( createButton('Show model', 'Include device model', props.setDevicesType, props.devices.type, devices.DEVICES_TYPE_WITH_MODEL), createButton('Hide model', 'Don\'t include model', props.setDevicesType, props.devices.type, devices.DEVICES_TYPE_NO_MODEL) ) ]), - rangeButton + rangeItem ], - [ROUTE_BROWSERS]: [ - createItem(labels[props.browsers.sorting], [ - createButton('Top', 'Top systems', props.setBrowsersSorting, props.browsers.sorting, browsers.BROWSERS_SORTING_TOP), - createButton('Recent', 'Recent systems', props.setBrowsersSorting, props.browsers.sorting, browsers.BROWSERS_SORTING_RECENT), + [ROUTE_BROWSERS.key]: [ + createItem(labels.sortings[props.filter.sorting], [ + ...sortingButtons, createSeparator(), onlyInactiveButton( createButton('Show version', 'Include browser version', props.setBrowsersType, props.browsers.type, browsers.BROWSERS_TYPE_WITH_VERSION), createButton('Hide version', 'Don\'t include version', props.setBrowsersType, props.browsers.type, browsers.BROWSERS_TYPE_NO_VERSION) ) ]), - rangeButton + rangeItem ], - [ROUTE_SIZES]: [ - createItem(labels[props.sizes.type], [ + [ROUTE_SIZES.key]: [ + sortingItem, + createItem(labels.sizes[props.sizes.type], [ createButton('Browser sizes', 'Width and height combined', props.setSizesType, props.sizes.type, sizes.SIZES_TYPE_BROWSER_RESOLUTION), createButton('↳ widths', undefined, props.setSizesType, props.sizes.type, sizes.SIZES_TYPE_BROWSER_WIDTH), createButton('↳ heights', undefined, props.setSizesType, props.sizes.type, sizes.SIZES_TYPE_BROWSER_HEIGHT), @@ -208,18 +222,15 @@ const Filter = (props) => { createButton('↳ widths', undefined, props.setSizesType, props.sizes.type, sizes.SIZES_TYPE_SCREEN_WIDTH), createButton('↳ heights', undefined, props.setSizesType, props.sizes.type, sizes.SIZES_TYPE_SCREEN_HEIGHT) ]), - rangeButton + rangeItem ], - [ROUTE_LANGUAGES]: [ - createItem(labels[props.languages.sorting], [ - createButton('Top', 'Top languages', props.setLanguagesSorting, props.languages.sorting, languages.LANGUAGES_SORTING_TOP), - createButton('Recent', 'Recent languages', props.setLanguagesSorting, props.languages.sorting, languages.LANGUAGES_SORTING_RECENT) - ]), - rangeButton + [ROUTE_LANGUAGES.key]: [ + sortingItem, + rangeItem ] } - const currentButtons = routesMap[props.route.value] + const currentButtons = routesMap[routeKey] if (currentButtons == null) return null @@ -234,26 +245,4 @@ const Filter = (props) => { } -const createItem = (label, items, visible = true) => ({ - label, - items, - visible -}) - -const createButton = (label, description, setter, key, value) => ({ - type: BUTTON, - label, - description, - active: key === value, - onClick: () => setter(value) -}) - -const createSeparator = () => ({ - type: SEPARATOR -}) - -const onlyInactiveButton = (...buttons) => { - return buttons.find((button) => button.active === false) -} - export default Filter \ No newline at end of file diff --git a/src/ui/scripts/components/Header.js b/src/ui/scripts/components/Header.js index 20dd36a3..99acdd03 100644 --- a/src/ui/scripts/components/Header.js +++ b/src/ui/scripts/components/Header.js @@ -2,7 +2,9 @@ import { createElement as h, Fragment, useRef, useState } from 'react' import PropTypes from 'prop-types' import classNames from 'classnames' -import Context, { BUTTON as DROPDOWN_BUTTON } from './Context' +import isSameRoute from '../utils/isSameRoute' + +import Context, { BUTTON as DROPDOWN_BUTTON, SEPARATOR as DROPDOWN_SEPARATOR } from './Context' import IconArrowDown from './icons/IconArrowDown' const BUTTON = Symbol() @@ -10,11 +12,16 @@ const DROPDOWN = Symbol() const calculateX = (measurement) => { - return Math.min( - // Ensure that the context stays on the screen - measurement.body.width - measurement.element.width - 10, - // Ensure that the context is pinned to the target - measurement.target.absolute.x + measurement.target.width - measurement.element.width + const padding = 10 + + return Math.max( + padding, + Math.min( + // Ensure that the context stays on the screen + measurement.body.width - measurement.element.width - padding, + // Ensure that the context is pinned to the target + measurement.target.absolute.x + measurement.target.width - measurement.element.width + ) ) } @@ -25,6 +32,8 @@ const calculateY = (measurement) => { } +const containsActiveItem = (items) => items.some((item) => item.active === true) + const Spinner = (props) => { return ( @@ -77,7 +86,7 @@ const Dropdown = (props) => { const close = () => setActive(false) const toggle = () => setActive(!active) - const containsActiveItem = props.items.some((item) => item.active === true) + const activeInside = containsActiveItem(props.items) return ( h(Fragment, {}, @@ -86,9 +95,9 @@ const Dropdown = (props) => { className: classNames({ 'header__button': true, 'hovered': active === true, - 'active': containsActiveItem === true, + 'active': activeInside === true, 'link': true, - 'color-white': containsActiveItem === true + 'color-white': activeInside === true }), onClick: toggle }, @@ -118,14 +127,14 @@ const Header = (props) => { props.items.map((item, index) => { if (item.type === BUTTON) return h(Button, { - key: item.label + index, + key: index, ...item }, item.label) if (item.type === DROPDOWN) return h(Dropdown, { - key: item.label + index, + key: index, ...item - }, item.label) + }, item.label(containsActiveItem(item.items))) }) ) @@ -142,8 +151,8 @@ Header.propTypes = { export const createButton = (label, route, props) => ({ type: BUTTON, - onClick: () => props.setRouteValue(route), - active: props.route.value === route, + onClick: () => props.setRoute(route), + active: isSameRoute(props.route, route) === true, label }) @@ -153,11 +162,16 @@ export const createDropdown = (label, items) => ({ label }) -export const createDropdownButton = (label, route, props) => ({ +export const createDropdownButton = (label, route, props, keyHint) => ({ type: DROPDOWN_BUTTON, - onClick: () => props.setRouteValue(route), - active: props.route.value === route, - label + onClick: () => props.setRoute(route), + active: isSameRoute(props.route, route) === true, + label, + keyHint +}) + +export const createDropdownSeparator = () => ({ + type: DROPDOWN_SEPARATOR }) export default Header \ No newline at end of file diff --git a/src/ui/scripts/components/Headline.js b/src/ui/scripts/components/Headline.js index 9f59592c..b560bfc8 100644 --- a/src/ui/scripts/components/Headline.js +++ b/src/ui/scripts/components/Headline.js @@ -4,22 +4,32 @@ import classNames from 'classnames' const Headline = (props) => { + const hasClick = props.onClick != null + + const button = h('button', { + className: 'headline__button link', + onClick: props.onClick + }, props.children) + return ( h(props.type, { className: classNames({ 'headline': true, - 'headline--small': props.small === true + [`headline--${ props.size }`]: props.size != null, + 'headline--no-spacing': props.spacing === false }, props.className) - }, props.children) + }, hasClick === true ? button : props.children) ) } Headline.propTypes = { - type: PropTypes.oneOf([ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ]).isRequired, - small: PropTypes.bool, + type: PropTypes.oneOf([ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div' ]).isRequired, + size: PropTypes.oneOf([ 'medium', 'small' ]), + spacing: PropTypes.bool, className: PropTypes.string, - children: PropTypes.node.isRequired + children: PropTypes.node.isRequired, + onClick: PropTypes.func } export default Headline \ No newline at end of file diff --git a/src/ui/scripts/components/KeyHint.js b/src/ui/scripts/components/KeyHint.js new file mode 100644 index 00000000..9475af1a --- /dev/null +++ b/src/ui/scripts/components/KeyHint.js @@ -0,0 +1,16 @@ +import { createElement as h } from 'react' +import PropTypes from 'prop-types' + +const KeyHint = (props) => { + + return ( + h('div', { className: 'keyHint' }, props.children) + ) + +} + +KeyHint.propTypes = { + children: PropTypes.node.isRequired +} + +export default KeyHint \ No newline at end of file diff --git a/src/ui/scripts/components/Main.js b/src/ui/scripts/components/Main.js index e944e03b..2ff11220 100644 --- a/src/ui/scripts/components/Main.js +++ b/src/ui/scripts/components/Main.js @@ -31,4 +31,6 @@ const Main = (props) => { } -export default withErrorBoundary(Main, ErrorFallback) \ No newline at end of file +export default withErrorBoundary(Main, { + FallbackComponent: ErrorFallback +}) \ No newline at end of file diff --git a/src/ui/scripts/components/Modals.js b/src/ui/scripts/components/Modals.js index 8aa53ddf..04d1949d 100644 --- a/src/ui/scripts/components/Modals.js +++ b/src/ui/scripts/components/Modals.js @@ -11,13 +11,15 @@ import ModalDomainAdd from './modals/ModalDomainAdd' const Modals = (props) => { - const modals = Object.entries(props.modals.value).map(([ modalId, modalData ]) => { + const modals = Object.entries(props.modals.value).map(([ modalId, modalData ], index, modals) => { + const current = modals.length - 1 === index const closeModal = props.removeModalsModal.bind(null, modalId) return ( h(Modal, { key: modalId, visible: modalData.visible }, modalData.type === MODALS_DOMAIN_EDIT && h(ModalDomainEdit, { + current, id: modalData.props.id, title: modalData.props.title, fetching: props.domains.fetching, @@ -26,6 +28,7 @@ const Modals = (props) => { closeModal }), modalData.type === MODALS_DOMAIN_ADD && h(ModalDomainAdd, { + current, fetching: props.domains.fetching, addDomain: props.addDomain.bind(null, props), closeModal diff --git a/src/ui/scripts/components/Text.js b/src/ui/scripts/components/Text.js index 2b5b0285..65df50c0 100644 --- a/src/ui/scripts/components/Text.js +++ b/src/ui/scripts/components/Text.js @@ -5,7 +5,7 @@ import classNames from 'classnames' const Text = (props) => { return ( - h('p', { + h(props.type, { className: classNames({ 'text': true, 'text--no-spacing': props.spacing === false @@ -16,6 +16,7 @@ const Text = (props) => { } Text.propTypes = { + type: PropTypes.oneOf([ 'p', 'div' ]).isRequired, spacing: PropTypes.bool, className: PropTypes.string, children: PropTypes.node.isRequired diff --git a/src/ui/scripts/components/Updater.js b/src/ui/scripts/components/Updater.js new file mode 100644 index 00000000..ac05196e --- /dev/null +++ b/src/ui/scripts/components/Updater.js @@ -0,0 +1,13 @@ +import { createElement as h } from 'react' + +const Updater = () => { + + return ( + h('div', { className: 'updater' }, + h('div', { className: 'updater__circle' }) + ) + ) + +} + +export default Updater \ No newline at end of file diff --git a/src/ui/scripts/components/Updating.js b/src/ui/scripts/components/Updating.js new file mode 100644 index 00000000..fab0796b --- /dev/null +++ b/src/ui/scripts/components/Updating.js @@ -0,0 +1,16 @@ +import { createElement as h } from 'react' + +import Updater from './Updater' + +const Updating = () => { + + return ( + h('div', { className: 'updating' }, + h(Updater, {}), + 'Updating' + ) + ) + +} + +export default Updating \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardAverageDurations.js b/src/ui/scripts/components/cards/CardAverageDurations.js deleted file mode 100644 index 62b24eb4..00000000 --- a/src/ui/scripts/components/cards/CardAverageDurations.js +++ /dev/null @@ -1,57 +0,0 @@ -import { createElement as h, useState } from 'react' -import PropTypes from 'prop-types' -import classNames from 'classnames' - -import relativeDays from '../../utils/relativeDays' -import formatDuration from '../../utils/formatDuration' - -import Headline from '../Headline' -import Text from '../Text' -import PresentationBarChart from '../presentations/PresentationBarChart' - -const CardViews = (props) => { - - // Index of the active element - const [ active, setActive ] = useState(0) - - const onEnter = (index) => setActive(index) - const onLeave = () => setActive(0) - - const formatter = (ms) => formatDuration(ms).toString() - - return ( - h('div', { - className: classNames({ - 'card': true, - 'card--wide': props.wide === true - }) - }, - h('div', { className: 'card__inner' }, - h(Headline, { - type: 'h2', - small: true, - className: 'color-white' - }, props.headline), - h(Text, { - spacing: false - }, relativeDays(active)), - h(PresentationBarChart, { - items: props.items, - formatter, - active: active, - onEnter, - onLeave - }) - ) - ) - ) - -} - -CardViews.propTypes = { - wide: PropTypes.bool, - headline: PropTypes.string.isRequired, - items: PropTypes.array.isRequired -} - -export default CardViews \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardBrowsers.js b/src/ui/scripts/components/cards/CardBrowsers.js index 4a1525b0..088837ba 100644 --- a/src/ui/scripts/components/cards/CardBrowsers.js +++ b/src/ui/scripts/components/cards/CardBrowsers.js @@ -1,18 +1,21 @@ import { createElement as h, useState } from 'react' import PropTypes from 'prop-types' -import { BROWSERS_SORTING_TOP, BROWSERS_SORTING_RECENT } from '../../../../constants/browsers' +import { SORTINGS_TOP, SORTINGS_RECENT } from '../../../../constants/sortings' import Headline from '../Headline' import Text from '../Text' +import Updating from '../Updating' import PresentationCounterList from '../presentations/PresentationCounterList' import PresentationList from '../presentations/PresentationList' import PresentationEmptyState, { ICON_LOADING, ICON_WARNING } from '../presentations/PresentationEmptyState' import relativeDate from '../../utils/relativeDate' import rangeLabel from '../../utils/rangeLabel' +import status from '../../utils/status' -const textLabel = (item, range, isRecent) => { +const textLabel = (item, range, isRecent, isStale) => { + if (isStale === true) return h(Updating) if (item && item.date) return relativeDate(item.date) if (isRecent) return 'Recent' @@ -28,19 +31,23 @@ const CardBrowsers = (props) => { const onEnter = (index) => setActive(index) const onLeave = () => setActive() + const { + isEmpty, + isStale, + isLoading + } = status(props.items, props.loading) + const presentation = (() => { - if (props.loading === true) return h(PresentationEmptyState, { + if (isLoading === true) return h(PresentationEmptyState, { icon: ICON_LOADING }, 'Loading browsers') - const hasItems = props.items.length > 0 - - if (hasItems === true && props.sorting === BROWSERS_SORTING_TOP) return h(PresentationCounterList, { + if (isEmpty === false && props.sorting === SORTINGS_TOP) return h(PresentationCounterList, { items: props.items }) - if (hasItems === true && props.sorting === BROWSERS_SORTING_RECENT) return h(PresentationList, { + if (isEmpty === false && props.sorting === SORTINGS_RECENT) return h(PresentationList, { items: props.items, onEnter, onLeave @@ -59,15 +66,17 @@ const CardBrowsers = (props) => { h('div', { className: 'card__inner' }, h(Headline, { type: 'h2', - small: true, - className: 'color-white' + size: 'medium', + onClick: props.onMore }, props.headline), h(Text, { + type: 'div', spacing: false }, textLabel( props.items[active], props.range, - props.sorting === BROWSERS_SORTING_RECENT + props.sorting === SORTINGS_RECENT, + isStale )), presentation ) @@ -81,7 +90,8 @@ CardBrowsers.propTypes = { range: PropTypes.string.isRequired, sorting: PropTypes.string.isRequired, loading: PropTypes.bool.isRequired, - items: PropTypes.array.isRequired + items: PropTypes.array.isRequired, + onMore: PropTypes.func } export default CardBrowsers \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardDetailedDurations.js b/src/ui/scripts/components/cards/CardDetailedDurations.js deleted file mode 100644 index c02b0f52..00000000 --- a/src/ui/scripts/components/cards/CardDetailedDurations.js +++ /dev/null @@ -1,55 +0,0 @@ -import { createElement as h } from 'react' -import PropTypes from 'prop-types' - -import Headline from '../Headline' -import Text from '../Text' -import PresentationValuesBar from '../presentations/PresentationValuesBar' -import PresentationEmptyState, { ICON_LOADING, ICON_WARNING } from '../presentations/PresentationEmptyState' - -const CardDetailedDurations = (props) => { - - const presentation = (() => { - - if (props.loading === true) return h(PresentationEmptyState, { - icon: ICON_LOADING - }, 'Loading durations') - - const hasItems = props.items.length > 0 - - if (hasItems === true) return h(PresentationValuesBar, { - items: props.items - }) - - return h(PresentationEmptyState, { - icon: ICON_WARNING - }, 'No durations') - - })() - - return ( - h('div', { - className: 'card' - }, - h('div', { className: 'card__inner' }, - h(Headline, { - type: 'h2', - small: true, - className: 'color-white' - }, props.headline), - h(Text, { - spacing: false - }, 'Last 7 days'), - presentation - ) - ) - ) - -} - -CardDetailedDurations.propTypes = { - headline: PropTypes.string.isRequired, - loading: PropTypes.bool.isRequired, - items: PropTypes.array.isRequired -} - -export default CardDetailedDurations \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardDevices.js b/src/ui/scripts/components/cards/CardDevices.js index 566a009a..d0095edb 100644 --- a/src/ui/scripts/components/cards/CardDevices.js +++ b/src/ui/scripts/components/cards/CardDevices.js @@ -1,18 +1,21 @@ import { createElement as h, useState } from 'react' import PropTypes from 'prop-types' -import { DEVICES_SORTING_TOP, DEVICES_SORTING_RECENT } from '../../../../constants/devices' +import { SORTINGS_TOP, SORTINGS_RECENT } from '../../../../constants/sortings' import Headline from '../Headline' import Text from '../Text' +import Updating from '../Updating' import PresentationCounterList from '../presentations/PresentationCounterList' import PresentationList from '../presentations/PresentationList' import PresentationEmptyState, { ICON_LOADING, ICON_WARNING } from '../presentations/PresentationEmptyState' import relativeDate from '../../utils/relativeDate' import rangeLabel from '../../utils/rangeLabel' +import status from '../../utils/status' -const textLabel = (item, range, isRecent) => { +const textLabel = (item, range, isRecent, isStale) => { + if (isStale === true) return h(Updating) if (item && item.date) return relativeDate(item.date) if (isRecent) return 'Recent' @@ -27,19 +30,23 @@ const CardDevices = (props) => { const onEnter = (index) => setActive(index) const onLeave = () => setActive() + const { + isEmpty, + isStale, + isLoading + } = status(props.items, props.loading) + const presentation = (() => { - if (props.loading === true) return h(PresentationEmptyState, { + if (isLoading === true) return h(PresentationEmptyState, { icon: ICON_LOADING }, 'Loading devices') - const hasItems = props.items.length > 0 - - if (hasItems === true && props.sorting === DEVICES_SORTING_TOP) return h(PresentationCounterList, { + if (isEmpty === false && props.sorting === SORTINGS_TOP) return h(PresentationCounterList, { items: props.items }) - if (hasItems === true && props.sorting === DEVICES_SORTING_RECENT) return h(PresentationList, { + if (isEmpty === false && props.sorting === SORTINGS_RECENT) return h(PresentationList, { items: props.items, onEnter, onLeave @@ -58,15 +65,17 @@ const CardDevices = (props) => { h('div', { className: 'card__inner' }, h(Headline, { type: 'h2', - small: true, - className: 'color-white' + size: 'medium', + onClick: props.onMore }, props.headline), h(Text, { + type: 'div', spacing: false }, textLabel( props.items[active], props.range, - props.sorting === DEVICES_SORTING_RECENT + props.sorting === SORTINGS_RECENT, + isStale )), presentation ) @@ -80,7 +89,8 @@ CardDevices.propTypes = { range: PropTypes.string.isRequired, sorting: PropTypes.string.isRequired, loading: PropTypes.bool.isRequired, - items: PropTypes.array.isRequired + items: PropTypes.array.isRequired, + onMore: PropTypes.func } export default CardDevices \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardDurations.js b/src/ui/scripts/components/cards/CardDurations.js new file mode 100644 index 00000000..2b096094 --- /dev/null +++ b/src/ui/scripts/components/cards/CardDurations.js @@ -0,0 +1,92 @@ +import { createElement as h, useState } from 'react' +import PropTypes from 'prop-types' +import classNames from 'classnames' + +import { INTERVALS_DAILY, INTERVALS_MONTHLY, INTERVALS_YEARLY } from '../../../../constants/intervals' + +import Headline from '../Headline' +import Text from '../Text' +import Updating from '../Updating' +import PresentationBarChart from '../presentations/PresentationBarChart' +import relativeDays from '../../utils/relativeDays' +import relativeMonths from '../../utils/relativeMonths' +import relativeYears from '../../utils/relativeYears' +import formatDuration from '../../utils/formatDuration' +import status from '../../utils/status' + +const formatter = (ms) => formatDuration(ms).toString() + +const relativeFn = (interval) => { + + switch (interval) { + case INTERVALS_DAILY: return relativeDays + case INTERVALS_MONTHLY: return relativeMonths + case INTERVALS_YEARLY: return relativeYears + } + +} + +const textLabel = (active, interval, isStale) => { + + if (isStale === true) return h(Updating) + + return relativeFn(interval)(active) + +} + +const CardDurations = (props) => { + + // Index of the active element + const [ active, setActive ] = useState(0) + + const onEnter = (index) => setActive(index) + const onLeave = () => setActive(0) + + const { + isStale + } = status(props.items, props.loading) + + return ( + h('div', { + className: classNames({ + 'card': true, + 'card--wide': props.wide === true + }) + }, + h('div', { className: 'card__inner' }, + h(Headline, { + type: 'h2', + size: 'medium', + onClick: props.onMore + }, props.headline), + h(Text, { + type: 'div', + spacing: false + }, textLabel( + active, + props.interval, + isStale + )), + h(PresentationBarChart, { + items: props.items, + formatter, + active: active, + onEnter, + onLeave + }) + ) + ) + ) + +} + +CardDurations.propTypes = { + wide: PropTypes.bool, + headline: PropTypes.string.isRequired, + interval: PropTypes.string.isRequired, + loading: PropTypes.bool.isRequired, + items: PropTypes.array.isRequired, + onMore: PropTypes.func +} + +export default CardDurations \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardFacts.js b/src/ui/scripts/components/cards/CardFacts.js new file mode 100644 index 00000000..fd8662d9 --- /dev/null +++ b/src/ui/scripts/components/cards/CardFacts.js @@ -0,0 +1,81 @@ +import { createElement as h } from 'react' +import PropTypes from 'prop-types' + +import formatDuration from '../../utils/formatDuration' +import formatNumber from '../../utils/formatNumber' +import pluralize from '../../utils/pluralize' + +import Headline from '../Headline' +import PresentationValueText from '../presentations/PresentationValueText' + +const Presentation = (props) => { + + return ( + h('div', { className: 'facts__card' }, + h(Headline, { + type: 'h2', + size: 'small' + }, props.headline), + h(PresentationValueText, { + value: props.value, + text: props.text + }) + ) + ) + +} + +const CardFacts = (props) => { + + return ( + h('div', { + className: 'facts' + }, + h(Presentation, { + headline: 'Active visitors', + value: props.items.activeVisitors, + text: pluralize([ 'visitors', 'visitor', 'visitors' ], props.items.activeVisitors) + }), + h(Presentation, { + headline: 'Average views', + value: formatNumber(props.items.averageViews), + text: 'per day' + }), + h(Presentation, { + headline: 'Average duration', + value: formatDuration(props.items.averageDuration).value, + text: formatDuration(props.items.averageDuration).unit + }), + h(Presentation, { + headline: 'Views today', + value: formatNumber(props.items.viewsToday), + text: pluralize([ 'views', 'view', 'views' ], props.items.viewsToday) + }), + h(Presentation, { + headline: 'Views this month', + value: formatNumber(props.items.viewsMonth), + text: pluralize([ 'views', 'view', 'views' ], props.items.viewsMonth) + }), + h(Presentation, { + headline: 'Views this year', + value: formatNumber(props.items.viewsYear), + text: pluralize([ 'views', 'view', 'views' ], props.items.viewsYear) + }) + ) + ) + +} + +CardFacts.propTypes = { + loading: PropTypes.bool.isRequired, + items: PropTypes.exact({ + activeVisitors: PropTypes.number.isRequired, + averageViews: PropTypes.number.isRequired, + averageDuration: PropTypes.number.isRequired, + viewsToday: PropTypes.number.isRequired, + viewsMonth: PropTypes.number.isRequired, + viewsYear: PropTypes.number.isRequired + }).isRequired +} + +export default CardFacts \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardLanguages.js b/src/ui/scripts/components/cards/CardLanguages.js index b33a1750..5534f2c5 100644 --- a/src/ui/scripts/components/cards/CardLanguages.js +++ b/src/ui/scripts/components/cards/CardLanguages.js @@ -1,18 +1,21 @@ import { createElement as h, useState } from 'react' import PropTypes from 'prop-types' -import { LANGUAGES_SORTING_TOP, LANGUAGES_SORTING_RECENT } from '../../../../constants/languages' +import { SORTINGS_TOP, SORTINGS_RECENT } from '../../../../constants/sortings' import Headline from '../Headline' import Text from '../Text' +import Updating from '../Updating' import PresentationCounterList from '../presentations/PresentationCounterList' import PresentationList from '../presentations/PresentationList' import PresentationEmptyState, { ICON_LOADING, ICON_WARNING } from '../presentations/PresentationEmptyState' import relativeDate from '../../utils/relativeDate' import rangeLabel from '../../utils/rangeLabel' +import status from '../../utils/status' -const textLabel = (item, range, isRecent) => { +const textLabel = (item, range, isRecent, isStale) => { + if (isStale === true) return h(Updating) if (item && item.date) return relativeDate(item.date) if (isRecent) return 'Recent' @@ -28,19 +31,23 @@ const CardLanguages = (props) => { const onEnter = (index) => setActive(index) const onLeave = () => setActive() + const { + isEmpty, + isStale, + isLoading + } = status(props.items, props.loading) + const presentation = (() => { - if (props.loading === true) return h(PresentationEmptyState, { + if (isLoading === true) return h(PresentationEmptyState, { icon: ICON_LOADING }, 'Loading languages') - const hasItems = props.items.length > 0 - - if (hasItems === true && props.sorting === LANGUAGES_SORTING_TOP) return h(PresentationCounterList, { + if (isEmpty === false && props.sorting === SORTINGS_TOP) return h(PresentationCounterList, { items: props.items }) - if (hasItems === true && props.sorting === LANGUAGES_SORTING_RECENT) return h(PresentationList, { + if (isEmpty === false && props.sorting === SORTINGS_RECENT) return h(PresentationList, { items: props.items, onEnter, onLeave @@ -59,15 +66,17 @@ const CardLanguages = (props) => { h('div', { className: 'card__inner' }, h(Headline, { type: 'h2', - small: true, - className: 'color-white' + size: 'medium', + onClick: props.onMore }, props.headline), h(Text, { + type: 'div', spacing: false }, textLabel( props.items[active], props.range, - props.sorting === LANGUAGES_SORTING_RECENT + props.sorting === SORTINGS_RECENT, + isStale )), presentation ) @@ -81,7 +90,8 @@ CardLanguages.propTypes = { range: PropTypes.string.isRequired, sorting: PropTypes.string.isRequired, loading: PropTypes.bool.isRequired, - items: PropTypes.array.isRequired + items: PropTypes.array.isRequired, + onMore: PropTypes.func } export default CardLanguages \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardPages.js b/src/ui/scripts/components/cards/CardPages.js index 475cd3ed..5b665da4 100644 --- a/src/ui/scripts/components/cards/CardPages.js +++ b/src/ui/scripts/components/cards/CardPages.js @@ -1,18 +1,21 @@ import { createElement as h, useState } from 'react' import PropTypes from 'prop-types' -import { PAGES_SORTING_TOP, PAGES_SORTING_RECENT } from '../../../../constants/pages' +import { SORTINGS_TOP, SORTINGS_RECENT } from '../../../../constants/sortings' import Headline from '../Headline' import Text from '../Text' +import Updating from '../Updating' import PresentationCounterList from '../presentations/PresentationCounterList' import PresentationList from '../presentations/PresentationList' import PresentationEmptyState, { ICON_LOADING, ICON_WARNING } from '../presentations/PresentationEmptyState' import relativeDate from '../../utils/relativeDate' import rangeLabel from '../../utils/rangeLabel' +import status from '../../utils/status' -const textLabel = (item, range, isRecent) => { +const textLabel = (item, range, isRecent, isStale) => { + if (isStale === true) return h(Updating) if (item && item.date) return relativeDate(item.date) if (isRecent) return 'Recent' @@ -28,19 +31,23 @@ const CardPages = (props) => { const onEnter = (index) => setActive(index) const onLeave = () => setActive() + const { + isEmpty, + isStale, + isLoading + } = status(props.items, props.loading) + const presentation = (() => { - if (props.loading === true) return h(PresentationEmptyState, { + if (isLoading === true) return h(PresentationEmptyState, { icon: ICON_LOADING }, 'Loading pages') - const hasItems = props.items.length > 0 - - if (hasItems === true && props.sorting === PAGES_SORTING_TOP) return h(PresentationCounterList, { + if (isEmpty === false && props.sorting === SORTINGS_TOP) return h(PresentationCounterList, { items: props.items }) - if (hasItems === true && props.sorting === PAGES_SORTING_RECENT) return h(PresentationList, { + if (isEmpty === false && props.sorting === SORTINGS_RECENT) return h(PresentationList, { items: props.items, onEnter, onLeave @@ -59,15 +66,17 @@ const CardPages = (props) => { h('div', { className: 'card__inner' }, h(Headline, { type: 'h2', - small: true, - className: 'color-white' + size: 'medium', + onClick: props.onMore }, props.headline), h(Text, { + type: 'div', spacing: false }, textLabel( props.items[active], props.range, - props.sorting === PAGES_SORTING_RECENT + props.sorting === SORTINGS_RECENT, + isStale )), presentation ) @@ -81,7 +90,8 @@ CardPages.propTypes = { range: PropTypes.string.isRequired, sorting: PropTypes.string.isRequired, loading: PropTypes.bool.isRequired, - items: PropTypes.array.isRequired + items: PropTypes.array.isRequired, + onMore: PropTypes.func } export default CardPages \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardReferrers.js b/src/ui/scripts/components/cards/CardReferrers.js index 1749751f..945dbd9e 100644 --- a/src/ui/scripts/components/cards/CardReferrers.js +++ b/src/ui/scripts/components/cards/CardReferrers.js @@ -1,16 +1,20 @@ import { createElement as h, useState } from 'react' import PropTypes from 'prop-types' -import { REFERRERS_SORTING_NEW, REFERRERS_SORTING_RECENT } from '../../../../constants/referrers' +import { SORTINGS_NEW, SORTINGS_RECENT } from '../../../../constants/sortings' import Headline from '../Headline' import Text from '../Text' +import Updating from '../Updating' import PresentationIconList from '../presentations/PresentationIconList' import PresentationEmptyState, { ICON_LOADING, ICON_WARNING } from '../presentations/PresentationEmptyState' import relativeDate from '../../utils/relativeDate' import rangeLabel from '../../utils/rangeLabel' +import status from '../../utils/status' -const textLabel = (item, range, isRecent, isNew) => { +const textLabel = (item, range, isRecent, isNew, isStale) => { + + if (isStale === true) return h(Updating) if (item && item.date) return relativeDate(item.date) if (item && item.count) return `${ item.count } ${ item.count === 1 ? 'visit' : 'visits' }` @@ -30,15 +34,19 @@ const CardReferrers = (props) => { const onEnter = (index) => setActive(index) const onLeave = () => setActive() + const { + isEmpty, + isStale, + isLoading + } = status(props.items, props.loading) + const presentation = (() => { - if (props.loading === true) return h(PresentationEmptyState, { + if (isLoading === true) return h(PresentationEmptyState, { icon: ICON_LOADING }, 'Loading referrers') - const hasItems = props.items.length > 0 - - if (hasItems === true) return h(PresentationIconList, { + if (isEmpty === false) return h(PresentationIconList, { items: props.items, onEnter, onLeave @@ -57,16 +65,18 @@ const CardReferrers = (props) => { h('div', { className: 'card__inner' }, h(Headline, { type: 'h2', - small: true, - className: 'color-white' + size: 'medium', + onClick: props.onMore }, props.headline), h(Text, { + type: 'div', spacing: false }, textLabel( props.items[active], props.range, - props.sorting === REFERRERS_SORTING_RECENT, - props.sorting === REFERRERS_SORTING_NEW + props.sorting === SORTINGS_RECENT, + props.sorting === SORTINGS_NEW, + isStale )), presentation ) @@ -79,7 +89,8 @@ CardReferrers.propTypes = { headline: PropTypes.string.isRequired, range: PropTypes.string.isRequired, loading: PropTypes.bool.isRequired, - items: PropTypes.array.isRequired + items: PropTypes.array.isRequired, + onMore: PropTypes.func } export default CardReferrers \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardSetting.js b/src/ui/scripts/components/cards/CardSetting.js index f20e9015..d9dbf02a 100644 --- a/src/ui/scripts/components/cards/CardSetting.js +++ b/src/ui/scripts/components/cards/CardSetting.js @@ -12,8 +12,7 @@ const CardSetting = (props) => { h(Headline, { type: 'h2', - small: true, - className: 'color-white' + size: 'medium' }, props.headline), h(Spacer, { size: 1.6 }), diff --git a/src/ui/scripts/components/cards/CardSizes.js b/src/ui/scripts/components/cards/CardSizes.js index a5581d55..89454e5b 100644 --- a/src/ui/scripts/components/cards/CardSizes.js +++ b/src/ui/scripts/components/cards/CardSizes.js @@ -1,13 +1,23 @@ -import { createElement as h } from 'react' +import { createElement as h, useState } from 'react' import PropTypes from 'prop-types' +import { SORTINGS_TOP, SORTINGS_RECENT } from '../../../../constants/sortings' + import Headline from '../Headline' import Text from '../Text' +import Updating from '../Updating' import PresentationCounterList from '../presentations/PresentationCounterList' +import PresentationList from '../presentations/PresentationList' import PresentationEmptyState, { ICON_LOADING, ICON_WARNING } from '../presentations/PresentationEmptyState' +import relativeDate from '../../utils/relativeDate' import rangeLabel from '../../utils/rangeLabel' +import status from '../../utils/status' + +const textLabel = (item, range, isRecent, isStale) => { -const textLabel = (range) => { + if (isStale === true) return h(Updating) + if (item && item.date) return relativeDate(item.date) + if (isRecent) return 'Recent' return rangeLabel(range) @@ -15,18 +25,34 @@ const textLabel = (range) => { const CardSizes = (props) => { + // Index of the active element + const [ active, setActive ] = useState() + + const onEnter = (index) => setActive(index) + const onLeave = () => setActive() + + const { + isEmpty, + isStale, + isLoading + } = status(props.items, props.loading) + const presentation = (() => { - if (props.loading === true) return h(PresentationEmptyState, { + if (isLoading === true) return h(PresentationEmptyState, { icon: ICON_LOADING }, 'Loading sizes') - const hasItems = props.items.length > 0 - - if (hasItems === true) return h(PresentationCounterList, { + if (isEmpty === false && props.sorting === SORTINGS_TOP) return h(PresentationCounterList, { items: props.items }) + if (isEmpty === false && props.sorting === SORTINGS_RECENT) return h(PresentationList, { + items: props.items, + onEnter, + onLeave + }) + return h(PresentationEmptyState, { icon: ICON_WARNING }, 'No sizes') @@ -40,12 +66,18 @@ const CardSizes = (props) => { h('div', { className: 'card__inner' }, h(Headline, { type: 'h2', - small: true, - className: 'color-white' + size: 'medium', + onClick: props.onMore }, props.headline), h(Text, { + type: 'div', spacing: false - }, textLabel(props.range)), + }, textLabel( + props.items[active], + props.range, + props.sorting === SORTINGS_RECENT, + isStale + )), presentation ) ) @@ -56,8 +88,10 @@ const CardSizes = (props) => { CardSizes.propTypes = { headline: PropTypes.string.isRequired, range: PropTypes.string.isRequired, + sorting: PropTypes.string.isRequired, loading: PropTypes.bool.isRequired, - items: PropTypes.array.isRequired + items: PropTypes.array.isRequired, + onMore: PropTypes.func } export default CardSizes \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardSystems.js b/src/ui/scripts/components/cards/CardSystems.js index 7904286d..32c74908 100644 --- a/src/ui/scripts/components/cards/CardSystems.js +++ b/src/ui/scripts/components/cards/CardSystems.js @@ -1,18 +1,21 @@ import { createElement as h, useState } from 'react' import PropTypes from 'prop-types' -import { SYSTEMS_SORTING_TOP, SYSTEMS_SORTING_RECENT } from '../../../../constants/systems' +import { SORTINGS_TOP, SORTINGS_RECENT } from '../../../../constants/sortings' import Headline from '../Headline' import Text from '../Text' +import Updating from '../Updating' import PresentationCounterList from '../presentations/PresentationCounterList' import PresentationList from '../presentations/PresentationList' import PresentationEmptyState, { ICON_LOADING, ICON_WARNING } from '../presentations/PresentationEmptyState' import relativeDate from '../../utils/relativeDate' import rangeLabel from '../../utils/rangeLabel' +import status from '../../utils/status' -const textLabel = (item, range, isRecent) => { +const textLabel = (item, range, isRecent, isStale) => { + if (isStale === true) return h(Updating) if (item && item.date) return relativeDate(item.date) if (isRecent) return 'Recent' @@ -28,19 +31,23 @@ const CardSystems = (props) => { const onEnter = (index) => setActive(index) const onLeave = () => setActive() + const { + isEmpty, + isStale, + isLoading + } = status(props.items, props.loading) + const presentation = (() => { - if (props.loading === true) return h(PresentationEmptyState, { + if (isLoading === true) return h(PresentationEmptyState, { icon: ICON_LOADING }, 'Loading systems') - const hasItems = props.items.length > 0 - - if (hasItems === true && props.sorting === SYSTEMS_SORTING_TOP) return h(PresentationCounterList, { + if (isEmpty === false && props.sorting === SORTINGS_TOP) return h(PresentationCounterList, { items: props.items }) - if (hasItems === true && props.sorting === SYSTEMS_SORTING_RECENT) return h(PresentationList, { + if (isEmpty === false && props.sorting === SORTINGS_RECENT) return h(PresentationList, { items: props.items, onEnter, onLeave @@ -59,15 +66,17 @@ const CardSystems = (props) => { h('div', { className: 'card__inner' }, h(Headline, { type: 'h2', - small: true, - className: 'color-white' + size: 'medium', + onClick: props.onMore }, props.headline), h(Text, { + type: 'div', spacing: false }, textLabel( props.items[active], props.range, - props.sorting === SYSTEMS_SORTING_RECENT + props.sorting === SORTINGS_RECENT, + isStale )), presentation ) @@ -81,7 +90,8 @@ CardSystems.propTypes = { range: PropTypes.string.isRequired, sorting: PropTypes.string.isRequired, loading: PropTypes.bool.isRequired, - items: PropTypes.array.isRequired + items: PropTypes.array.isRequired, + onMore: PropTypes.func } export default CardSystems \ No newline at end of file diff --git a/src/ui/scripts/components/cards/CardViews.js b/src/ui/scripts/components/cards/CardViews.js index ee81dd2d..c8935824 100644 --- a/src/ui/scripts/components/cards/CardViews.js +++ b/src/ui/scripts/components/cards/CardViews.js @@ -2,26 +2,36 @@ import { createElement as h, useState } from 'react' import PropTypes from 'prop-types' import classNames from 'classnames' -import { VIEWS_INTERVAL_DAILY, VIEWS_INTERVAL_MONTHLY, VIEWS_INTERVAL_YEARLY } from '../../../../constants/views' - -import relativeDays from '../../utils/relativeDays' -import relativeMonths from '../../utils/relativeMonths' -import relativeYears from '../../utils/relativeYears' +import { INTERVALS_DAILY, INTERVALS_MONTHLY, INTERVALS_YEARLY } from '../../../../constants/intervals' import Headline from '../Headline' import Text from '../Text' +import Updating from '../Updating' import PresentationBarChart from '../presentations/PresentationBarChart' +import relativeDays from '../../utils/relativeDays' +import relativeMonths from '../../utils/relativeMonths' +import relativeYears from '../../utils/relativeYears' +import formatNumber from '../../utils/formatNumber' +import status from '../../utils/status' const relativeFn = (interval) => { switch (interval) { - case VIEWS_INTERVAL_DAILY: return relativeDays - case VIEWS_INTERVAL_MONTHLY: return relativeMonths - case VIEWS_INTERVAL_YEARLY: return relativeYears + case INTERVALS_DAILY: return relativeDays + case INTERVALS_MONTHLY: return relativeMonths + case INTERVALS_YEARLY: return relativeYears } } +const textLabel = (active, interval, isStale) => { + + if (isStale === true) return h(Updating) + + return relativeFn(interval)(active) + +} + const CardViews = (props) => { // Index of the active element @@ -30,6 +40,10 @@ const CardViews = (props) => { const onEnter = (index) => setActive(index) const onLeave = () => setActive(0) + const { + isStale + } = status(props.items, props.loading) + return ( h('div', { className: classNames({ @@ -40,14 +54,20 @@ const CardViews = (props) => { h('div', { className: 'card__inner' }, h(Headline, { type: 'h2', - small: true, - className: 'color-white' + size: 'medium', + onClick: props.onMore }, props.headline), h(Text, { + type: 'div', spacing: false - }, relativeFn(props.interval)(active)), + }, textLabel( + active, + props.interval, + isStale + )), h(PresentationBarChart, { items: props.items, + formatter: formatNumber, active: active, onEnter, onLeave @@ -62,7 +82,9 @@ CardViews.propTypes = { wide: PropTypes.bool, headline: PropTypes.string.isRequired, interval: PropTypes.string.isRequired, - items: PropTypes.array.isRequired + loading: PropTypes.bool.isRequired, + items: PropTypes.array.isRequired, + onMore: PropTypes.func } export default CardViews \ No newline at end of file diff --git a/src/ui/scripts/components/modals/ModalDomainAdd.js b/src/ui/scripts/components/modals/ModalDomainAdd.js index bdf8b746..d85c9f4b 100644 --- a/src/ui/scripts/components/modals/ModalDomainAdd.js +++ b/src/ui/scripts/components/modals/ModalDomainAdd.js @@ -1,6 +1,7 @@ import { createElement as h, useState } from 'react' import PropTypes from 'prop-types' import shortid from 'shortid' +// import { useHotkeys } from 'react-hotkeys-hook' import Input from '../Input' import Label from '../Label' @@ -9,6 +10,12 @@ import Spacer from '../Spacer' const ModalDomainAdd = (props) => { + // Currently not possible: + // https://github.com/JohannesKlauss/react-hotkeys-hook/issues/276 + // useHotkeys('esc', props.closeModal, { + // filter: () => props.current === true + // }) + const [ inputs, setInputs ] = useState({ title: '' }) @@ -54,7 +61,7 @@ const ModalDomainAdd = (props) => { }, 'Close'), h('div', { - className: 'card__separator' + className: 'card__separator ' }), h('button', { @@ -69,6 +76,7 @@ const ModalDomainAdd = (props) => { } ModalDomainAdd.propTypes = { + current: PropTypes.bool.isRequired, fetching: PropTypes.bool.isRequired, addDomain: PropTypes.func.isRequired, closeModal: PropTypes.func.isRequired diff --git a/src/ui/scripts/components/modals/ModalDomainEdit.js b/src/ui/scripts/components/modals/ModalDomainEdit.js index 16edfb7a..4429a941 100644 --- a/src/ui/scripts/components/modals/ModalDomainEdit.js +++ b/src/ui/scripts/components/modals/ModalDomainEdit.js @@ -1,6 +1,7 @@ import { createElement as h, useState } from 'react' import PropTypes from 'prop-types' import shortid from 'shortid' +// import { useHotkeys } from 'react-hotkeys-hook' import customTrackerUrl from '../../../../utils/customTrackerUrl' @@ -12,6 +13,12 @@ import Spacer from '../Spacer' const ModalDomainEdit = (props) => { + // Currently not possible: + // https://github.com/JohannesKlauss/react-hotkeys-hook/issues/276 + // useHotkeys('esc', props.closeModal, { + // filter: () => props.current === true + // }) + const [ inputs, setInputs ] = useState({ title: props.title }) @@ -96,7 +103,7 @@ const ModalDomainEdit = (props) => { }, 'Close'), h('div', { - className: 'card__separator' + className: 'card__separator ' }), h('button', { @@ -106,7 +113,7 @@ const ModalDomainEdit = (props) => { }, 'Delete'), h('div', { - className: 'card__separator' + className: 'card__separator ' }), h('button', { @@ -121,6 +128,7 @@ const ModalDomainEdit = (props) => { } ModalDomainEdit.propTypes = { + current: PropTypes.bool.isRequired, id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, fetching: PropTypes.bool.isRequired, diff --git a/src/ui/scripts/components/overlays/OverlayFailure.js b/src/ui/scripts/components/overlays/OverlayFailure.js index c2eb59b1..f08f5bff 100644 --- a/src/ui/scripts/components/overlays/OverlayFailure.js +++ b/src/ui/scripts/components/overlays/OverlayFailure.js @@ -25,10 +25,11 @@ const OverlayFailure = (props) => { h(Spacer, { size: 2.4 }), h(Headline, { - type: 'h1', - className: 'color-white' + type: 'h1' }, 'Oops'), - h(Text, {}, 'Something went wrong.'), + h(Text, { + type: 'p' + }, 'Something went wrong.'), h(Spacer, { size: 2.5 }), @@ -53,7 +54,7 @@ const OverlayFailure = (props) => { }, 'Help'), h('div', { - className: 'card__separator' + className: 'card__separator ' }), h('button', { diff --git a/src/ui/scripts/components/overlays/OverlayLogin.js b/src/ui/scripts/components/overlays/OverlayLogin.js index df86b9bb..f8dd838f 100644 --- a/src/ui/scripts/components/overlays/OverlayLogin.js +++ b/src/ui/scripts/components/overlays/OverlayLogin.js @@ -2,7 +2,7 @@ import { createElement as h, useState } from 'react' import PropTypes from 'prop-types' import { homepage } from '../../../../../package' -import isDemo from '../../../../utils/isDemo' +import isDemoMode from '../../../../utils/isDemoMode' import Input from '../Input' import Spacer from '../Spacer' @@ -14,8 +14,8 @@ import Message from '../Message' const OverlayLogin = (props) => { const [ inputs, setInputs ] = useState({ - username: isDemo === true ? 'admin' : '', - password: isDemo === true ? '123456' : '' + username: isDemoMode === true ? 'admin' : '', + password: isDemoMode === true ? '123456' : '' }) const onChange = (key) => (e) => setInputs({ @@ -38,10 +38,11 @@ const OverlayLogin = (props) => { h(Spacer, { size: 2.4 }), h(Headline, { - type: 'h1', - className: 'color-white' + type: 'h1' }, 'Ackee'), - h(Text, {}, 'Welcome back, sign in to continue.'), + h(Text, { + type: 'p' + }, 'Welcome back, sign in to continue.'), h(Spacer, { size: 2.5 }), @@ -78,7 +79,7 @@ const OverlayLogin = (props) => { }, 'Help'), h('div', { - className: 'card__separator' + className: 'card__separator ' }), h('button', { diff --git a/src/ui/scripts/components/presentations/PresentationBarChart.js b/src/ui/scripts/components/presentations/PresentationBarChart.js index cf87939f..48cbe819 100644 --- a/src/ui/scripts/components/presentations/PresentationBarChart.js +++ b/src/ui/scripts/components/presentations/PresentationBarChart.js @@ -9,7 +9,10 @@ const max = (items) => round(Math.max.apply(Math, items)) const mid = (items) => max(items) / 2 const min = () => 0 -const percentage = (amount, max) => (amount / max) * 100 +const percentage = (amount, max) => { + if (amount === 0 && max === 0) return 0 + return (amount / max) * 100 +} const Row = (props) => { @@ -50,17 +53,14 @@ const Column = (props) => { const PresentationBarChart = (props) => { - const defaultFormatter = (_) => _ - const hasItems = props.items.length > 0 - const formatter = props.formatter || defaultFormatter return ( h('div', { className: 'barChart' }, h('div', { className: 'barChart__axis' }, - h(Row, { position: 'top' }, hasItems === true ? formatter(max(props.items)) : ''), - h(Row, { position: 'middle' }, hasItems === true ? formatter(mid(props.items)) : ''), - h(Row, { position: 'bottom' }, hasItems === true ? formatter(min()) : '') + h(Row, { position: 'top' }, hasItems === true ? props.formatter(max(props.items)) : ''), + h(Row, { position: 'middle' }, hasItems === true ? props.formatter(mid(props.items)) : ''), + h(Row, { position: 'bottom' }, hasItems === true ? props.formatter(min()) : '') ), h('div', { className: 'barChart__columns' }, props.items.map((item, index) => ( @@ -70,7 +70,7 @@ const PresentationBarChart = (props) => { size: `${ percentage(item, max(props.items)) }%`, onEnter: () => props.onEnter(index), onLeave: () => props.onLeave(index), - label: formatter(item) + label: props.formatter(item) }) )) ) @@ -81,7 +81,7 @@ const PresentationBarChart = (props) => { PresentationBarChart.propTypes = { items: PropTypes.arrayOf(PropTypes.number).isRequired, - formatter: PropTypes.func, + formatter: PropTypes.func.isRequired, onEnter: PropTypes.func.isRequired, onLeave: PropTypes.func.isRequired } diff --git a/src/ui/scripts/components/presentations/PresentationValueText.js b/src/ui/scripts/components/presentations/PresentationValueText.js new file mode 100644 index 00000000..5ad05094 --- /dev/null +++ b/src/ui/scripts/components/presentations/PresentationValueText.js @@ -0,0 +1,34 @@ +import { createElement as h } from 'react' +import PropTypes from 'prop-types' + +import Headline from '../Headline' +import Text from '../Text' + +const PresentationValueText = (props) => { + + return ( + h('div', { + className: 'valueText' + }, + h(Headline, { + type: 'div', + spacing: false + }, props.value), + h(Text, { + type: 'div', + spacing: false + }, props.text) + ) + ) + +} + +PresentationValueText.propTypes = { + value: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string + ]).isRequired, + text: PropTypes.string.isRequired +} + +export default PresentationValueText \ No newline at end of file diff --git a/src/ui/scripts/components/presentations/PresentationValuesBar.js b/src/ui/scripts/components/presentations/PresentationValuesBar.js deleted file mode 100644 index e7622024..00000000 --- a/src/ui/scripts/components/presentations/PresentationValuesBar.js +++ /dev/null @@ -1,153 +0,0 @@ -import { createElement as h, useState } from 'react' -import PropTypes from 'prop-types' - -import { - DURATIONS_INTERVAL, - DURATIONS_LIMIT -} from '../../../../constants/durations' - -import minByProp from '../../utils/minByProp' -import maxByProp from '../../utils/maxByProp' -import formatDuration from '../../utils/formatDuration' - -const Value = (props) => { - - return ( - h('div', { - className: 'valuesBar__value', - style: { '--opacity': props.opacity }, - onMouseEnter: props.onEnter, - onMouseLeave: props.onLeave - }) - ) - -} - -const Content = (props) => { - - const hasDecorator = props.decorator != null - - return ( - h('div', { className: 'valuesBar__content' }, - h('p', { className: `valuesBar__duration color-${ props.color }` }, - hasDecorator === true && h('span', { className: 'valuesBar__decorator' }, props.decorator), - props.duration.value, - h('span', { className: 'valuesBar__unit' }, props.duration.unit) - ), - h('p', { className: 'valuesBar__description' }, props.description) - ) - ) - -} - -const PresentationValuesBar = (props) => { - - // Index of the active element - const [ active, setActive ] = useState() - - const onEnter = (index) => setActive(index) - const onLeave = () => setActive() - - const averageDuration = props.items[0].average - - const belowLimitItems = props.items.filter(({ duration }) => duration < DURATIONS_LIMIT) - const aboveLimitItems = props.items.filter(({ duration }) => duration >= DURATIONS_LIMIT) - - const minDuration = belowLimitItems.reduce(minByProp('duration'), Number.MAX_SAFE_INTEGER) - const maxDuration = belowLimitItems.reduce(maxByProp('duration'), 0) - - const maxCount = props.items.reduce(maxByProp('count'), 0) - const proportionalOpacity = ({ count }) => count / maxCount - - const content = (() => { - - const activeItem = props.items[active] - - if (activeItem == null) return h(Content, { - color: 'white', - duration: formatDuration(averageDuration), - description: 'Average visit duration' - }) - - const isBelowInterval = activeItem.duration < DURATIONS_INTERVAL - const isAboveLimit = activeItem.duration >= DURATIONS_LIMIT - - const decorator = (() => { - - if (isBelowInterval === true) return '<' - if (isAboveLimit === true) return '>' - - })() - - const duration = (() => { - - if (isBelowInterval === true) return formatDuration(DURATIONS_INTERVAL) - return formatDuration(activeItem.duration) - - })() - - return h(Content, { - color: 'primary', - decorator, - duration, - description: `${ activeItem.count } visits` - }) - - })() - - return ( - h('div', { className: 'valuesBar' }, - h('div', { className: 'valuesBar__row' }, - h('div', { className: 'valuesBar__bar' }, - belowLimitItems.map((item, index) => ( - h(Value, { - key: String(item.duration) + index, - opacity: proportionalOpacity(item), - onEnter: () => onEnter(index), - onLeave: () => onLeave(index), - ...item - }) - )) - ), - h('div', { className: 'valuesBar__inner' }, - h('div', { className: 'valuesBar__line' }, - h('div', { className: 'valuesBar__anchor valuesBar__anchor--bottom' }, - formatDuration(minDuration).toString() - ) - ), - content, - h('div', { className: 'valuesBar__line' }, - h('div', { className: 'valuesBar__anchor valuesBar__anchor--top' }, - formatDuration(maxDuration).toString() - ) - ) - ) - ), - h('div', { className: 'valuesBar__row' }, - h('div', { className: 'valuesBar__bar' }, - aboveLimitItems.map((item, index) => ( - h(Value, { - key: String(item.duration) + index, - opacity: proportionalOpacity(item), - onEnter: () => onEnter(belowLimitItems.length + index), - onLeave: () => onLeave(belowLimitItems.length + index), - ...item - }) - )) - ) - ) - ) - ) - -} - -PresentationValuesBar.propTypes = { - items: PropTypes.arrayOf( - PropTypes.shape({ - duration: PropTypes.number.isRequired, - count: PropTypes.number.isRequired - }) - ).isRequired -} - -export default PresentationValuesBar \ No newline at end of file diff --git a/src/ui/scripts/components/routes/RouteBrowsers.js b/src/ui/scripts/components/routes/RouteBrowsers.js index d015f574..cdac9b36 100644 --- a/src/ui/scripts/components/routes/RouteBrowsers.js +++ b/src/ui/scripts/components/routes/RouteBrowsers.js @@ -2,7 +2,7 @@ import { createElement as h, Fragment, useEffect } from 'react' import selectBrowsersValue from '../../selectors/selectBrowsersValue' import enhanceBrowsers from '../../enhancers/enhanceBrowsers' -import useDidMountEffect from '../../utils/useDidMountEffect' +import overviewRoute from '../../utils/overviewRoute' import CardBrowsers from '../cards/CardBrowsers' @@ -10,17 +10,9 @@ const RouteBrowsers = (props) => { useEffect(() => { - props.fetchDomains(props) + props.fetchBrowsers(props) - }, []) - - useDidMountEffect(() => { - - props.domains.value.map((domain) => { - props.fetchBrowsers(props, domain.data.id) - }) - - }, [ props.filter.range, props.domains.value, props.browsers.sorting, props.browsers.type ]) + }, [ props.filter.range, props.filter.sorting, props.browsers.type ]) return ( h(Fragment, {}, @@ -28,12 +20,13 @@ const RouteBrowsers = (props) => { props.domains.value.map( (domain) => ( h(CardBrowsers, { - key: domain.data.id, - headline: domain.data.title, + key: domain.id, + headline: domain.title, range: props.filter.range, - sorting: props.browsers.sorting, - loading: selectBrowsersValue(props, domain.data.id).fetching, - items: enhanceBrowsers(selectBrowsersValue(props, domain.data.id).value) + sorting: props.filter.sorting, + loading: props.browsers.fetching, + items: enhanceBrowsers(selectBrowsersValue(props, domain.id).value), + onMore: () => props.setRoute(overviewRoute(domain)) }) ) ) diff --git a/src/ui/scripts/components/routes/RouteDevices.js b/src/ui/scripts/components/routes/RouteDevices.js index 43fea9b2..080b6a47 100644 --- a/src/ui/scripts/components/routes/RouteDevices.js +++ b/src/ui/scripts/components/routes/RouteDevices.js @@ -2,7 +2,7 @@ import { createElement as h, Fragment, useEffect } from 'react' import selectDevicesValue from '../../selectors/selectDevicesValue' import enhanceDevices from '../../enhancers/enhanceDevices' -import useDidMountEffect from '../../utils/useDidMountEffect' +import overviewRoute from '../../utils/overviewRoute' import CardDevices from '../cards/CardDevices' @@ -10,17 +10,9 @@ const RouteDevices = (props) => { useEffect(() => { - props.fetchDomains(props) + props.fetchDevices(props) - }, []) - - useDidMountEffect(() => { - - props.domains.value.map((domain) => { - props.fetchDevices(props, domain.data.id) - }) - - }, [ props.filter.range, props.domains.value, props.devices.sorting, props.devices.type ]) + }, [ props.filter.range, props.filter.sorting, props.devices.type ]) return ( h(Fragment, {}, @@ -28,12 +20,13 @@ const RouteDevices = (props) => { props.domains.value.map( (domain) => ( h(CardDevices, { - key: domain.data.id, - headline: domain.data.title, + key: domain.id, + headline: domain.title, range: props.filter.range, - sorting: props.devices.sorting, - loading: selectDevicesValue(props, domain.data.id).fetching, - items: enhanceDevices(selectDevicesValue(props, domain.data.id).value) + sorting: props.filter.sorting, + loading: props.devices.fetching, + items: enhanceDevices(selectDevicesValue(props, domain.id).value), + onMore: () => props.setRoute(overviewRoute(domain)) }) ) ) diff --git a/src/ui/scripts/components/routes/RouteDurations.js b/src/ui/scripts/components/routes/RouteDurations.js index 7d246b0f..a703ab00 100644 --- a/src/ui/scripts/components/routes/RouteDurations.js +++ b/src/ui/scripts/components/routes/RouteDurations.js @@ -1,67 +1,45 @@ import { createElement as h, Fragment, useEffect } from 'react' -import { DURATIONS_TYPE_AVERAGE, DURATIONS_TYPE_DETAILED } from '../../../../constants/durations' - import selectDurationsValue from '../../selectors/selectDurationsValue' -import enhanceAverageDurations from '../../enhancers/enhanceAverageDurations' -import enhanceDetailedDurations from '../../enhancers/enhanceDetailedDurations' -import mergeAverageDurations from '../../utils/mergeAverageDurations' -import useDidMountEffect from '../../utils/useDidMountEffect' +import enhanceDurations from '../../enhancers/enhanceDurations' +import mergeDurations from '../../utils/mergeDurations' +import overviewRoute from '../../utils/overviewRoute' -import CardAverageDurations from '../cards/CardAverageDurations' -import CardDetailedDurations from '../cards/CardDetailedDurations' +import CardDurations from '../cards/CardDurations' const RouteDurations = (props) => { useEffect(() => { - props.fetchDomains(props) - - }, []) - - useDidMountEffect(() => { - - props.domains.value.map((domain) => { - props.fetchDurations(props, domain.data.id) - }) - - }, [ props.domains.value, props.durations.type ]) + props.fetchDurations(props) - const type = props.durations.type + }, [ props.filter.interval ]) - if (type === DURATIONS_TYPE_AVERAGE) return ( + return ( h(Fragment, {}, - h(CardAverageDurations, { + h(CardDurations, { wide: true, - headline: 'Average Durations', - items: mergeAverageDurations(props) + headline: 'Durations', + interval: props.filter.interval, + loading: props.fetching, + items: mergeDurations(props) }), props.domains.value.map( (domain) => ( - h(CardAverageDurations, { - key: domain.data.id, - headline: domain.data.title, - items: enhanceAverageDurations(selectDurationsValue(props, domain.data.id).value, 7) + h(CardDurations, { + key: domain.id, + headline: domain.title, + interval: props.filter.interval, + loading: props.durations.fetching, + items: enhanceDurations(selectDurationsValue(props, domain.id).value, 7), + onMore: () => props.setRoute(overviewRoute(domain)) }) ) ) ) ) - if (type === DURATIONS_TYPE_DETAILED) return ( - props.domains.value.map( - (domain) => ( - h(CardDetailedDurations, { - key: domain.data.id, - headline: domain.data.title, - loading: selectDurationsValue(props, domain.data.id).fetching, - items: enhanceDetailedDurations(selectDurationsValue(props, domain.data.id).value) - }) - ) - ) - ) - } export default RouteDurations \ No newline at end of file diff --git a/src/ui/scripts/components/routes/RouteLanguages.js b/src/ui/scripts/components/routes/RouteLanguages.js index 383b9e06..aceda7a7 100644 --- a/src/ui/scripts/components/routes/RouteLanguages.js +++ b/src/ui/scripts/components/routes/RouteLanguages.js @@ -2,7 +2,7 @@ import { createElement as h, Fragment, useEffect } from 'react' import selectLanguagesValue from '../../selectors/selectLanguagesValue' import enhanceLanguages from '../../enhancers/enhanceLanguages' -import useDidMountEffect from '../../utils/useDidMountEffect' +import overviewRoute from '../../utils/overviewRoute' import CardLanguages from '../cards/CardLanguages' @@ -10,17 +10,9 @@ const RouteLanguages = (props) => { useEffect(() => { - props.fetchDomains(props) + props.fetchLanguages(props) - }, []) - - useDidMountEffect(() => { - - props.domains.value.map((domain) => { - props.fetchLanguages(props, domain.data.id) - }) - - }, [ props.filter.range, props.domains.value, props.languages.sorting ]) + }, [ props.filter.range, props.filter.sorting ]) return ( h(Fragment, {}, @@ -28,12 +20,13 @@ const RouteLanguages = (props) => { props.domains.value.map( (domain) => ( h(CardLanguages, { - key: domain.data.id, - headline: domain.data.title, + key: domain.id, + headline: domain.title, range: props.filter.range, - sorting: props.languages.sorting, - loading: selectLanguagesValue(props, domain.data.id).fetching, - items: enhanceLanguages(selectLanguagesValue(props, domain.data.id).value) + sorting: props.filter.sorting, + loading: props.languages.fetching, + items: enhanceLanguages(selectLanguagesValue(props, domain.id).value), + onMore: () => props.setRoute(overviewRoute(domain)) }) ) ) diff --git a/src/ui/scripts/components/routes/RouteOverview.js b/src/ui/scripts/components/routes/RouteOverview.js new file mode 100644 index 00000000..74c33124 --- /dev/null +++ b/src/ui/scripts/components/routes/RouteOverview.js @@ -0,0 +1,140 @@ +import { createElement as h, Fragment, useEffect } from 'react' + +import * as route from '../../constants/route' +import { ALL_DOMAINS } from '../../actions/overview' +import * as selectOverviewValue from '../../selectors/selectOverviewValue' +import { initialState as initialFilterState } from '../../reducers/filter' + +import enhanceFacts from '../../enhancers/enhanceFacts' +import enhanceViews from '../../enhancers/enhanceViews' +import enhancePages from '../../enhancers/enhancePages' +import enhanceReferrers from '../../enhancers/enhanceReferrers' +import enhanceDurations from '../../enhancers/enhanceDurations' +import enhanceSystems from '../../enhancers/enhanceSystems' +import enhanceDevices from '../../enhancers/enhanceDevices' +import enhanceBrowsers from '../../enhancers/enhanceBrowsers' +import enhanceSizes from '../../enhancers/enhanceSizes' +import enhanceLanguages from '../../enhancers/enhanceLanguages' + +import CardFacts from '../cards/CardFacts' +import CardViews from '../cards/CardViews' +import CardPages from '../cards/CardPages' +import CardReferrers from '../cards/CardReferrers' +import CardDurations from '../cards/CardDurations' +import CardSystems from '../cards/CardSystems' +import CardDevices from '../cards/CardDevices' +import CardBrowsers from '../cards/CardBrowsers' +import CardSizes from '../cards/CardSizes' +import CardLanguages from '../cards/CardLanguages' + +const RouteOverview = (props) => { + + const domainId = props.route.params.domainId || ALL_DOMAINS + const filterState = initialFilterState() + const isLoading = selectOverviewValue.withoutType(props, domainId).fetching + + useEffect(() => { + + props.fetchOverview(props, domainId) + + }, [ domainId ]) + + return ( + h(Fragment, {}, + + h(CardFacts, { + loading: isLoading, + items: enhanceFacts(selectOverviewValue.withoutType(props, domainId).facts) + }), + + h('div', { className: 'content__spacer' }), + + h(CardViews, { + wide: true, + headline: 'Views', + interval: filterState.interval, + loading: isLoading, + items: enhanceViews(selectOverviewValue.withType(props, domainId, 'views'), 14), + onMore: () => props.setRoute(route.ROUTE_VIEWS) + }), + + h(CardDurations, { + wide: true, + headline: 'Durations', + interval: filterState.interval, + loading: isLoading, + items: enhanceDurations(selectOverviewValue.withType(props, domainId, 'durations'), 14), + onMore: () => props.setRoute(route.ROUTE_DURATIONS) + }), + + h(CardPages, { + headline: 'Pages', + range: filterState.range, + sorting: filterState.sorting, + loading: isLoading, + items: enhancePages(selectOverviewValue.withType(props, domainId, 'pages')), + onMore: () => props.setRoute(route.ROUTE_PAGES) + }), + + h(CardReferrers, { + headline: 'Referrers', + range: filterState.range, + sorting: filterState.sorting, + loading: isLoading, + items: enhanceReferrers(selectOverviewValue.withType(props, domainId, 'referrers')), + onMore: () => props.setRoute(route.ROUTE_REFERRERS) + }), + + h('div', { className: 'content__spacer' }), + + h(CardSystems, { + headline: 'Systems', + range: filterState.range, + sorting: filterState.sorting, + loading: isLoading, + items: enhanceSystems(selectOverviewValue.withType(props, domainId, 'systems')), + onMore: () => props.setRoute(route.ROUTE_SYSTEMS) + }), + + h(CardDevices, { + headline: 'Devices', + range: filterState.range, + sorting: filterState.sorting, + loading: isLoading, + items: enhanceDevices(selectOverviewValue.withType(props, domainId, 'devices')), + onMore: () => props.setRoute(route.ROUTE_DEVICES) + }), + + h(CardBrowsers, { + headline: 'Browsers', + range: filterState.range, + sorting: filterState.sorting, + loading: isLoading, + items: enhanceBrowsers(selectOverviewValue.withType(props, domainId, 'browsers')), + onMore: () => props.setRoute(route.ROUTE_BROWSERS) + }), + + h(CardSizes, { + headline: 'Sizes', + range: filterState.range, + sorting: filterState.sorting, + loading: isLoading, + items: enhanceSizes(selectOverviewValue.withType(props, domainId, 'sizes')), + onMore: () => props.setRoute(route.ROUTE_SIZES) + }), + + h(CardLanguages, { + headline: 'Languages', + range: filterState.range, + sorting: filterState.sorting, + loading: isLoading, + items: enhanceLanguages(selectOverviewValue.withType(props, domainId, 'languages')), + onMore: () => props.setRoute(route.ROUTE_LANGUAGES) + }) + + ) + ) + +} + +export default RouteOverview \ No newline at end of file diff --git a/src/ui/scripts/components/routes/RoutePages.js b/src/ui/scripts/components/routes/RoutePages.js index 4b63f790..29263683 100644 --- a/src/ui/scripts/components/routes/RoutePages.js +++ b/src/ui/scripts/components/routes/RoutePages.js @@ -2,7 +2,7 @@ import { createElement as h, Fragment, useEffect } from 'react' import selectPagesValue from '../../selectors/selectPagesValue' import enhancePages from '../../enhancers/enhancePages' -import useDidMountEffect from '../../utils/useDidMountEffect' +import overviewRoute from '../../utils/overviewRoute' import CardPages from '../cards/CardPages' @@ -10,17 +10,9 @@ const RoutePages = (props) => { useEffect(() => { - props.fetchDomains(props) + props.fetchPages(props) - }, []) - - useDidMountEffect(() => { - - props.domains.value.map((domain) => { - props.fetchPages(props, domain.data.id) - }) - - }, [ props.filter.range, props.domains.value, props.pages.sorting ]) + }, [ props.filter.range, props.filter.sorting ]) return ( h(Fragment, {}, @@ -28,12 +20,13 @@ const RoutePages = (props) => { props.domains.value.map( (domain) => ( h(CardPages, { - key: domain.data.id, - headline: domain.data.title, + key: domain.id, + headline: domain.title, range: props.filter.range, - sorting: props.pages.sorting, - loading: selectPagesValue(props, domain.data.id).fetching, - items: enhancePages(selectPagesValue(props, domain.data.id).value) + sorting: props.filter.sorting, + loading: props.pages.fetching, + items: enhancePages(selectPagesValue(props, domain.id).value), + onMore: () => props.setRoute(overviewRoute(domain)) }) ) ) diff --git a/src/ui/scripts/components/routes/RouteReferrers.js b/src/ui/scripts/components/routes/RouteReferrers.js index 3e911858..dd68f88b 100644 --- a/src/ui/scripts/components/routes/RouteReferrers.js +++ b/src/ui/scripts/components/routes/RouteReferrers.js @@ -2,7 +2,7 @@ import { createElement as h, Fragment, useEffect } from 'react' import selectReferrersValue from '../../selectors/selectReferrersValue' import enhanceReferrers from '../../enhancers/enhanceReferrers' -import useDidMountEffect from '../../utils/useDidMountEffect' +import overviewRoute from '../../utils/overviewRoute' import CardReferrers from '../cards/CardReferrers' @@ -10,17 +10,9 @@ const RouteReferrers = (props) => { useEffect(() => { - props.fetchDomains(props) + props.fetchReferrers(props) - }, []) - - useDidMountEffect(() => { - - props.domains.value.map((domain) => { - props.fetchReferrers(props, domain.data.id) - }) - - }, [ props.filter.range, props.domains.value, props.referrers.sorting ]) + }, [ props.filter.range, props.filter.sorting ]) return ( h(Fragment, {}, @@ -28,12 +20,13 @@ const RouteReferrers = (props) => { props.domains.value.map( (domain) => ( h(CardReferrers, { - key: domain.data.id, - headline: domain.data.title, + key: domain.id, + headline: domain.title, range: props.filter.range, - sorting: props.referrers.sorting, - loading: selectReferrersValue(props, domain.data.id).fetching, - items: enhanceReferrers(selectReferrersValue(props, domain.data.id).value) + sorting: props.filter.sorting, + loading: props.referrers.fetching, + items: enhanceReferrers(selectReferrersValue(props, domain.id).value), + onMore: () => props.setRoute(overviewRoute(domain)) }) ) ) diff --git a/src/ui/scripts/components/routes/RouteSettings.js b/src/ui/scripts/components/routes/RouteSettings.js index eed5c336..01960fa7 100644 --- a/src/ui/scripts/components/routes/RouteSettings.js +++ b/src/ui/scripts/components/routes/RouteSettings.js @@ -1,4 +1,4 @@ -import { createElement as h, Fragment, useEffect } from 'react' +import { createElement as h, Fragment } from 'react' import { version, homepage } from '../../../../../package' import { MODALS_DOMAIN_EDIT, MODALS_DOMAIN_ADD } from '../../constants/modals' @@ -10,12 +10,6 @@ import Message from '../Message' const RouteSettings = (props) => { - useEffect(() => { - - props.fetchDomains(props) - - }, []) - const showDomainEditModal = (id, title) => { props.addModalsModal({ @@ -46,9 +40,9 @@ const RouteSettings = (props) => { (domain) => [ h(LinkItem, { type: 'button', - text: domain.data.id, - onClick: () => showDomainEditModal(domain.data.id, domain.data.title) - }, domain.data.title), + text: domain.id, + onClick: () => showDomainEditModal(domain.id, domain.title) + }, domain.title), h(Line) ] ).flat(), @@ -75,9 +69,11 @@ const RouteSettings = (props) => { h(CardSetting, { headline: 'Donate' }, - h(LinkItem, { type: 'a', href: 'https://paypal.me/electerious', target: '_blank', rel: 'noopener' }, 'Donate via PayPal'), + h(LinkItem, { type: 'a', href: 'https://github.com/sponsors/electerious', target: '_blank', rel: 'noopener' }, 'Become a GitHub sponsor'), + h(Line), + h(LinkItem, { type: 'a', href: 'https://www.buymeacoffee.com/electerious', target: '_blank', rel: 'noopener' }, 'Buy me a coffee'), h(Line), - h(LinkItem, { type: 'a', href: 'https://www.buymeacoffee.com/electerious', target: '_blank', rel: 'noopener' }, 'Buy me a coffee') + h(LinkItem, { type: 'a', href: 'https://paypal.me/electerious', target: '_blank', rel: 'noopener' }, 'Donate via PayPal') ), h(CardSetting, { diff --git a/src/ui/scripts/components/routes/RouteSizes.js b/src/ui/scripts/components/routes/RouteSizes.js index a914643d..2e29732e 100644 --- a/src/ui/scripts/components/routes/RouteSizes.js +++ b/src/ui/scripts/components/routes/RouteSizes.js @@ -2,7 +2,7 @@ import { createElement as h, Fragment, useEffect } from 'react' import selectSizesValue from '../../selectors/selectSizesValue' import enhanceSizes from '../../enhancers/enhanceSizes' -import useDidMountEffect from '../../utils/useDidMountEffect' +import overviewRoute from '../../utils/overviewRoute' import CardSizes from '../cards/CardSizes' @@ -10,17 +10,9 @@ const RouteSizes = (props) => { useEffect(() => { - props.fetchDomains(props) + props.fetchSizes(props) - }, []) - - useDidMountEffect(() => { - - props.domains.value.map((domain) => { - props.fetchSizes(props, domain.data.id) - }) - - }, [ props.filter.range, props.domains.value, props.sizes.type ]) + }, [ props.filter.range, props.filter.sorting, props.sizes.type ]) return ( h(Fragment, {}, @@ -28,11 +20,13 @@ const RouteSizes = (props) => { props.domains.value.map( (domain) => ( h(CardSizes, { - key: domain.data.id, + key: domain.id, + headline: domain.title, range: props.filter.range, - headline: domain.data.title, - loading: selectSizesValue(props, domain.data.id).fetching, - items: enhanceSizes(selectSizesValue(props, domain.data.id).value) + sorting: props.filter.sorting, + loading: props.sizes.fetching, + items: enhanceSizes(selectSizesValue(props, domain.id).value), + onMore: () => props.setRoute(overviewRoute(domain)) }) ) ) diff --git a/src/ui/scripts/components/routes/RouteSystems.js b/src/ui/scripts/components/routes/RouteSystems.js index 39abcb88..201b3934 100644 --- a/src/ui/scripts/components/routes/RouteSystems.js +++ b/src/ui/scripts/components/routes/RouteSystems.js @@ -2,7 +2,7 @@ import { createElement as h, Fragment, useEffect } from 'react' import selectSystemsValue from '../../selectors/selectSystemsValue' import enhanceSystems from '../../enhancers/enhanceSystems' -import useDidMountEffect from '../../utils/useDidMountEffect' +import overviewRoute from '../../utils/overviewRoute' import CardSystems from '../cards/CardSystems' @@ -10,17 +10,9 @@ const RouteSystems = (props) => { useEffect(() => { - props.fetchDomains(props) + props.fetchSystems(props) - }, []) - - useDidMountEffect(() => { - - props.domains.value.map((domain) => { - props.fetchSystems(props, domain.data.id) - }) - - }, [ props.filter.range, props.domains.value, props.systems.sorting, props.systems.type ]) + }, [ props.filter.range, props.filter.sorting, props.systems.type ]) return ( h(Fragment, {}, @@ -28,12 +20,13 @@ const RouteSystems = (props) => { props.domains.value.map( (domain) => ( h(CardSystems, { - key: domain.data.id, - headline: domain.data.title, + key: domain.id, + headline: domain.title, range: props.filter.range, - sorting: props.systems.sorting, - loading: selectSystemsValue(props, domain.data.id).fetching, - items: enhanceSystems(selectSystemsValue(props, domain.data.id).value) + sorting: props.filter.sorting, + loading: props.systems.fetching, + items: enhanceSystems(selectSystemsValue(props, domain.id).value), + onMore: () => props.setRoute(overviewRoute(domain)) }) ) ) diff --git a/src/ui/scripts/components/routes/RouteViews.js b/src/ui/scripts/components/routes/RouteViews.js index 6dff74cd..085633e3 100644 --- a/src/ui/scripts/components/routes/RouteViews.js +++ b/src/ui/scripts/components/routes/RouteViews.js @@ -1,11 +1,10 @@ import { createElement as h, Fragment, useEffect } from 'react' import { VIEWS_TYPE_UNIQUE, VIEWS_TYPE_TOTAL } from '../../../../constants/views' - import selectViewsValue from '../../selectors/selectViewsValue' import enhanceViews from '../../enhancers/enhanceViews' import mergeViews from '../../utils/mergeViews' -import useDidMountEffect from '../../utils/useDidMountEffect' +import overviewRoute from '../../utils/overviewRoute' import CardViews from '../cards/CardViews' @@ -13,17 +12,9 @@ const RouteViews = (props) => { useEffect(() => { - props.fetchDomains(props) - - }, []) - - useDidMountEffect(() => { - - props.domains.value.map((domain) => { - props.fetchViews(props, domain.data.id) - }) + props.fetchViews(props) - }, [ props.domains.value, props.views.type, props.views.interval ]) + }, [ props.filter.interval, props.views.type ]) return ( h(Fragment, {}, @@ -34,17 +25,20 @@ const RouteViews = (props) => { [VIEWS_TYPE_UNIQUE]: 'Site Views', [VIEWS_TYPE_TOTAL]: 'Page Views' })[props.views.type], - interval: props.views.interval, + interval: props.filter.interval, + loading: props.fetching, items: mergeViews(props) }), props.domains.value.map( (domain) => ( h(CardViews, { - key: domain.data.id, - headline: domain.data.title, - interval: props.views.interval, - items: enhanceViews(selectViewsValue(props, domain.data.id).value, 7, props.views.interval) + key: domain.id, + headline: domain.title, + interval: props.filter.interval, + loading: props.views.fetching, + items: enhanceViews(selectViewsValue(props, domain.id).value, 7), + onMore: () => props.setRoute(overviewRoute(domain)) }) ) ) diff --git a/src/ui/scripts/constants/route.js b/src/ui/scripts/constants/route.js index 8de07417..13e50b7c 100644 --- a/src/ui/scripts/constants/route.js +++ b/src/ui/scripts/constants/route.js @@ -1,10 +1,23 @@ -export const ROUTE_VIEWS = 'route_views' -export const ROUTE_PAGES = 'route_pages' -export const ROUTE_REFERRERS = 'route_referrers' -export const ROUTE_DURATIONS = 'route_durations' -export const ROUTE_LANGUAGES = 'route_languages' -export const ROUTE_SIZES = 'route_sizes' -export const ROUTE_SYSTEMS = 'route_systems' -export const ROUTE_SETTINGS = 'route_settings' -export const ROUTE_DEVICES = 'route_devices' -export const ROUTE_BROWSERS = 'route_browsers' \ No newline at end of file +import RouteOverview from '../components/routes/RouteOverview' +import RouteViews from '../components/routes/RouteViews' +import RoutePages from '../components/routes/RoutePages' +import RouteReferrers from '../components/routes/RouteReferrers' +import RouteDurations from '../components/routes/RouteDurations' +import RouteBrowsers from '../components/routes/RouteBrowsers' +import RouteDevices from '../components/routes/RouteDevices' +import RouteLanguages from '../components/routes/RouteLanguages' +import RouteSystems from '../components/routes/RouteSystems' +import RouteSizes from '../components/routes/RouteSizes' +import RouteSettings from '../components/routes/RouteSettings' + +export const ROUTE_OVERVIEW = { key: 'route_overview', title: 'Overview', component: RouteOverview } +export const ROUTE_VIEWS = { key: 'route_views', title: 'Views', component: RouteViews } +export const ROUTE_PAGES = { key: 'route_pages', title: 'Pages', component: RoutePages } +export const ROUTE_REFERRERS = { key: 'route_referrers', title: 'Referrers', component: RouteReferrers } +export const ROUTE_DURATIONS = { key: 'route_durations', title: 'Durations', component: RouteDurations } +export const ROUTE_LANGUAGES = { key: 'route_languages', title: 'Languages', component: RouteLanguages } +export const ROUTE_SIZES = { key: 'route_sizes', title: 'Sizes', component: RouteSizes } +export const ROUTE_SYSTEMS = { key: 'route_systems', title: 'Systems', component: RouteSystems } +export const ROUTE_SETTINGS = { key: 'route_settings', title: 'Settings', component: RouteSettings } +export const ROUTE_DEVICES = { key: 'route_devices', title: 'Devices', component: RouteDevices } +export const ROUTE_BROWSERS = { key: 'route_browsers', title: 'Browsers', component: RouteBrowsers } \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhanceAverageDurations.js b/src/ui/scripts/enhancers/enhanceAverageDurations.js deleted file mode 100644 index 0a4a9aa5..00000000 --- a/src/ui/scripts/enhancers/enhanceAverageDurations.js +++ /dev/null @@ -1,17 +0,0 @@ -import { subDays } from 'date-fns' - -import createArray from '../utils/createArray' -import matchesDate from '../utils/matchesDate' - -export default (durations, length) => createArray(length).map((_, index) => { - - const date = subDays(new Date(), index) - - // Find a duration that matches the date - const duration = durations.find((duration) => { - return matchesDate(duration.data.id.day, duration.data.id.month, duration.data.id.year, date) - }) - - return duration == null ? 0 : duration.data.average - -}) \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhanceBrowsers.js b/src/ui/scripts/enhancers/enhanceBrowsers.js index 783c9a2d..918fdf44 100644 --- a/src/ui/scripts/enhancers/enhanceBrowsers.js +++ b/src/ui/scripts/enhancers/enhanceBrowsers.js @@ -1,20 +1,9 @@ -const getText = ({ id }) => { - - const isWithVersion = id.browserVersion != null - - if (isWithVersion === true) return `${ id.browserName } ${ id.browserVersion }` - - return id - -} - export default (browsers) => { - // Extract and enhance the data from the API return browsers.map((browser) => ({ - text: getText(browser.data), - count: browser.data.count, - date: browser.data.created == null ? null : new Date(browser.data.created) + text: browser.id, + count: browser.count, + date: browser.created == null ? null : new Date(browser.created) })) } \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhanceDetailedDurations.js b/src/ui/scripts/enhancers/enhanceDetailedDurations.js deleted file mode 100644 index 8b0793a9..00000000 --- a/src/ui/scripts/enhancers/enhanceDetailedDurations.js +++ /dev/null @@ -1,10 +0,0 @@ -export default (durations) => { - - // Extract and enhance the data from the API - return durations.map((duration) => ({ - duration: duration.data.id, - average: duration.data.average, - count: duration.data.count - })) - -} \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhanceDevices.js b/src/ui/scripts/enhancers/enhanceDevices.js index 728085d9..2ebe57d9 100644 --- a/src/ui/scripts/enhancers/enhanceDevices.js +++ b/src/ui/scripts/enhancers/enhanceDevices.js @@ -1,20 +1,9 @@ -const getText = ({ id }) => { - - const isWithModel = id.deviceName != null - - if (isWithModel === true) return `${ id.deviceManufacturer } ${ id.deviceName }` - - return id - -} - export default (devices) => { - // Extract and enhance the data from the API return devices.map((device) => ({ - text: getText(device.data), - count: device.data.count, - date: device.data.created == null ? null : new Date(device.data.created) + text: device.id, + count: device.count, + date: device.created == null ? null : new Date(device.created) })) } \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhanceDurations.js b/src/ui/scripts/enhancers/enhanceDurations.js new file mode 100644 index 00000000..7fa340d0 --- /dev/null +++ b/src/ui/scripts/enhancers/enhanceDurations.js @@ -0,0 +1,10 @@ +import createArray from '../../../utils/createArray' + +// TODO: Avoid that this functions runs that may times +export default (durations, length) => createArray(length).map((_, index) => { + + const duration = durations[index] + + return duration == null ? 0 : duration.count + +}) \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhanceFacts.js b/src/ui/scripts/enhancers/enhanceFacts.js new file mode 100644 index 00000000..1c2b3294 --- /dev/null +++ b/src/ui/scripts/enhancers/enhanceFacts.js @@ -0,0 +1,17 @@ +const defaults = { + activeVisitors: 0, + averageViews: 0, + averageDuration: 0, + viewsToday: 0, + viewsMonth: 0, + viewsYear: 0 +} + +export default (items) => { + + return { + ...defaults, + ...items + } + +} \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhanceLanguages.js b/src/ui/scripts/enhancers/enhanceLanguages.js index 84654976..c8f940cd 100644 --- a/src/ui/scripts/enhancers/enhanceLanguages.js +++ b/src/ui/scripts/enhancers/enhanceLanguages.js @@ -1,12 +1,9 @@ -import languageCodes from '../utils/languageCodes' - export default (languages) => { - // Extract and enhance the data from the API return languages.map((language) => ({ - text: languageCodes[language.data.id] || language.data.id, - count: language.data.count, - date: language.data.created == null ? null : new Date(language.data.created) + text: language.id, + count: language.count, + date: language.created == null ? null : new Date(language.created) })) } \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhancePages.js b/src/ui/scripts/enhancers/enhancePages.js index 40ff991c..556e2acd 100644 --- a/src/ui/scripts/enhancers/enhancePages.js +++ b/src/ui/scripts/enhancers/enhancePages.js @@ -1,11 +1,10 @@ export default (pages) => { - // Extract and enhance the data from the API return pages.map((page) => ({ - url: new URL(page.data.id), - text: new URL(page.data.id).href, - count: page.data.count, - date: page.data.created == null ? null : new Date(page.data.created) + url: new URL(page.id), + text: new URL(page.id).href, + count: page.count, + date: page.created == null ? null : new Date(page.created) })) } \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhanceReferrers.js b/src/ui/scripts/enhancers/enhanceReferrers.js index bd1d59c9..f2282d3c 100644 --- a/src/ui/scripts/enhancers/enhanceReferrers.js +++ b/src/ui/scripts/enhancers/enhanceReferrers.js @@ -1,11 +1,10 @@ export default (referrers) => { - // Extract and enhance the data from the API return referrers.map((referrer) => ({ - url: new URL(referrer.data.id), - text: new URL(referrer.data.id).href, - count: referrer.data.count, - date: referrer.data.created == null ? null : new Date(referrer.data.created) + url: new URL(referrer.id), + text: new URL(referrer.id).href, + count: referrer.count, + date: referrer.created == null ? null : new Date(referrer.created) })) } \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhanceSizes.js b/src/ui/scripts/enhancers/enhanceSizes.js index 938b4689..2ef2f99d 100644 --- a/src/ui/scripts/enhancers/enhanceSizes.js +++ b/src/ui/scripts/enhancers/enhanceSizes.js @@ -1,21 +1,9 @@ -const getText = ({ id }) => { - - const isScreenResolution = id.screenWidth != null && id.screenHeight != null - const isBrowserResolution = id.browserWidth != null && id.browserHeight != null - - if (isScreenResolution === true) return `${ id.screenWidth }px x ${ id.screenHeight }px` - if (isBrowserResolution === true) return `${ id.browserWidth }px x ${ id.browserHeight }px` - - return `${ id }px` - -} - export default (sizes) => { - // Extract and enhance the data from the API return sizes.map((size) => ({ - text: getText(size.data), - count: size.data.count + text: size.id, + count: size.count, + date: size.created == null ? null : new Date(size.created) })) } \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhanceState.js b/src/ui/scripts/enhancers/enhanceState.js index 80656a56..62026206 100644 --- a/src/ui/scripts/enhancers/enhanceState.js +++ b/src/ui/scripts/enhancers/enhanceState.js @@ -1,31 +1,37 @@ +import { ALL_DOMAINS } from '../actions/overview' import isDefined from '../../../utils/isDefined' +import * as selectOverviewValue from '../selectors/selectOverviewValue' export default (state) => { const fetching = ( - Object.values(state.views.value).some((value) => value.fetching) === true || - Object.values(state.pages.value).some((value) => value.fetching) === true || - Object.values(state.referrers.value).some((value) => value.fetching) === true || - Object.values(state.durations.value).some((value) => value.fetching) === true || - Object.values(state.systems.value).some((value) => value.fetching) === true || - Object.values(state.devices.value).some((value) => value.fetching) === true || - Object.values(state.browsers.value).some((value) => value.fetching) === true || - Object.values(state.sizes.value).some((value) => value.fetching) === true || - Object.values(state.languages.value).some((value) => value.fetching) === true || + selectOverviewValue.withoutType(state, ALL_DOMAINS).fetching === true || + Object.values(state.overview.value).some((value) => value.fetching) === true || + state.views.fetching === true || + state.pages.fetching === true || + state.referrers.fetching === true || + state.durations.fetching === true || + state.systems.fetching === true || + state.devices.fetching === true || + state.browsers.fetching === true || + state.sizes.fetching === true || + state.languages.fetching === true || state.domains.fetching === true || state.token.fetching === true ) const errors = [ - ...Object.values(state.views.value).map((value) => value.error), - ...Object.values(state.pages.value).map((value) => value.error), - ...Object.values(state.referrers.value).map((value) => value.error), - ...Object.values(state.durations.value).map((value) => value.error), - ...Object.values(state.systems.value).map((value) => value.error), - ...Object.values(state.devices.value).map((value) => value.error), - ...Object.values(state.browsers.value).map((value) => value.error), - ...Object.values(state.sizes.value).map((value) => value.error), - ...Object.values(state.languages.value).map((value) => value.error), + selectOverviewValue.withoutType(state, ALL_DOMAINS).error, + ...Object.values(state.overview.value).map((value) => value.error), + state.views.error, + state.pages.error, + state.referrers.error, + state.durations.error, + state.systems.error, + state.devices.error, + state.browsers.error, + state.sizes.error, + state.languages.error, state.domains.error, state.token.error ].filter(isDefined) diff --git a/src/ui/scripts/enhancers/enhanceSystems.js b/src/ui/scripts/enhancers/enhanceSystems.js index 3b01cd0b..9c6fb768 100644 --- a/src/ui/scripts/enhancers/enhanceSystems.js +++ b/src/ui/scripts/enhancers/enhanceSystems.js @@ -1,20 +1,9 @@ -const getText = ({ id }) => { - - const isWithVersion = id.osVersion != null - - if (isWithVersion === true) return `${ id.osName } ${ id.osVersion }` - - return id - -} - export default (systems) => { - // Extract and enhance the data from the API return systems.map((system) => ({ - text: getText(system.data), - count: system.data.count, - date: system.data.created == null ? null : new Date(system.data.created) + text: system.id, + count: system.count, + date: system.created == null ? null : new Date(system.created) })) } \ No newline at end of file diff --git a/src/ui/scripts/enhancers/enhanceViews.js b/src/ui/scripts/enhancers/enhanceViews.js index 81e45347..12d5dd00 100644 --- a/src/ui/scripts/enhancers/enhanceViews.js +++ b/src/ui/scripts/enhancers/enhanceViews.js @@ -1,42 +1,10 @@ -import { subDays, subMonths, subYears } from 'date-fns' +import createArray from '../../../utils/createArray' -import { - VIEWS_INTERVAL_DAILY, - VIEWS_INTERVAL_MONTHLY, - VIEWS_INTERVAL_YEARLY -} from '../../../constants/views' +// TODO: Avoid that this functions runs that may times +export default (views, length) => createArray(length).map((_, index) => { -import createArray from '../utils/createArray' -import matchesDate from '../utils/matchesDate' + const view = views[index] -const subFn = (interval) => { - - switch (interval) { - case VIEWS_INTERVAL_DAILY: return subDays - case VIEWS_INTERVAL_MONTHLY: return subMonths - case VIEWS_INTERVAL_YEARLY: return subYears - } - -} - -export default (views, length, interval) => createArray(length).map((_, index) => { - - const matchDay = [ VIEWS_INTERVAL_DAILY ].includes(interval) - const matchMonth = [ VIEWS_INTERVAL_DAILY, VIEWS_INTERVAL_MONTHLY ].includes(interval) - const matchYear = [ VIEWS_INTERVAL_DAILY, VIEWS_INTERVAL_MONTHLY, VIEWS_INTERVAL_YEARLY ].includes(interval) - - const date = subFn(interval)(new Date(), index) - - // Find a view that matches the date - const view = views.find((view) => { - return matchesDate( - matchDay === true ? view.data.id.day : undefined, - matchMonth === true ? view.data.id.month : undefined, - matchYear === true ? view.data.id.year : undefined, - date - ) - }) - - return view == null ? 0 : view.data.count + return view == null ? 0 : view.count }) \ No newline at end of file diff --git a/src/ui/scripts/index.js b/src/ui/scripts/index.js index 88d3f349..d573f08f 100644 --- a/src/ui/scripts/index.js +++ b/src/ui/scripts/index.js @@ -3,7 +3,7 @@ import { render } from 'react-dom' import { bindActionCreators } from 'redux' import { Provider, connect } from 'react-redux' -import isDemo from '../../utils/isDemo' +import isDemoMode from '../../utils/isDemoMode' import enhanceState from './enhancers/enhanceState' import createStore from './utils/createStore' @@ -15,10 +15,6 @@ import { initialState as initialTokenState } from './reducers/token' import { initialState as initialRouteState } from './reducers/route' import { initialState as initialFilterState } from './reducers/filter' import { initialState as initialViewsState } from './reducers/views' -import { initialState as initialPagesState } from './reducers/pages' -import { initialState as initialReferrersState } from './reducers/referrers' -import { initialState as initialDurationsState } from './reducers/durations' -import { initialState as initialLanguagesState } from './reducers/languages' import { initialState as initialSystemsState } from './reducers/systems' import { initialState as initialBrowsersState } from './reducers/browsers' import { initialState as initialDevicesState } from './reducers/devices' @@ -35,7 +31,7 @@ const mapDispatchToProps = (dispatch) => bindActionCreators(actions, dispatch) const ConnectedMain = connect(mapStateToProps, mapDispatchToProps)(Main) const container = document.querySelector('#main') -if (isDemo === true) { +if (isDemoMode === true) { console.warn('Ackee runs in demo mode') } @@ -50,56 +46,33 @@ store.subscribe(() => { }, route: { ...initialRouteState(), - value: currentState.route.value + key: currentState.route.key, + params: currentState.route.params }, filter: { ...initialFilterState(), - range: currentState.filter.range + sorting: currentState.filter.sorting, + range: currentState.filter.range, + interval: currentState.filter.interval }, views: { ...initialViewsState(), - type: currentState.views.type, - interval: currentState.views.interval - }, - pages: { - ...initialPagesState(), - sorting: currentState.pages.sorting - }, - referrers: { - ...initialReferrersState(), - range: currentState.referrers.range, - sorting: currentState.referrers.sorting - }, - durations: { - ...initialDurationsState(), - type: currentState.durations.type - }, - languages: { - ...initialLanguagesState(), - range: currentState.languages.range, - sorting: currentState.languages.sorting + type: currentState.views.type }, systems: { ...initialSystemsState(), - range: currentState.systems.range, - type: currentState.systems.type, - sorting: currentState.systems.sorting + type: currentState.systems.type }, browsers: { ...initialBrowsersState(), - range: currentState.browsers.range, - type: currentState.browsers.type, - sorting: currentState.browsers.sorting + type: currentState.browsers.type }, devices: { ...initialDevicesState(), - range: currentState.devices.range, - type: currentState.devices.type, - sorting: currentState.devices.sorting + type: currentState.devices.type }, sizes: { ...initialSizesState(), - range: currentState.sizes.range, type: currentState.sizes.type } }) diff --git a/src/ui/scripts/reducers/browsers.js b/src/ui/scripts/reducers/browsers.js index a0c76637..52c0f0c9 100644 --- a/src/ui/scripts/reducers/browsers.js +++ b/src/ui/scripts/reducers/browsers.js @@ -3,24 +3,20 @@ import produce from 'immer' import { SET_BROWSERS_ERROR, SET_BROWSERS_FETCHING, - SET_BROWSERS_SORTING, SET_BROWSERS_VALUE, SET_BROWSERS_TYPE } from '../actions' -import { BROWSERS_SORTING_TOP, BROWSERS_TYPE_NO_VERSION } from '../../../constants/browsers' +import { BROWSERS_TYPE_NO_VERSION } from '../../../constants/browsers' +import genericState from '../utils/genericState' +import genericSubState from '../utils/genericSubState' export const initialState = () => ({ type: BROWSERS_TYPE_NO_VERSION, - sorting: BROWSERS_SORTING_TOP, - value: {} + ...genericState() }) -export const initialSubState = () => ({ - value: [], - fetching: false, - error: undefined -}) +export const initialSubState = genericSubState export default produce((draft, action) => { @@ -36,20 +32,14 @@ export default produce((draft, action) => { draft.value = initialState().value draft.type = action.payload break - case SET_BROWSERS_SORTING: - if (draft.sorting === action.payload) break - // Reset value because the view shouldn't show the old data when switching - draft.value = initialState().value - draft.sorting = action.payload - break case SET_BROWSERS_VALUE: draft.value[action.domainId].value = action.payload || initialSubState().value break case SET_BROWSERS_FETCHING: - draft.value[action.domainId].fetching = action.payload || initialSubState().fetching + draft.fetching = action.payload || initialState().fetching break case SET_BROWSERS_ERROR: - draft.value[action.domainId].error = action.payload || initialSubState().error + draft.error = action.payload || initialState().error break } diff --git a/src/ui/scripts/reducers/devices.js b/src/ui/scripts/reducers/devices.js index 9f238a8e..3aa51643 100644 --- a/src/ui/scripts/reducers/devices.js +++ b/src/ui/scripts/reducers/devices.js @@ -3,24 +3,20 @@ import produce from 'immer' import { SET_DEVICES_ERROR, SET_DEVICES_FETCHING, - SET_DEVICES_SORTING, SET_DEVICES_VALUE, SET_DEVICES_TYPE } from '../actions' -import { DEVICES_SORTING_TOP, DEVICES_TYPE_WITH_MODEL } from '../../../constants/devices' +import { DEVICES_TYPE_WITH_MODEL } from '../../../constants/devices' +import genericState from '../utils/genericState' +import genericSubState from '../utils/genericSubState' export const initialState = () => ({ type: DEVICES_TYPE_WITH_MODEL, - sorting: DEVICES_SORTING_TOP, - value: {} + ...genericState() }) -export const initialSubState = () => ({ - value: [], - fetching: false, - error: undefined -}) +export const initialSubState = genericSubState export default produce((draft, action) => { @@ -36,20 +32,14 @@ export default produce((draft, action) => { draft.value = initialState().value draft.type = action.payload break - case SET_DEVICES_SORTING: - if (draft.sorting === action.payload) break - // Reset value because the view shouldn't show the old data when switching - draft.value = initialState().value - draft.sorting = action.payload - break case SET_DEVICES_VALUE: draft.value[action.domainId].value = action.payload || initialSubState().value break case SET_DEVICES_FETCHING: - draft.value[action.domainId].fetching = action.payload || initialSubState().fetching + draft.fetching = action.payload || initialState().fetching break case SET_DEVICES_ERROR: - draft.value[action.domainId].error = action.payload || initialSubState().error + draft.error = action.payload || initialState().error break } diff --git a/src/ui/scripts/reducers/durations.js b/src/ui/scripts/reducers/durations.js index 2798f82a..941171ba 100644 --- a/src/ui/scripts/reducers/durations.js +++ b/src/ui/scripts/reducers/durations.js @@ -1,24 +1,17 @@ import produce from 'immer' import { - SET_DURATIONS_TYPE, SET_DURATIONS_VALUE, SET_DURATIONS_FETCHING, SET_DURATIONS_ERROR } from '../actions' -import { DURATIONS_TYPE_AVERAGE } from '../../../constants/durations' +import genericState from '../utils/genericState' +import genericSubState from '../utils/genericSubState' -export const initialState = () => ({ - type: DURATIONS_TYPE_AVERAGE, - value: {} -}) +export const initialState = genericState -export const initialSubState = () => ({ - value: [], - fetching: false, - error: undefined -}) +export const initialSubState = genericSubState export default produce((draft, action) => { @@ -28,20 +21,14 @@ export default produce((draft, action) => { if (hasDomainId() === true && hasDomainValue() === false) draft.value[action.domainId] = initialSubState() switch (action.type) { - case SET_DURATIONS_TYPE: - if (draft.type === action.payload) break - // Reset value because the view shouldn't show the old data when switching - draft.value = initialState().value - draft.type = action.payload - break case SET_DURATIONS_VALUE: draft.value[action.domainId].value = action.payload || initialSubState().value break case SET_DURATIONS_FETCHING: - draft.value[action.domainId].fetching = action.payload || initialSubState().fetching + draft.fetching = action.payload || initialState().fetching break case SET_DURATIONS_ERROR: - draft.value[action.domainId].error = action.payload || initialSubState().error + draft.error = action.payload || initialState().error break } diff --git a/src/ui/scripts/reducers/filter.js b/src/ui/scripts/reducers/filter.js index b13f10d0..d1607e37 100644 --- a/src/ui/scripts/reducers/filter.js +++ b/src/ui/scripts/reducers/filter.js @@ -1,21 +1,33 @@ import produce from 'immer' import { - SET_FILTER_RANGE + SET_FILTER_SORTING, + SET_FILTER_RANGE, + SET_FILTER_INTERVAL } from '../actions' +import { SORTINGS_TOP } from '../../../constants/sortings' import { RANGES_LAST_7_DAYS } from '../../../constants/ranges' +import { INTERVALS_DAILY } from '../../../constants/intervals' export const initialState = () => ({ - range: RANGES_LAST_7_DAYS + sorting: SORTINGS_TOP, + range: RANGES_LAST_7_DAYS, + interval: INTERVALS_DAILY }) export default produce((draft, action) => { switch (action.type) { + case SET_FILTER_SORTING: + draft.sorting = action.payload + break case SET_FILTER_RANGE: draft.range = action.payload break + case SET_FILTER_INTERVAL: + draft.interval = action.payload + break } }, initialState()) \ No newline at end of file diff --git a/src/ui/scripts/reducers/index.js b/src/ui/scripts/reducers/index.js index eafb0e46..8e17484a 100644 --- a/src/ui/scripts/reducers/index.js +++ b/src/ui/scripts/reducers/index.js @@ -9,6 +9,7 @@ import token from './token' import route from './route' import filter from './filter' import domains from './domains' +import overview from './overview' import views from './views' import pages from './pages' import referrers from './referrers' @@ -25,6 +26,7 @@ const reducers = combineReducers({ route, filter, domains, + overview, views, pages, referrers, diff --git a/src/ui/scripts/reducers/languages.js b/src/ui/scripts/reducers/languages.js index 3e364b3c..3588a19d 100644 --- a/src/ui/scripts/reducers/languages.js +++ b/src/ui/scripts/reducers/languages.js @@ -1,24 +1,17 @@ import produce from 'immer' import { - SET_LANGUAGES_SORTING, SET_LANGUAGES_VALUE, SET_LANGUAGES_FETCHING, SET_LANGUAGES_ERROR } from '../actions' -import { LANGUAGES_SORTING_TOP } from '../../../constants/languages' +import genericState from '../utils/genericState' +import genericSubState from '../utils/genericSubState' -export const initialState = () => ({ - sorting: LANGUAGES_SORTING_TOP, - value: {} -}) +export const initialState = genericState -export const initialSubState = () => ({ - value: [], - fetching: false, - error: undefined -}) +export const initialSubState = genericSubState export default produce((draft, action) => { @@ -28,20 +21,14 @@ export default produce((draft, action) => { if (hasDomainId() === true && hasDomainValue() === false) draft.value[action.domainId] = initialSubState() switch (action.type) { - case SET_LANGUAGES_SORTING: - if (draft.sorting === action.payload) break - // Reset value because the view shouldn't show the old data when switching - draft.value = initialState().value - draft.sorting = action.payload - break case SET_LANGUAGES_VALUE: draft.value[action.domainId].value = action.payload || initialSubState().value break case SET_LANGUAGES_FETCHING: - draft.value[action.domainId].fetching = action.payload || initialSubState().fetching + draft.fetching = action.payload || initialState().fetching break case SET_LANGUAGES_ERROR: - draft.value[action.domainId].error = action.payload || initialSubState().error + draft.error = action.payload || initialState().error break } diff --git a/src/ui/scripts/reducers/overview.js b/src/ui/scripts/reducers/overview.js new file mode 100644 index 00000000..d2bb84b5 --- /dev/null +++ b/src/ui/scripts/reducers/overview.js @@ -0,0 +1,43 @@ +import produce from 'immer' + +import { + SET_OVERVIEW_FACTS, + SET_OVERVIEW_STATISTICS, + SET_OVERVIEW_FETCHING, + SET_OVERVIEW_ERROR +} from '../actions' + +export const initialState = () => ({ + value: {} +}) + +export const initialSubState = () => ({ + facts: {}, + statistics: {}, + fetching: false, + error: undefined +}) + +export default produce((draft, action) => { + + const hasDomainId = () => action.domainId != null + const hasDomainValue = () => draft.value[action.domainId] != null + + if (hasDomainId() === true && hasDomainValue() === false) draft.value[action.domainId] = initialSubState() + + switch (action.type) { + case SET_OVERVIEW_FACTS: + draft.value[action.domainId].facts = action.payload || initialSubState().facts + break + case SET_OVERVIEW_STATISTICS: + draft.value[action.domainId].statistics = action.payload || initialSubState().statistics + break + case SET_OVERVIEW_FETCHING: + draft.value[action.domainId].fetching = action.payload || initialSubState().fetching + break + case SET_OVERVIEW_ERROR: + draft.value[action.domainId].error = action.payload || initialSubState().error + break + } + +}, initialState()) \ No newline at end of file diff --git a/src/ui/scripts/reducers/pages.js b/src/ui/scripts/reducers/pages.js index fd5db0c4..e97c75f7 100644 --- a/src/ui/scripts/reducers/pages.js +++ b/src/ui/scripts/reducers/pages.js @@ -1,24 +1,17 @@ import produce from 'immer' import { - SET_PAGES_SORTING, SET_PAGES_VALUE, SET_PAGES_FETCHING, SET_PAGES_ERROR } from '../actions' -import { PAGES_SORTING_TOP } from '../../../constants/pages' +import genericState from '../utils/genericState' +import genericSubState from '../utils/genericSubState' -export const initialState = () => ({ - sorting: PAGES_SORTING_TOP, - value: {} -}) +export const initialState = genericState -export const initialSubState = () => ({ - value: [], - fetching: false, - error: undefined -}) +export const initialSubState = genericSubState export default produce((draft, action) => { @@ -28,20 +21,14 @@ export default produce((draft, action) => { if (hasDomainId() === true && hasDomainValue() === false) draft.value[action.domainId] = initialSubState() switch (action.type) { - case SET_PAGES_SORTING: - if (draft.sorting === action.payload) break - // Reset value because the view shouldn't show the old data when switching - draft.value = initialState().value - draft.sorting = action.payload - break case SET_PAGES_VALUE: draft.value[action.domainId].value = action.payload || initialSubState().value break case SET_PAGES_FETCHING: - draft.value[action.domainId].fetching = action.payload || initialSubState().fetching + draft.fetching = action.payload || initialState().fetching break case SET_PAGES_ERROR: - draft.value[action.domainId].error = action.payload || initialSubState().error + draft.error = action.payload || initialState().error break } diff --git a/src/ui/scripts/reducers/referrers.js b/src/ui/scripts/reducers/referrers.js index e551afb5..46a68167 100644 --- a/src/ui/scripts/reducers/referrers.js +++ b/src/ui/scripts/reducers/referrers.js @@ -1,24 +1,17 @@ import produce from 'immer' import { - SET_REFERRERS_SORTING, SET_REFERRERS_VALUE, SET_REFERRERS_FETCHING, SET_REFERRERS_ERROR } from '../actions' -import { REFERRERS_SORTING_TOP } from '../../../constants/referrers' +import genericState from '../utils/genericState' +import genericSubState from '../utils/genericSubState' -export const initialState = () => ({ - sorting: REFERRERS_SORTING_TOP, - value: {} -}) +export const initialState = genericState -export const initialSubState = () => ({ - value: [], - fetching: false, - error: undefined -}) +export const initialSubState = genericSubState export default produce((draft, action) => { @@ -28,20 +21,14 @@ export default produce((draft, action) => { if (hasDomainId() === true && hasDomainValue() === false) draft.value[action.domainId] = initialSubState() switch (action.type) { - case SET_REFERRERS_SORTING: - if (draft.sorting === action.payload) break - // Reset value because the view shouldn't show the old data when switching - draft.value = initialState().value - draft.sorting = action.payload - break case SET_REFERRERS_VALUE: draft.value[action.domainId].value = action.payload || initialSubState().value break case SET_REFERRERS_FETCHING: - draft.value[action.domainId].fetching = action.payload || initialSubState().fetching + draft.fetching = action.payload || initialState().fetching break case SET_REFERRERS_ERROR: - draft.value[action.domainId].error = action.payload || initialSubState().error + draft.error = action.payload || initialState().error break } diff --git a/src/ui/scripts/reducers/route.js b/src/ui/scripts/reducers/route.js index b254230e..b318b42c 100644 --- a/src/ui/scripts/reducers/route.js +++ b/src/ui/scripts/reducers/route.js @@ -1,20 +1,22 @@ import produce from 'immer' import { - SET_ROUTE_VALUE + SET_ROUTE } from '../actions' -import { ROUTE_VIEWS } from '../constants/route' +import { ROUTE_OVERVIEW } from '../constants/route' export const initialState = () => ({ - value: ROUTE_VIEWS + key: ROUTE_OVERVIEW.key, + params: {} }) export default produce((draft, action) => { switch (action.type) { - case SET_ROUTE_VALUE: - draft.value = action.payload + case SET_ROUTE: + draft.key = action.key + draft.params = action.params break } diff --git a/src/ui/scripts/reducers/sizes.js b/src/ui/scripts/reducers/sizes.js index 93126d34..e9170def 100644 --- a/src/ui/scripts/reducers/sizes.js +++ b/src/ui/scripts/reducers/sizes.js @@ -8,17 +8,15 @@ import { } from '../actions' import { SIZES_TYPE_BROWSER_RESOLUTION } from '../../../constants/sizes' +import genericState from '../utils/genericState' +import genericSubState from '../utils/genericSubState' export const initialState = () => ({ type: SIZES_TYPE_BROWSER_RESOLUTION, - value: {} + ...genericState() }) -export const initialSubState = () => ({ - value: [], - fetching: false, - error: undefined -}) +export const initialSubState = genericSubState export default produce((draft, action) => { @@ -38,10 +36,10 @@ export default produce((draft, action) => { draft.value[action.domainId].value = action.payload || initialSubState().value break case SET_SIZES_FETCHING: - draft.value[action.domainId].fetching = action.payload || initialSubState().fetching + draft.fetching = action.payload || initialState().fetching break case SET_SIZES_ERROR: - draft.value[action.domainId].error = action.payload || initialSubState().error + draft.error = action.payload || initialState().error break } diff --git a/src/ui/scripts/reducers/systems.js b/src/ui/scripts/reducers/systems.js index 4667cbbf..3ac376c3 100644 --- a/src/ui/scripts/reducers/systems.js +++ b/src/ui/scripts/reducers/systems.js @@ -3,24 +3,20 @@ import produce from 'immer' import { SET_SYSTEMS_ERROR, SET_SYSTEMS_FETCHING, - SET_SYSTEMS_SORTING, SET_SYSTEMS_VALUE, SET_SYSTEMS_TYPE } from '../actions' -import { SYSTEMS_SORTING_TOP, SYSTEMS_TYPE_NO_VERSION } from '../../../constants/systems' +import { SYSTEMS_TYPE_NO_VERSION } from '../../../constants/systems' +import genericState from '../utils/genericState' +import genericSubState from '../utils/genericSubState' export const initialState = () => ({ type: SYSTEMS_TYPE_NO_VERSION, - sorting: SYSTEMS_SORTING_TOP, - value: {} + ...genericState() }) -export const initialSubState = () => ({ - value: [], - fetching: false, - error: undefined -}) +export const initialSubState = genericSubState export default produce((draft, action) => { @@ -36,20 +32,14 @@ export default produce((draft, action) => { draft.value = initialState().value draft.type = action.payload break - case SET_SYSTEMS_SORTING: - if (draft.sorting === action.payload) break - // Reset value because the view shouldn't show the old data when switching - draft.value = initialState().value - draft.sorting = action.payload - break case SET_SYSTEMS_VALUE: draft.value[action.domainId].value = action.payload || initialSubState().value break case SET_SYSTEMS_FETCHING: - draft.value[action.domainId].fetching = action.payload || initialSubState().fetching + draft.fetching = action.payload || initialState().fetching break case SET_SYSTEMS_ERROR: - draft.value[action.domainId].error = action.payload || initialSubState().error + draft.error = action.payload || initialState().error break } diff --git a/src/ui/scripts/reducers/views.js b/src/ui/scripts/reducers/views.js index c89a3a50..220f2c20 100644 --- a/src/ui/scripts/reducers/views.js +++ b/src/ui/scripts/reducers/views.js @@ -2,25 +2,21 @@ import produce from 'immer' import { SET_VIEWS_TYPE, - SET_VIEWS_INTERVAL, SET_VIEWS_VALUE, SET_VIEWS_FETCHING, SET_VIEWS_ERROR } from '../actions' -import { VIEWS_TYPE_UNIQUE, VIEWS_INTERVAL_DAILY } from '../../../constants/views' +import { VIEWS_TYPE_UNIQUE } from '../../../constants/views' +import genericState from '../utils/genericState' +import genericSubState from '../utils/genericSubState' export const initialState = () => ({ type: VIEWS_TYPE_UNIQUE, - interval: VIEWS_INTERVAL_DAILY, - value: {} + ...genericState() }) -export const initialSubState = () => ({ - value: [], - fetching: false, - error: undefined -}) +export const initialSubState = genericSubState export default produce((draft, action) => { @@ -33,17 +29,14 @@ export default produce((draft, action) => { case SET_VIEWS_TYPE: draft.type = action.payload break - case SET_VIEWS_INTERVAL: - draft.interval = action.payload - break case SET_VIEWS_VALUE: draft.value[action.domainId].value = action.payload || initialSubState().value break case SET_VIEWS_FETCHING: - draft.value[action.domainId].fetching = action.payload || initialSubState().fetching + draft.fetching = action.payload || initialState().fetching break case SET_VIEWS_ERROR: - draft.value[action.domainId].error = action.payload || initialSubState().error + draft.error = action.payload || initialState().error break } diff --git a/src/ui/scripts/selectors/selectDomainsValue.js b/src/ui/scripts/selectors/selectDomainsValue.js new file mode 100644 index 00000000..48e0fc26 --- /dev/null +++ b/src/ui/scripts/selectors/selectDomainsValue.js @@ -0,0 +1,7 @@ +export const byIndex = (state, index) => { + return state.domains.value[index] +} + +export const byId = (state, domainId) => { + return state.domains.value.find((domain) => domain.id === domainId) +} \ No newline at end of file diff --git a/src/ui/scripts/selectors/selectOverviewValue.js b/src/ui/scripts/selectors/selectOverviewValue.js new file mode 100644 index 00000000..9415eae5 --- /dev/null +++ b/src/ui/scripts/selectors/selectOverviewValue.js @@ -0,0 +1,12 @@ +import { initialSubState } from '../reducers/overview' +import genericSubState from '../utils/genericSubState' + +export const withoutType = (state, domainId) => { + const value = state.overview.value[domainId] + return value == null ? initialSubState() : value +} + +export const withType = (state, domainId, type) => { + const value = withoutType(state, domainId).statistics[type] + return value == null ? genericSubState().value : value +} \ No newline at end of file diff --git a/src/ui/scripts/utils/HandledError.js b/src/ui/scripts/utils/HandledError.js new file mode 100644 index 00000000..cf71ea92 --- /dev/null +++ b/src/ui/scripts/utils/HandledError.js @@ -0,0 +1,7 @@ +export default class HandledError extends Error { + constructor(message) { + super(message) + this.name = 'HandledError' + this.message = message + } +} \ No newline at end of file diff --git a/src/ui/scripts/utils/api.js b/src/ui/scripts/utils/api.js index d7939f36..fa4da36c 100644 --- a/src/ui/scripts/utils/api.js +++ b/src/ui/scripts/utils/api.js @@ -1,18 +1,25 @@ import timeout from './timeout' +import HandledError from './HandledError' +import userTimeZone from '../../../utils/timeZone' -export default async (url, { props, method, body, signal }) => { +export default async ({ query, variables, props, signal }) => { try { const headers = new Headers() const token = props.token.value.id + headers.append('Content-Type', 'application/json') + headers.append('Time-Zone', userTimeZone) if (token) headers.append('Authorization', `Bearer ${ token }`) - const request = fetch(url, { + const request = fetch('/api', { + method: 'post', headers, - method, - body, + body: JSON.stringify({ + query, + variables + }), signal }) @@ -23,37 +30,27 @@ export default async (url, { props, method, body, signal }) => { throw new Error(text) } - const type = response.headers.get('content-type') + const json = await response.json() - const isEmpty = type == null - const isJSON = isEmpty === false && type.includes('application/json') === true - - if (isEmpty === true) { - return undefined - } - - if (isJSON === true) { - const json = await response.json() - return json.data + if (json.errors != null) { + const message = json.errors[0].message + throw new Error(message) } - throw new Error('Unknown response content-type') + return json.data } catch (err) { console.error(err) - if (err.name === 'AbortError') { - // Request has been canceled => Do nothing - return - } - if (err.message === 'Token invalid') { - // Reset token and show login - props.deleteToken(props) + // Reset state to show login + props.resetState() + throw new HandledError(err.message) } - // Re-throw error so the caller can handle it, too + // Re-throw error so the caller can handle it. + // Make sure to do nothing when a AbortError occurs. throw err } diff --git a/src/ui/scripts/utils/createArray.js b/src/ui/scripts/utils/createArray.js deleted file mode 100644 index 9e761d90..00000000 --- a/src/ui/scripts/utils/createArray.js +++ /dev/null @@ -1 +0,0 @@ -export default (length) => Array(length).fill(undefined) \ No newline at end of file diff --git a/src/ui/scripts/utils/formatDuration.js b/src/ui/scripts/utils/formatDuration.js index 00322977..fce3c9fc 100644 --- a/src/ui/scripts/utils/formatDuration.js +++ b/src/ui/scripts/utils/formatDuration.js @@ -2,6 +2,10 @@ const removeLeadingZero = (str) => str.replace(/^0/, '') const removeTrailingZeros = (str) => str.replace(/(:00:00|:00)$/, '') const cleanZeros = (str) => removeLeadingZero(removeTrailingZeros(str)) +const toString = function() { + return `${ this.value }${ this.unit }` +} + export default (ms) => { const date = new Date(ms) @@ -11,21 +15,21 @@ export default (ms) => { const hasHours = duration.match(/^00:/) == null if (hasMinutes === false) return { - toString: () => `${ cleanZeros(duration.substr(6)) }s`, value: cleanZeros(duration.substr(6)), - unit: 's' + unit: 's', + toString } if (hasHours === false) return { - toString: () => `${ cleanZeros(duration.substr(3)) }m`, value: cleanZeros(duration.substr(3)), - unit: 'm' + unit: 'm', + toString } return { - toString: () => `${ cleanZeros(duration) }h`, value: cleanZeros(duration), - unit: 'h' + unit: 'h', + toString } } \ No newline at end of file diff --git a/src/ui/scripts/utils/formatNumber.js b/src/ui/scripts/utils/formatNumber.js new file mode 100644 index 00000000..93be41c3 --- /dev/null +++ b/src/ui/scripts/utils/formatNumber.js @@ -0,0 +1,11 @@ +import humanNumber from 'human-number' + +export default (num) => { + + const roundedNum = Math.round(num) + const formattedNum = humanNumber(roundedNum, (num) => Number.parseFloat(num).toFixed(1)) + const cleanNum = formattedNum.replace('.0', '') + + return cleanNum + +} \ No newline at end of file diff --git a/src/ui/scripts/utils/genericState.js b/src/ui/scripts/utils/genericState.js new file mode 100644 index 00000000..62776221 --- /dev/null +++ b/src/ui/scripts/utils/genericState.js @@ -0,0 +1,5 @@ +export default () => ({ + value: {}, + fetching: false, + error: undefined +}) \ No newline at end of file diff --git a/src/ui/scripts/utils/genericSubState.js b/src/ui/scripts/utils/genericSubState.js new file mode 100644 index 00000000..6e77c648 --- /dev/null +++ b/src/ui/scripts/utils/genericSubState.js @@ -0,0 +1,3 @@ +export default () => ({ + value: [] +}) \ No newline at end of file diff --git a/src/ui/scripts/utils/isSameRoute.js b/src/ui/scripts/utils/isSameRoute.js new file mode 100644 index 00000000..89b7521a --- /dev/null +++ b/src/ui/scripts/utils/isSameRoute.js @@ -0,0 +1,3 @@ +import isEqual from 'react-fast-compare' + +export default (routeA, routeB) => routeA.key === routeB.key && isEqual(routeA.params || {}, routeB.params || {}) \ No newline at end of file diff --git a/src/ui/scripts/utils/mergeAverageDurations.js b/src/ui/scripts/utils/mergeDurations.js similarity index 64% rename from src/ui/scripts/utils/mergeAverageDurations.js rename to src/ui/scripts/utils/mergeDurations.js index 04134cb0..a7355e96 100644 --- a/src/ui/scripts/utils/mergeAverageDurations.js +++ b/src/ui/scripts/utils/mergeDurations.js @@ -1,6 +1,5 @@ import selectDurationsValue from '../selectors/selectDurationsValue' -import enhanceAverageDurations from '../enhancers/enhanceAverageDurations' -import isDefined from '../../../utils/isDefined' +import enhanceDurations from '../enhancers/enhanceDurations' // Turns the durations of multiple domains into one array of durations export default (state) => { @@ -8,17 +7,14 @@ export default (state) => { // Enhance durations for all domains const enhancedDurations = state.domains.value.map((domain) => { - const duration = selectDurationsValue(state, domain.data.id) + const duration = selectDurationsValue(state, domain.id) - return enhanceAverageDurations(duration.value, 14) + return enhanceDurations(duration.value, 14) }) - // Remove durations of domains that are still loading - const filteredDurations = enhancedDurations.filter(isDefined) - // Merge all durations to one array of durations - const mergedDurations = filteredDurations.reduce((acc, durations) => { + const mergedDurations = enhancedDurations.reduce((acc, durations) => { // Durations is an array. Each item represents the average duration of one day. durations.forEach((duration, index) => { @@ -35,11 +31,11 @@ export default (state) => { }, []) + const totalDomains = enhancedDurations.length + // Convert merged, total durations into average durations return mergedDurations.map((duration) => { - const totalDomains = filteredDurations.length - return duration / totalDomains }) diff --git a/src/ui/scripts/utils/mergeViews.js b/src/ui/scripts/utils/mergeViews.js index 42b4f228..9785b361 100644 --- a/src/ui/scripts/utils/mergeViews.js +++ b/src/ui/scripts/utils/mergeViews.js @@ -1,6 +1,5 @@ import selectViewsValue from '../selectors/selectViewsValue' import enhanceViews from '../enhancers/enhanceViews' -import isDefined from '../../../utils/isDefined' // Turns the views of multiple domains into one array of views export default (state) => { @@ -8,17 +7,14 @@ export default (state) => { // Enhance views for all domains const enhancedViews = state.domains.value.map((domain) => { - const view = selectViewsValue(state, domain.data.id) + const view = selectViewsValue(state, domain.id) - return enhanceViews(view.value, 14, state.views.interval) + return enhanceViews(view.value, 14) }) - // Remove views of domains that are still loading - const filteredViews = enhancedViews.filter(isDefined) - // Merge all views to one array of views - return filteredViews.reduce((acc, views) => { + return enhancedViews.reduce((acc, views) => { // Views is an array. Each item represents the visit count of one day, month or year. views.forEach((view, index) => { diff --git a/src/ui/scripts/utils/minByProp.js b/src/ui/scripts/utils/minByProp.js deleted file mode 100644 index 6721c918..00000000 --- a/src/ui/scripts/utils/minByProp.js +++ /dev/null @@ -1,8 +0,0 @@ -export default (prop) => (acc, obj) => { - - const value = obj[prop] - - if (value < acc) return value - else return acc - -} \ No newline at end of file diff --git a/src/ui/scripts/utils/overviewRoute.js b/src/ui/scripts/utils/overviewRoute.js new file mode 100644 index 00000000..6f000db1 --- /dev/null +++ b/src/ui/scripts/utils/overviewRoute.js @@ -0,0 +1,12 @@ +import { ROUTE_OVERVIEW } from '../constants/route' + +export default (domain) => { + + return { + ...ROUTE_OVERVIEW, + params: { + domainId: domain.id + } + } + +} \ No newline at end of file diff --git a/src/ui/scripts/utils/pluralize.js b/src/ui/scripts/utils/pluralize.js new file mode 100644 index 00000000..d25d1197 --- /dev/null +++ b/src/ui/scripts/utils/pluralize.js @@ -0,0 +1,9 @@ +export default (words, num) => { + + switch (num) { + case 0: return words[0] + case 1: return words[1] + default: return words[2] + } + +} \ No newline at end of file diff --git a/src/ui/scripts/utils/rangeLabel.js b/src/ui/scripts/utils/rangeLabel.js index 32504064..79ac1232 100644 --- a/src/ui/scripts/utils/rangeLabel.js +++ b/src/ui/scripts/utils/rangeLabel.js @@ -6,7 +6,7 @@ export default (range) => { [ranges.RANGES_LAST_24_HOURS]: 'Last 24 hours', [ranges.RANGES_LAST_7_DAYS]: 'Last 7 days', [ranges.RANGES_LAST_30_DAYS]: 'Last 30 days', - [ranges.RANGES_ALL_TIME]: 'All time' + [ranges.RANGES_LAST_6_MONTHS]: 'Last 6 months' })[range] } \ No newline at end of file diff --git a/src/ui/scripts/utils/routeByKey.js b/src/ui/scripts/utils/routeByKey.js new file mode 100644 index 00000000..3c6baaf0 --- /dev/null +++ b/src/ui/scripts/utils/routeByKey.js @@ -0,0 +1,9 @@ +import * as route from '../constants/route' + +export default (key) => { + + const values = Object.values(route) + + return values.find((value) => value.key === key) + +} \ No newline at end of file diff --git a/src/ui/scripts/utils/status.js b/src/ui/scripts/utils/status.js new file mode 100644 index 00000000..d5c44d48 --- /dev/null +++ b/src/ui/scripts/utils/status.js @@ -0,0 +1,13 @@ +export default (entries, loading) => { + + const isEmpty = entries.length === 0 + const isStale = isEmpty === false && loading === true + const isLoading = isEmpty === true && loading === true + + return { + isEmpty, + isStale, + isLoading + } + +} \ No newline at end of file diff --git a/src/ui/scripts/utils/useDidMountEffect.js b/src/ui/scripts/utils/useDidMountEffect.js deleted file mode 100644 index 0e8050a6..00000000 --- a/src/ui/scripts/utils/useDidMountEffect.js +++ /dev/null @@ -1,12 +0,0 @@ -import React, { useEffect, useRef } from 'react' - -export default (fn, deps) => { - - const didMount = useRef(false) - - useEffect(() => { - if (didMount.current === true) fn() - didMount.current = true - }, deps) - -} \ No newline at end of file diff --git a/src/ui/scripts/utils/whenBelow.js b/src/ui/scripts/utils/whenBelow.js new file mode 100644 index 00000000..5fc8e1f2 --- /dev/null +++ b/src/ui/scripts/utils/whenBelow.js @@ -0,0 +1,5 @@ +export default (num, max) => { + + return num < max ? num : undefined + +} \ No newline at end of file diff --git a/src/ui/styles/_card.scss b/src/ui/styles/_card.scss index 0ddbffe0..0e87317e 100644 --- a/src/ui/styles/_card.scss +++ b/src/ui/styles/_card.scss @@ -17,6 +17,7 @@ &__inner { padding: $gutter*1.6 $gutter*1.5 $gutter*1.5; + width: 100%; } &__footer { diff --git a/src/ui/styles/_content.scss b/src/ui/styles/_content.scss index 69bfa7ef..eaeab2f3 100644 --- a/src/ui/styles/_content.scss +++ b/src/ui/styles/_content.scss @@ -1,7 +1,9 @@ .content { + --columns: 2; + display: grid; - grid-template-columns: 1fr 1fr; + grid-template-columns: repeat(var(--columns), minmax(0, 1fr)); gap: $gutter; margin: 0 auto; padding: 6vh $gutter; @@ -9,7 +11,12 @@ max-width: $maxWidth; @media (max-width: 800px) { - grid-template-columns: 1fr; + --columns: 1; + } + + &__spacer { + height: 3vh; + grid-column: 1 / -1; } } \ No newline at end of file diff --git a/src/ui/styles/_context.scss b/src/ui/styles/_context.scss index 669c8b4a..fb21aa0f 100644 --- a/src/ui/styles/_context.scss +++ b/src/ui/styles/_context.scss @@ -5,7 +5,7 @@ top: 0; left: 0; padding: $gutter/2 0; - min-width: 170px; + min-width: 210px; background: rgba($context, .98); border-radius: $radius; transform: translate(var(--x), var(--y)); @@ -35,7 +35,6 @@ &__button { padding: $gutter/3 $gutter*1.2; - padding-right: $gutter*3; color: currentColor; text-align: left; transition: color .3s ease, background .2s ease; @@ -55,7 +54,6 @@ &--floating &__button { margin: 0 $gutter/2; padding: $gutter/2 $gutter/1.6; - padding-right: $gutter*3; color: $white; border-radius: $radius; @@ -64,7 +62,23 @@ } } + &__head { + display: grid; + grid-auto-flow: column; + gap: $gutter; + align-items: center; + justify-content: space-between; + } + + &__label { + max-width: 240px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + &__description { + padding-right: $gutter; font-size: .86em; color: $light; } diff --git a/src/ui/styles/_facts.scss b/src/ui/styles/_facts.scss new file mode 100644 index 00000000..63d1dc4b --- /dev/null +++ b/src/ui/styles/_facts.scss @@ -0,0 +1,30 @@ +.facts { + + --columns: 3; + + grid-column: 1 / -1; + display: grid; + grid-template-columns: repeat(var(--columns), minmax(0, 1fr)); + gap: 1px; + border-radius: $radius; + width: 100%; + overflow: hidden; + + @media (max-width: 900px) { + --columns: 2; + } + + @media (max-width: 560px) { + --columns: 1; + } + + &__card { + display: grid; + align-content: space-between; + gap: $gutter; + background: $card; + padding: $gutter*1.6 $gutter*1.5 $gutter*1.5; + width: 100%; + } + +} \ No newline at end of file diff --git a/src/ui/styles/_header.scss b/src/ui/styles/_header.scss index 0562a7ab..dc784d24 100644 --- a/src/ui/styles/_header.scss +++ b/src/ui/styles/_header.scss @@ -98,6 +98,7 @@ margin: 0 $gutter/2; padding: $gutter/1.5 2px; outline: none; + white-space: nowrap; transition: box-shadow .3s ease; &.hovered, diff --git a/src/ui/styles/_headline.scss b/src/ui/styles/_headline.scss index 8878646f..6ba7eee6 100644 --- a/src/ui/styles/_headline.scss +++ b/src/ui/styles/_headline.scss @@ -1,15 +1,39 @@ .headline { margin: 0 0 $gutter/2; + color: $white; font-weight: 400; font-size: 2.2em; text-rendering: optimizeLegibility; line-height: 1; - &--small { + &--medium { margin: 0 0 $gutter/3; font-size: 1.5em; line-height: 1.2; } + &--small { + margin: 0 0 $gutter/3; + font-size: inherit; + line-height: inherit; + } + + &--no-spacing { + margin-bottom: 0; + } + + &__button { + text-align: left; + max-width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + &__button:focus { + color: $primary; + outline: none; + } + } \ No newline at end of file diff --git a/src/ui/styles/_keyHint.scss b/src/ui/styles/_keyHint.scss new file mode 100644 index 00000000..80e3de69 --- /dev/null +++ b/src/ui/styles/_keyHint.scss @@ -0,0 +1,16 @@ +.keyHint { + + $size: 1.5em; + + display: flex; + align-items: center; + justify-content: center; + width: $size; + height: $size; + font-size: .8em; + background: rgba(255, 255, 255, .05); + border-radius: 3px; + border: 1px solid $tertiary; + color: $light; + +} \ No newline at end of file diff --git a/src/ui/styles/_modal.scss b/src/ui/styles/_modal.scss index be882f6f..bd026f5b 100644 --- a/src/ui/styles/_modal.scss +++ b/src/ui/styles/_modal.scss @@ -12,7 +12,7 @@ background: rgba(darken($black, 6%), .9); pointer-events: none; opacity: 0; - z-index: 1; + z-index: 3; transition: opacity .3s ease; &.visible { diff --git a/src/ui/styles/_updater.scss b/src/ui/styles/_updater.scss new file mode 100644 index 00000000..daad826f --- /dev/null +++ b/src/ui/styles/_updater.scss @@ -0,0 +1,41 @@ +.updater { + + $size: 1em; + + @keyframes updater__zoom { + 0% { + transform: scale(.2); + opacity: 0; + } + 20% { + opacity: .6; + } + 80% { + transform: scale(.9); + opacity: 0; + } + 100% { + transform: scale(.9); + opacity: 0; + } + } + + position: relative; + width: $size; + height: $size; + border-radius: 100%; + background: $context; + + &__circle { + position: absolute; + width: 100%; + height: 100%; + background: $white; + border-radius: inherit; + animation-name: updater__zoom; + animation-iteration-count: infinite; + animation-timing-function: ease; + animation-duration: 2s; + } + +} \ No newline at end of file diff --git a/src/ui/styles/_updating.scss b/src/ui/styles/_updating.scss new file mode 100644 index 00000000..c76e65fa --- /dev/null +++ b/src/ui/styles/_updating.scss @@ -0,0 +1,9 @@ +.updating { + + display: grid; + gap: $gutter/2; + grid-auto-flow: column; + justify-content: start; + align-items: center; + +} \ No newline at end of file diff --git a/src/ui/styles/_valueText.scss b/src/ui/styles/_valueText.scss new file mode 100644 index 00000000..ca4e2569 --- /dev/null +++ b/src/ui/styles/_valueText.scss @@ -0,0 +1,9 @@ +.valueText { + + display: grid; + grid-auto-flow: column; + justify-content: start; + align-items: end; + gap: $gutter/2; + +} \ No newline at end of file diff --git a/src/ui/styles/_valuesBar.scss b/src/ui/styles/_valuesBar.scss deleted file mode 100644 index 1909cbf8..00000000 --- a/src/ui/styles/_valuesBar.scss +++ /dev/null @@ -1,107 +0,0 @@ -.valuesBar { - - display: grid; - grid-template-rows: auto 1em; - gap: $gutter/2; - padding-top: $gutter*1.5; - height: $cardContentHeight; - - &__row { - display: grid; - grid-template-columns: 3em auto; - gap: $gutter/2; - } - - &__bar { - display: flex; - flex-direction: column; - background: $dimmed; - border-radius: $radius; - } - - &__value { - position: relative; - flex-grow: 1; - - &::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: $primary; - border-radius: inherit; - opacity: var(--opacity); - } - - &:hover { - box-shadow: 0 0 0 2px $card, 0 0 0 4px white; - z-index: 1; - } - - &:first-child { - border-top-left-radius: $radius; - border-top-right-radius: $radius; - } - - &:last-child { - border-bottom-left-radius: $radius; - border-bottom-right-radius: $radius; - } - } - - &__inner { - display: flex; - flex-direction: column; - justify-content: space-between; - } - - &__line { - position: relative; - width: 100%; - height: 1px; - background: $dimmed; - } - - &__anchor { - position: absolute; - padding: $gutter/2 0; - font-size: .8em; - right: 0; - - &--top { - bottom: 0; - } - - &--bottom { - top: 0; - } - } - - &__content { - margin-left: $gutter*1.5; - } - - &__duration { - margin: 0; - font-size: 1.8em; - text-rendering: optimizeLegibility; - line-height: 1.1; - } - - &__decorator { - font-size: .7em; - margin-right: 4px; - } - - &__unit { - font-size: .7em; - margin-left: 2px; - } - - &__description { - margin: 0; - } - -} \ No newline at end of file diff --git a/src/ui/styles/index.scss b/src/ui/styles/index.scss index e832ce7b..c37688d4 100644 --- a/src/ui/styles/index.scss +++ b/src/ui/styles/index.scss @@ -19,6 +19,7 @@ @import 'main'; @import 'card'; @import 'spinner'; +@import 'updater'; @import 'message'; @import 'header'; @import 'content'; @@ -27,11 +28,14 @@ @import 'linkItem'; @import 'flexList'; @import 'emptyState'; +@import 'valueText'; @import 'favicon'; @import 'modal'; -@import 'valuesBar'; @import 'context'; @import 'filter'; +@import 'keyHint'; +@import 'updating'; +@import 'facts'; // Helpers ----------------------------------------------------- // @import 'align'; diff --git a/src/utils/KnownError.js b/src/utils/KnownError.js new file mode 100644 index 00000000..1921ab3a --- /dev/null +++ b/src/utils/KnownError.js @@ -0,0 +1,7 @@ +module.exports = class KnownError extends Error { + constructor(message) { + super(message) + this.name = 'KnownError' + this.message = message + } +} \ No newline at end of file diff --git a/src/utils/bestMatch.js b/src/utils/bestMatch.js new file mode 100644 index 00000000..bce3de0a --- /dev/null +++ b/src/utils/bestMatch.js @@ -0,0 +1,12 @@ +'use strict' + +const isDefined = require('./isDefined') + +module.exports = (matches) => { + + // Find the first item that only consists if defined values + return matches.reduce((prev, [ key, values ]) => { + return values.every(isDefined) === true && prev == null ? key : prev + }, undefined) + +} \ No newline at end of file diff --git a/src/utils/createArray.js b/src/utils/createArray.js new file mode 100644 index 00000000..6f4a5086 --- /dev/null +++ b/src/utils/createArray.js @@ -0,0 +1,3 @@ +'use strict' + +module.exports = (length) => Array(length).fill(undefined) \ No newline at end of file diff --git a/src/utils/createDate.js b/src/utils/createDate.js new file mode 100644 index 00000000..f8eb996c --- /dev/null +++ b/src/utils/createDate.js @@ -0,0 +1,35 @@ +'use strict' + +const { subMilliseconds, subHours, subDays, subMonths, subYears, startOfDay, startOfMonth, startOfYear } = require('date-fns') +const serverTimeZone = require('./timeZone') + +module.exports = (userTimeZone = serverTimeZone) => { + + const currentDate = new Date() + + // This is the biggest, positive timezone offset possible (starting from UTC). + // We should always additionally include this amount of hours when selecting data, + // when data is grouped by day, month or year. This ensures that we don't exclude + // relevant data. E.g. if you're GMT+2 and we only include the data of the current + // day, than we will miss 2 hours of data. This is also the case in the other + // direction. GMT-2 will include 2 hours more data, but that's not a problem, + // because the data will be removed from the output when enhancing the data. + // We could also use the real offset of userTimeZone, but that would only make + // things more complicated. The max offset does the job. + const timeZoneToleranz = 14 + + return { + userTimeZone, + // Get a date with an offset + lastMilliseconds: (milliseconds) => subMilliseconds(currentDate, milliseconds), + lastHours: (hours) => subHours(currentDate, hours), + lastDays: (days) => subDays(currentDate, days), + lastMonths: (months) => subMonths(currentDate, months), + lastYears: (years) => subYears(currentDate, years), + // Get a date with an offset that always includes the whole unit of the given interval and a timezone toleranz + includeDays: (days) => subHours(subDays(startOfDay(currentDate), days - 1), timeZoneToleranz), + includeMonths: (months) => subHours(subMonths(startOfMonth(currentDate), months - 1), timeZoneToleranz), + includeYears: (years) => subHours(subYears(startOfYear(currentDate), years - 1), timeZoneToleranz) + } + +} \ No newline at end of file diff --git a/src/utils/domainIds.js b/src/utils/domainIds.js new file mode 100644 index 00000000..28971180 --- /dev/null +++ b/src/utils/domainIds.js @@ -0,0 +1,19 @@ +const debouncePromise = require('debounce-promise') + +const domains = require('../database/domains') + +// A zero timeout is enough to ensure that this task +// runs only once on every API call. It's a task that would +// otherwise execute multiple times. +const loadDomains = debouncePromise(domains.all, 0) + +module.exports = async (domain) => { + + if (domain.id == null) { + const allDomains = await loadDomains() + return allDomains.map((domain) => domain.id) + } + + return [ domain.id ] + +} \ No newline at end of file diff --git a/src/utils/fillDatabase.js b/src/utils/fillDatabase.js index f991b437..0f2cda96 100644 --- a/src/utils/fillDatabase.js +++ b/src/utils/fillDatabase.js @@ -203,62 +203,107 @@ const createRecord = () => { } -const addToken = async (url) => { +const addToken = async (endpoint) => { - const response = await fetch(`${ url }/tokens`, { + const response = await fetch(endpoint, { method: 'post', body: JSON.stringify({ - username: process.env.ACKEE_USERNAME, - password: process.env.ACKEE_PASSWORD + query: ` + mutation createToken($input: CreateTokenInput!) { + createToken(input: $input) { + payload { + id + } + } + } + `, + variables: { + input: { + username: process.env.ACKEE_USERNAME, + password: process.env.ACKEE_PASSWORD + } + } }) }) const data = await response.json() - return data.data.id + return data.data.createToken.payload } -const fetchDomains = async (url, token) => { +const fetchDomains = async (endpoint, headers) => { - const headers = new Headers({ - Authorization: `Bearer ${ token }` - }) - - const response = await fetch(`${ url }/domains`, { - headers + const response = await fetch(endpoint, { + method: 'post', + headers, + body: JSON.stringify({ + query: ` + query fetchDomains { + domains { + id + } + } + ` + }) }) const data = await response.json() - return data.data + return data.data.domains } -const addRecord = async (url, headers, domain, record) => { +const addRecord = async (endpoint, headers, domain, record) => { - const response = await fetch(`${ url }/domains/${ domain.id }/records`, { + const response = await fetch(endpoint, { method: 'post', headers, - body: JSON.stringify(record) + body: JSON.stringify({ + query: ` + mutation createRecord($domainId: ID!, $input: CreateRecordInput!) { + createRecord(domainId: $domainId, input: $input) { + payload { + id + } + } + } + `, + variables: { + domainId: domain.id, + input: record + } + }) }) const data = await response.json() - return data.data + return data.data.createRecord.payload } -const updateRecord = async (url, headers, domain, record) => { +const updateRecord = async (endpoint, headers, record) => { - const response = await fetch(`${ url }/domains/${ domain.id }/records/${ record.id }`, { - method: 'patch', - headers + const response = await fetch(endpoint, { + method: 'post', + headers, + body: JSON.stringify({ + query: ` + mutation updateRecord($id: ID!) { + updateRecord(id: $id) { + success + } + } + `, + variables: { + id: record.id + } + }) }) const data = await response.json() - return data.data + return data.data.updateRecord.success } @@ -266,27 +311,29 @@ const job = (url) => async () => { try { + const endpoint = `${ url }/api` + const currentDate = new Date() const currentWeekday = currentDate.getDay() const updateDelay = randomInt(0, hour * 1.5) - const token = await addToken(url) - const domains = await fetchDomains(url, token) - - const domain = randomItem([ ...domains, ...weekdayDuds[currentWeekday] ]) - const record = createRecord() + const token = await addToken(endpoint) const headers = new Headers({ - 'Authorization': `Bearer ${ token }`, + 'Authorization': `Bearer ${ token.id }`, 'User-Agent': randomItem(userAgents) }) + const domains = await fetchDomains(endpoint, headers) + const domain = randomItem([ ...domains, ...weekdayDuds[currentWeekday] ]) + if (domain == null) return - const response = await addRecord(url, headers, domain.data, record) + const record = createRecord() + const response = await addRecord(endpoint, headers, domain, record) await sleep(updateDelay) - await updateRecord(url, headers, domain.data, response) + await updateRecord(endpoint, headers, response) } catch (err) { diff --git a/src/utils/isAuthenticated.js b/src/utils/isAuthenticated.js new file mode 100644 index 00000000..52fc1af8 --- /dev/null +++ b/src/utils/isAuthenticated.js @@ -0,0 +1,38 @@ +'use strict' + +const { Bearer } = require('permit') + +const KnownError = require('../utils/KnownError') +const ttl = require('../utils/ttl') +const tokens = require('../database/tokens') + +const permit = new Bearer({ query: 'token' }) + +module.exports = async (req) => { + + const token = permit.check(req) + + // Token not in request + if (token == null) { + return new KnownError('Token missing') + } + + const entry = await tokens.get(token) + + // Token not in database + if (entry == null) { + return new KnownError('Token invalid') + } + + const valid = ttl(entry.updated, process.env.ACKEE_TTL) + + // Token too old + if (valid === false) { + return new KnownError('Token invalid') + } + + await tokens.update(token) + + return true + +} \ No newline at end of file diff --git a/src/utils/isDemo.js b/src/utils/isDemoMode.js similarity index 100% rename from src/utils/isDemo.js rename to src/utils/isDemoMode.js diff --git a/src/utils/isDevelopmentMode.js b/src/utils/isDevelopmentMode.js new file mode 100644 index 00000000..9b895590 --- /dev/null +++ b/src/utils/isDevelopmentMode.js @@ -0,0 +1,3 @@ +'use strict' + +module.exports = process.env.NODE_ENV === 'development' \ No newline at end of file diff --git a/src/utils/isProductionEnv.js b/src/utils/isProductionEnv.js deleted file mode 100644 index be160ea9..00000000 --- a/src/utils/isProductionEnv.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict' - -module.exports = process.env.NODE_ENV !== 'development' \ No newline at end of file diff --git a/src/ui/scripts/utils/languageCodes.js b/src/utils/languageCodes.js similarity index 99% rename from src/ui/scripts/utils/languageCodes.js rename to src/utils/languageCodes.js index 9ca2ff8e..55ff75bd 100644 --- a/src/ui/scripts/utils/languageCodes.js +++ b/src/utils/languageCodes.js @@ -1,4 +1,6 @@ -export default { +'use strict' + +module.exports = { aa: 'Afar', ab: 'Abkhazian', ae: 'Avestan', diff --git a/src/ui/scripts/utils/matchesDate.js b/src/utils/matchesDate.js similarity index 83% rename from src/ui/scripts/utils/matchesDate.js rename to src/utils/matchesDate.js index c5a8945f..cd492225 100644 --- a/src/ui/scripts/utils/matchesDate.js +++ b/src/utils/matchesDate.js @@ -1,4 +1,4 @@ -export default (day, month, year, date) => { +module.exports = (day, month, year, date) => { const isDay = day === date.getDate() || day == null const isMonth = month === date.getMonth() + 1 || month == null diff --git a/src/utils/offsetByRange.js b/src/utils/offsetByRange.js deleted file mode 100644 index 83eb2734..00000000 --- a/src/utils/offsetByRange.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -const { subDays } = require('date-fns') - -const zeroDate = require('./zeroDate') -const ranges = require('../constants/ranges') - -module.exports = (range) => { - - switch (range) { - case ranges.RANGES_LAST_24_HOURS: - return subDays(zeroDate(), 1) - case ranges.RANGES_LAST_7_DAYS: - return subDays(zeroDate(), 6) - case ranges.RANGES_LAST_30_DAYS: - return subDays(zeroDate(), 29) - default: - return null - } - -} \ No newline at end of file diff --git a/src/utils/runUpdate.js b/src/utils/runUpdate.js deleted file mode 100644 index 841f8505..00000000 --- a/src/utils/runUpdate.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict' - -module.exports = (schema, id, data = {}, props = []) => { - - const _set = {} - - Object.keys(data).forEach((key) => { - - // Check if it's allowed to change key - if (props.includes(key) === false) return - - _set[key] = data[key] - - }) - - return schema.findOneAndUpdate({ - id - }, { - $set: { - ..._set, - updated: Date.now() - } - }, { - new: true - }) - -} \ No newline at end of file diff --git a/src/utils/sortByProp.js b/src/utils/sortByProp.js new file mode 100644 index 00000000..c49a8061 --- /dev/null +++ b/src/utils/sortByProp.js @@ -0,0 +1,10 @@ +'use strict' + +module.exports = (prop) => (a, b) => { + + const _a = a[prop] + const _b = b[prop] + + return _a.localeCompare(_b, 'en', { numeric: true }) + +} \ No newline at end of file diff --git a/src/utils/timeZone.js b/src/utils/timeZone.js new file mode 100644 index 00000000..6e9d094e --- /dev/null +++ b/src/utils/timeZone.js @@ -0,0 +1,3 @@ +'use strict' + +module.exports = (new Intl.DateTimeFormat()).resolvedOptions().timeZone \ No newline at end of file diff --git a/src/utils/zeroDate.js b/src/utils/zeroDate.js deleted file mode 100644 index 5c02daae..00000000 --- a/src/utils/zeroDate.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict' - -module.exports = () => { - - const date = new Date() - - date.setHours(0) - date.setMinutes(0) - date.setSeconds(0) - date.setMilliseconds(0) - - return date - -} \ No newline at end of file diff --git a/test/aggregations/aggregateActiveVisitors.js b/test/aggregations/aggregateActiveVisitors.js new file mode 100644 index 00000000..e1e05f3f --- /dev/null +++ b/test/aggregations/aggregateActiveVisitors.js @@ -0,0 +1,15 @@ +'use strict' + +const test = require('ava') +const uuid = require('uuid').v4 + +const aggregateActiveVisitors = require('../../src/aggregations/aggregateActiveVisitors') +const createDate = require('../../src/utils/createDate') + +test('return aggregation', async (t) => { + + const result = aggregateActiveVisitors(uuid(), createDate()) + + t.true(Array.isArray(result)) + +}) \ No newline at end of file diff --git a/test/aggregations/aggregateDailyViews.js b/test/aggregations/aggregateDailyViews.js deleted file mode 100644 index 089ada7c..00000000 --- a/test/aggregations/aggregateDailyViews.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict' - -const test = require('ava') -const uuid = require('uuid').v4 - -const aggregateDailyViews = require('../../src/aggregations/aggregateDailyViews') - -test('return unique aggregation', async (t) => { - - const result = aggregateDailyViews(uuid(), true) - - t.true(Array.isArray(result)) - -}) - -test('return non-unique aggregation', async (t) => { - - const result = aggregateDailyViews(uuid(), false) - - t.true(Array.isArray(result)) - -}) \ No newline at end of file diff --git a/test/aggregations/aggregateDurations.js b/test/aggregations/aggregateDurations.js new file mode 100644 index 00000000..f26e380a --- /dev/null +++ b/test/aggregations/aggregateDurations.js @@ -0,0 +1,16 @@ +'use strict' + +const test = require('ava') +const uuid = require('uuid').v4 + +const aggregateDurations = require('../../src/aggregations/aggregateDurations') +const intervals = require('../../src/constants/intervals') +const createDate = require('../../src/utils/createDate') + +test('return aggregation', async (t) => { + + const result = aggregateDurations(uuid(), intervals.INTERVALS_DAILY, 14, createDate()) + + t.true(Array.isArray(result)) + +}) \ No newline at end of file diff --git a/test/aggregations/aggregateMonthlyViews.js b/test/aggregations/aggregateMonthlyViews.js deleted file mode 100644 index 80b6c416..00000000 --- a/test/aggregations/aggregateMonthlyViews.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict' - -const test = require('ava') -const uuid = require('uuid').v4 - -const aggregateMonthlyViews = require('../../src/aggregations/aggregateMonthlyViews') - -test('return unique aggregation', async (t) => { - - const result = aggregateMonthlyViews(uuid(), true) - - t.true(Array.isArray(result)) - -}) - -test('return non-unique aggregation', async (t) => { - - const result = aggregateMonthlyViews(uuid(), false) - - t.true(Array.isArray(result)) - -}) \ No newline at end of file diff --git a/test/aggregations/aggregateNewFields.js b/test/aggregations/aggregateNewFields.js index eeb91229..70888db0 100644 --- a/test/aggregations/aggregateNewFields.js +++ b/test/aggregations/aggregateNewFields.js @@ -5,9 +5,9 @@ const uuid = require('uuid').v4 const aggregateNewFields = require('../../src/aggregations/aggregateNewFields') -test('return array', async (t) => { +test('return aggregation', async (t) => { - const result = aggregateNewFields(uuid(), 'siteReferrer') + const result = aggregateNewFields(uuid(), [ 'siteReferrer' ]) t.true(Array.isArray(result)) diff --git a/test/aggregations/aggregateRecentFields.js b/test/aggregations/aggregateRecentFields.js index 19571b25..82887c35 100644 --- a/test/aggregations/aggregateRecentFields.js +++ b/test/aggregations/aggregateRecentFields.js @@ -5,9 +5,9 @@ const uuid = require('uuid').v4 const aggregateRecentFields = require('../../src/aggregations/aggregateRecentFields') -test('return array', async (t) => { +test('return aggregation', async (t) => { - const result = aggregateRecentFields(uuid(), 'siteReferrer') + const result = aggregateRecentFields(uuid(), [ 'osName', 'osVersion' ]) t.true(Array.isArray(result)) diff --git a/test/aggregations/aggregateRecentFieldsMultiple.js b/test/aggregations/aggregateRecentFieldsMultiple.js deleted file mode 100644 index f2307088..00000000 --- a/test/aggregations/aggregateRecentFieldsMultiple.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict' - -const test = require('ava') -const uuid = require('uuid').v4 - -const aggregateRecentFieldsMultiple = require('../../src/aggregations/aggregateRecentFieldsMultiple') - -test('return array', async (t) => { - - const result = aggregateRecentFieldsMultiple(uuid(), [ 'osName', 'osVersion' ]) - - t.true(Array.isArray(result)) - -}) \ No newline at end of file diff --git a/test/aggregations/aggregateTopFields.js b/test/aggregations/aggregateTopFields.js index f526bb23..58441770 100644 --- a/test/aggregations/aggregateTopFields.js +++ b/test/aggregations/aggregateTopFields.js @@ -4,10 +4,11 @@ const test = require('ava') const uuid = require('uuid').v4 const aggregateTopFields = require('../../src/aggregations/aggregateTopFields') +const createDate = require('../../src/utils/createDate') -test('return array', async (t) => { +test('return aggregation', async (t) => { - const result = aggregateTopFields(uuid(), 'siteReferrer') + const result = aggregateTopFields(uuid(), [ 'osName', 'osVersion' ], createDate()) t.true(Array.isArray(result)) diff --git a/test/aggregations/aggregateTopFieldsMultiple.js b/test/aggregations/aggregateTopFieldsMultiple.js deleted file mode 100644 index b392f858..00000000 --- a/test/aggregations/aggregateTopFieldsMultiple.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict' - -const test = require('ava') -const uuid = require('uuid').v4 - -const aggregateTopFieldsMultiple = require('../../src/aggregations/aggregateTopFieldsMultiple') - -test('return array', async (t) => { - - const result = aggregateTopFieldsMultiple(uuid(), [ 'osName', 'osVersion' ]) - - t.true(Array.isArray(result)) - -}) \ No newline at end of file diff --git a/test/aggregations/aggregateViews.js b/test/aggregations/aggregateViews.js new file mode 100644 index 00000000..35d79a62 --- /dev/null +++ b/test/aggregations/aggregateViews.js @@ -0,0 +1,24 @@ +'use strict' + +const test = require('ava') +const uuid = require('uuid').v4 + +const aggregateViews = require('../../src/aggregations/aggregateViews') +const intervals = require('../../src/constants/intervals') +const createDate = require('../../src/utils/createDate') + +test('return unique aggregation', async (t) => { + + const result = aggregateViews(uuid(), true, intervals.INTERVALS_DAILY, 14, createDate()) + + t.true(Array.isArray(result)) + +}) + +test('return non-unique aggregation', async (t) => { + + const result = aggregateViews(uuid(), false, intervals.INTERVALS_DAILY, 14, createDate()) + + t.true(Array.isArray(result)) + +}) \ No newline at end of file diff --git a/test/aggregations/aggregateYearlyViews.js b/test/aggregations/aggregateYearlyViews.js deleted file mode 100644 index abf2a7d3..00000000 --- a/test/aggregations/aggregateYearlyViews.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict' - -const test = require('ava') -const uuid = require('uuid').v4 - -const aggregateYearlyViews = require('../../src/aggregations/aggregateYearlyViews') - -test('return unique aggregation', async (t) => { - - const result = aggregateYearlyViews(uuid(), true) - - t.true(Array.isArray(result)) - -}) - -test('return non-unique aggregation', async (t) => { - - const result = aggregateYearlyViews(uuid(), false) - - t.true(Array.isArray(result)) - -}) \ No newline at end of file diff --git a/test/constants/browsers.js b/test/constants/browsers.js new file mode 100644 index 00000000..d06dfa55 --- /dev/null +++ b/test/constants/browsers.js @@ -0,0 +1,11 @@ +'use strict' + +const test = require('ava') + +const browsers = require('../../src/constants/browsers') + +test('is an object', async (t) => { + + t.is(typeof browsers, 'object') + +}) \ No newline at end of file diff --git a/test/constants/devices.js b/test/constants/devices.js new file mode 100644 index 00000000..f39ca2f2 --- /dev/null +++ b/test/constants/devices.js @@ -0,0 +1,11 @@ +'use strict' + +const test = require('ava') + +const devices = require('../../src/constants/devices') + +test('is an object', async (t) => { + + t.is(typeof devices, 'object') + +}) \ No newline at end of file diff --git a/test/constants/intervals.js b/test/constants/intervals.js new file mode 100644 index 00000000..49a95779 --- /dev/null +++ b/test/constants/intervals.js @@ -0,0 +1,11 @@ +'use strict' + +const test = require('ava') + +const intervals = require('../../src/constants/intervals') + +test('is an object', async (t) => { + + t.is(typeof intervals, 'object') + +}) \ No newline at end of file diff --git a/test/constants/languages.js b/test/constants/languages.js deleted file mode 100644 index 4d07af49..00000000 --- a/test/constants/languages.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict' - -const test = require('ava') - -const languages = require('../../src/constants/languages') - -test('is an object', async (t) => { - - t.is(typeof languages, 'object') - -}) \ No newline at end of file diff --git a/test/constants/pages.js b/test/constants/pages.js deleted file mode 100644 index da06e1e1..00000000 --- a/test/constants/pages.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict' - -const test = require('ava') - -const pages = require('../../src/constants/pages') - -test('is an object', async (t) => { - - t.is(typeof pages, 'object') - -}) \ No newline at end of file diff --git a/test/constants/ranges.js b/test/constants/ranges.js new file mode 100644 index 00000000..a8856608 --- /dev/null +++ b/test/constants/ranges.js @@ -0,0 +1,11 @@ +'use strict' + +const test = require('ava') + +const ranges = require('../../src/constants/ranges') + +test('is an object', async (t) => { + + t.true(typeof ranges === 'object') + +}) \ No newline at end of file diff --git a/test/constants/referrers.js b/test/constants/referrers.js deleted file mode 100644 index 83ab3dbc..00000000 --- a/test/constants/referrers.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict' - -const test = require('ava') - -const referrers = require('../../src/constants/referrers') - -test('is an object', async (t) => { - - t.true(typeof referrers === 'object') - -}) \ No newline at end of file diff --git a/test/constants/sortings.js b/test/constants/sortings.js new file mode 100644 index 00000000..00ade84d --- /dev/null +++ b/test/constants/sortings.js @@ -0,0 +1,11 @@ +'use strict' + +const test = require('ava') + +const sortings = require('../../src/constants/sortings') + +test('is an object', async (t) => { + + t.is(typeof sortings, 'object') + +}) \ No newline at end of file diff --git a/test/utils/createArray.js b/test/utils/createArray.js new file mode 100644 index 00000000..807ecfd5 --- /dev/null +++ b/test/utils/createArray.js @@ -0,0 +1,15 @@ +'use strict' + +const test = require('ava') + +const createArray = require('../../src/utils/createArray') + +test('return boolean', async (t) => { + + const length = 4 + const result = createArray(length) + + t.true(Array.isArray(result)) + t.is(result.length, length) + +}) \ No newline at end of file diff --git a/test/utils/isDemo.js b/test/utils/isDemo.js deleted file mode 100644 index 7e92519d..00000000 --- a/test/utils/isDemo.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict' - -const test = require('ava') - -const isDemo = require('../../src/utils/isDemo') - -test('return boolean', async (t) => { - - t.is(typeof isDemo, 'boolean') - -}) \ No newline at end of file diff --git a/test/utils/isDemoMode.js b/test/utils/isDemoMode.js new file mode 100644 index 00000000..96ec7b68 --- /dev/null +++ b/test/utils/isDemoMode.js @@ -0,0 +1,11 @@ +'use strict' + +const test = require('ava') + +const isDemoMode = require('../../src/utils/isDemoMode') + +test('return boolean', async (t) => { + + t.is(typeof isDemoMode, 'boolean') + +}) \ No newline at end of file diff --git a/test/utils/isDevelopmentMode.js b/test/utils/isDevelopmentMode.js new file mode 100644 index 00000000..584059a5 --- /dev/null +++ b/test/utils/isDevelopmentMode.js @@ -0,0 +1,11 @@ +'use strict' + +const test = require('ava') + +const isDevelopmentMode = require('../../src/utils/isDevelopmentMode') + +test('return boolean', async (t) => { + + t.is(typeof isDevelopmentMode, 'boolean') + +}) \ No newline at end of file diff --git a/test/utils/isProductionEnv.js b/test/utils/isProductionEnv.js deleted file mode 100644 index f12e5c1f..00000000 --- a/test/utils/isProductionEnv.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict' - -const test = require('ava') - -const isProductionEnv = require('../../src/utils/isProductionEnv') - -test('return boolean', async (t) => { - - t.is(typeof isProductionEnv, 'boolean') - -}) \ No newline at end of file diff --git a/test/utils/offsetByRange.js b/test/utils/offsetByRange.js deleted file mode 100644 index 34a2caa7..00000000 --- a/test/utils/offsetByRange.js +++ /dev/null @@ -1,54 +0,0 @@ -'use strict' - -const test = require('ava') - -const { subDays } = require('date-fns') - -const ranges = require('../../src/constants/ranges') -const zeroDate = require('../../src/utils/zeroDate') -const offsetByRange = require('../../src/utils/offsetByRange') - -test('return correct offset for RANGES_LAST_24_HOURS', async (t) => { - - const result = offsetByRange(ranges.RANGES_LAST_24_HOURS) - - t.deepEqual(result, subDays(zeroDate(), 1)) - -}) - -test('return correct offset for RANGES_LAST_7_DAYS', async (t) => { - - const result = offsetByRange(ranges.RANGES_LAST_7_DAYS) - - t.deepEqual(result, subDays(zeroDate(), 6)) - -}) - -test('return correct offset for RANGES_LAST_30_DAYS', async (t) => { - - const result = offsetByRange(ranges.RANGES_LAST_30_DAYS) - - t.deepEqual(result, subDays(zeroDate(), 29)) - -}) - -test('return null for RANGES_ALL_TIME', async (t) => { - - const result = offsetByRange(ranges.RANGES_ALL_TIME) - - t.is(result, null) - -}) - - -test('return null for other values', async (t) => { - - const resultString = offsetByRange('test') - const resultNull = offsetByRange(null) - const resultUndefined = offsetByRange(undefined) - - t.is(resultString, null) - t.is(resultNull, null) - t.is(resultUndefined, null) - -}) \ No newline at end of file diff --git a/test/utils/runUpdate.js b/test/utils/runUpdate.js deleted file mode 100644 index 83920d25..00000000 --- a/test/utils/runUpdate.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict' - -const test = require('ava') -const uuid = require('uuid').v4 - -const runUpdate = require('../../src/utils/runUpdate') - -test('set `updated` by default', (t) => { - - const schema = { - findOneAndUpdate: (filter, update, opts) => { - - t.deepEqual(filter, { id }) - t.deepEqual(Object.keys(update.$set), [ 'updated' ]) - t.deepEqual(opts, { new: true }) - - } - } - - const id = uuid() - - runUpdate(schema, id) - -}) - -test('update allowed data', (t) => { - - const schema = { - findOneAndUpdate: (filter, update) => { - - t.deepEqual(Object.keys(update.$set), [ ...props, 'updated' ]) - - } - } - - const id = uuid() - const data = { allowed: uuid(), disallowed: uuid() } - const props = [ 'allowed' ] - - runUpdate(schema, id, data, props) - -}) - -test('ignore unavailable props', (t) => { - - const schema = { - findOneAndUpdate: (filter, update) => { - - t.deepEqual(Object.keys(update.$set), [ 'updated' ]) - - } - } - - const id = uuid() - const data = {} - const props = [ 'unavailable' ] - - runUpdate(schema, id, data, props) - -}) \ No newline at end of file diff --git a/test/utils/timeZone.js b/test/utils/timeZone.js new file mode 100644 index 00000000..628e8329 --- /dev/null +++ b/test/utils/timeZone.js @@ -0,0 +1,12 @@ +'use strict' + +const test = require('ava') + +const timeZone = require('../../src/utils/timeZone') + +test('returns timeZone', (t) => { + + new Intl.DateTimeFormat(undefined, { timeZone }) + t.pass() + +}) \ No newline at end of file diff --git a/test/utils/zeroDate.js b/test/utils/zeroDate.js deleted file mode 100644 index 1b5fd515..00000000 --- a/test/utils/zeroDate.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' - -const test = require('ava') - -const zeroDate = require('../../src/utils/zeroDate') - -test('return date without hours, minutes, seconds and milliseconds', async (t) => { - - const date = zeroDate() - - t.is(date.getHours(), 0) - t.is(date.getMinutes(), 0) - t.is(date.getSeconds(), 0) - t.is(date.getMilliseconds(), 0) - -}) \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 3420c40e..f3a97f3e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,482 +2,473 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" - integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== +"@apollo/client@^3.0.2": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.1.1.tgz#7d57d037be8ee93694fbf82579f703e635c836c1" + integrity sha512-c5DxrU81p0B5BsyBXm+5uPJqLCX2epnBsd87PXfRwzDLbp/NiqnWp6a6c5vT5EV2LwJuCq1movmKthoy0gFb0w== dependencies: - "@babel/highlight" "^7.8.3" + "@types/zen-observable" "^0.8.0" + "@wry/context" "^0.5.2" + "@wry/equality" "^0.2.0" + fast-json-stable-stringify "^2.0.0" + graphql-tag "^2.11.0" + hoist-non-react-statics "^3.3.2" + optimism "^0.12.1" + prop-types "^15.7.2" + symbol-observable "^1.2.0" + ts-invariant "^0.4.4" + tslib "^1.10.0" + zen-observable "^0.8.14" -"@babel/compat-data@^7.8.4": - version "7.8.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.8.5.tgz#d28ce872778c23551cbb9432fc68d28495b613b9" - integrity sha512-jWYUqQX/ObOhG1UiEkbH5SANsE/8oKXiQWjj7p7xgj9Zmnt//aUvyz4dBkK0HNsS8/cbyC5NmmH87VekW+mXFg== +"@apollo/protobufjs@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.0.4.tgz#cf01747a55359066341f31b5ce8db17df44244e0" + integrity sha512-EE3zx+/D/wur/JiLp6VCiw1iYdyy1lCJMf8CGPkLeDt5QJrN4N8tKFx33Ah4V30AUQzMk7Uz4IXKZ1LOj124gA== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.0" + "@types/node" "^10.1.0" + long "^4.0.0" + +"@apollographql/apollo-tools@^0.4.3": + version "0.4.8" + resolved "https://registry.yarnpkg.com/@apollographql/apollo-tools/-/apollo-tools-0.4.8.tgz#d81da89ee880c2345eb86bddb92b35291f6135ed" + integrity sha512-W2+HB8Y7ifowcf3YyPHgDI05izyRtOeZ4MqIr7LbTArtmJ0ZHULWpn84SGMW7NAvTV1tFExpHlveHhnXuJfuGA== + dependencies: + apollo-env "^0.6.5" + +"@apollographql/graphql-playground-html@1.6.26": + version "1.6.26" + resolved "https://registry.yarnpkg.com/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz#2f7b610392e2a872722912fc342b43cf8d641cb3" + integrity sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ== + dependencies: + xss "^1.0.6" + +"@ardatan/aggregate-error@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@ardatan/aggregate-error/-/aggregate-error-0.0.1.tgz#1403ac5de10d8ca689fc1f65844c27179ae1d44f" + integrity sha512-UQ9BequOTIavs0pTHLMwQwKQF8tTV1oezY/H2O9chA+JNPFZSua55xpU5dPSjAU9/jLJ1VwU+HJuTVN8u7S6Fg== + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== dependencies: - browserslist "^4.8.5" - invariant "^2.2.4" - semver "^5.5.0" + "@babel/highlight" "^7.10.4" -"@babel/compat-data@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.6.tgz#3f604c40e420131affe6f2c8052e9a275ae2049b" - integrity sha512-5QPTrNen2bm7RBc7dsOmcA5hbrS4O2Vhmk5XOL4zWW/zD/hV0iinpefDlkm+tBBy8kDtFaaeEvmAqt+nURAV2g== +"@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" + integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== dependencies: - browserslist "^4.11.1" + browserslist "^4.12.0" invariant "^2.2.4" semver "^5.5.0" -"@babel/core@^7.7.5", "@babel/core@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e" - integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.8.4" - "@babel/helpers" "^7.8.4" - "@babel/parser" "^7.8.4" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.4" - "@babel/types" "^7.8.3" +"@babel/core@^7.0.0", "@babel/core@^7.7.5", "@babel/core@^7.8.4": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.0.tgz#73b9c33f1658506887f767c26dae07798b30df76" + integrity sha512-mkLq8nwaXmDtFmRkQ8ED/eA2CnVw4zr7dCztKalZXBvdK5EeNUAesrrwUqjQEzFgomJssayzB0aqlOsP1vGLqg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.11.0" + "@babel/types" "^7.11.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" - json5 "^2.1.0" - lodash "^4.17.13" + json5 "^2.1.2" + lodash "^4.17.19" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.6.tgz#d9aa1f580abf3b2286ef40b6904d390904c63376" - integrity sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.6" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helpers" "^7.9.6" - "@babel/parser" "^7.9.6" - "@babel/template" "^7.8.6" - "@babel/traverse" "^7.9.6" - "@babel/types" "^7.9.6" +"@babel/core@^7.11.1": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" + integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.11.1" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.11.0" + "@babel/types" "^7.11.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" json5 "^2.1.2" - lodash "^4.17.13" + lodash "^4.17.19" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e" - integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA== +"@babel/generator@^7.11.0", "@babel/generator@^7.5.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" + integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.11.0" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" -"@babel/generator@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9" - integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ== +"@babel/helper-annotate-as-pure@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" + integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== dependencies: - "@babel/types" "^7.9.5" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" + "@babel/types" "^7.10.4" -"@babel/generator@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.6.tgz#5408c82ac5de98cda0d77d8124e99fa1f2170a43" - integrity sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== dependencies: - "@babel/types" "^7.9.6" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-annotate-as-pure@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" - integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" - integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-builder-react-jsx@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz#dee98d7d79cc1f003d80b76fe01c7f8945665ff6" - integrity sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ== - dependencies: - "@babel/types" "^7.8.3" - esutils "^2.0.0" - -"@babel/helper-call-delegate@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz#de82619898aa605d409c42be6ffb8d7204579692" - integrity sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A== +"@babel/helper-builder-react-jsx-experimental@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.5.tgz#f35e956a19955ff08c1258e44a515a6d6248646b" + integrity sha512-Buewnx6M4ttG+NLkKyt7baQn7ScC/Td+e99G914fRU8fGIUivDDgVIQeDHFa5e4CRSJQt58WpNHhsAZgtzVhsg== dependencies: - "@babel/helper-hoist-variables" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/types" "^7.10.5" -"@babel/helper-compilation-targets@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.4.tgz#03d7ecd454b7ebe19a254f76617e61770aed2c88" - integrity sha512-3k3BsKMvPp5bjxgMdrFyq0UaEO48HciVrOVF0+lon8pp95cyJ2ujAh0TrBHNMnJGT2rr0iKOJPFFbSqjDyf/Pg== +"@babel/helper-builder-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d" + integrity sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg== dependencies: - "@babel/compat-data" "^7.8.4" - browserslist "^4.8.5" - invariant "^2.2.4" - levenary "^1.1.1" - semver "^5.5.0" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.9.6.tgz#1e05b7ccc9d38d2f8b40b458b380a04dcfadd38a" - integrity sha512-x2Nvu0igO0ejXzx09B/1fGBxY9NXQlBW2kZsSxCJft+KHN8t9XWzIvFxtPHnBOAXpVsdxZKZFbRUC8TsNKajMw== +"@babel/helper-compilation-targets@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" + integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== dependencies: - "@babel/compat-data" "^7.9.6" - browserslist "^4.11.1" + "@babel/compat-data" "^7.10.4" + browserslist "^4.12.0" invariant "^2.2.4" levenary "^1.1.1" semver "^5.5.0" -"@babel/helper-create-regexp-features-plugin@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz#c774268c95ec07ee92476a3862b75cc2839beb79" - integrity sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q== - dependencies: - "@babel/helper-regex" "^7.8.3" - regexpu-core "^4.6.0" - -"@babel/helper-create-regexp-features-plugin@^7.8.8": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" - integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-regex" "^7.8.3" +"@babel/helper-create-class-features-plugin@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" + integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + +"@babel/helper-create-regexp-features-plugin@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" + integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-regex" "^7.10.4" regexpu-core "^4.7.0" -"@babel/helper-define-map@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" - integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/types" "^7.8.3" - lodash "^4.17.13" - -"@babel/helper-explode-assignable-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" - integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== - dependencies: - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-function-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" - integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== - dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-function-name@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" - integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== - dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/types" "^7.9.5" - -"@babel/helper-get-function-arity@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" - integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-hoist-variables@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" - integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-member-expression-to-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" - integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-module-imports@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" - integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-module-transforms@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz#d305e35d02bee720fbc2c3c3623aa0c316c01590" - integrity sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q== - dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-simple-access" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/types" "^7.8.3" - lodash "^4.17.13" - -"@babel/helper-module-transforms@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" - integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== - dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-simple-access" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/template" "^7.8.6" - "@babel/types" "^7.9.0" - lodash "^4.17.13" - -"@babel/helper-optimise-call-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" - integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" - integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== - -"@babel/helper-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" - integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== - dependencies: - lodash "^4.17.13" - -"@babel/helper-remap-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" - integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-wrap-function" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-replace-supers@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz#91192d25f6abbcd41da8a989d4492574fb1530bc" - integrity sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-replace-supers@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" - integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/traverse" "^7.8.6" - "@babel/types" "^7.8.6" - -"@babel/helper-simple-access@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" - integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== - dependencies: - "@babel/template" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-split-export-declaration@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" - integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-validator-identifier@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" - integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== - -"@babel/helper-wrap-function@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" - integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helpers@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73" - integrity sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w== - dependencies: - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.4" - "@babel/types" "^7.8.3" - -"@babel/helpers@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.6.tgz#092c774743471d0bb6c7de3ad465ab3d3486d580" - integrity sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw== - dependencies: - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.9.6" - "@babel/types" "^7.9.6" - -"@babel/highlight@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" - integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== +"@babel/helper-define-map@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" + +"@babel/helper-explode-assignable-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" + integrity sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A== + dependencies: + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-hoist-variables@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" + integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-module-imports@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" + integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/types" "^7.11.0" + lodash "^4.17.19" + +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + +"@babel/helper-regex@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" + integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== + dependencies: + lodash "^4.17.19" + +"@babel/helper-remap-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz#fce8bea4e9690bbe923056ded21e54b4e8b68ed5" + integrity sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-simple-access@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" + integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== + dependencies: + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" + integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + +"@babel/helper-wrap-function@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" + integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helpers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" + integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" chalk "^2.0.0" - esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.7.5", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8" - integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw== +"@babel/parser@7.11.3", "@babel/parser@^7.11.1": + version "7.11.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.3.tgz#9e1eae46738bcd08e23e867bab43e7b95299a8f9" + integrity sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA== -"@babel/parser@^7.8.6", "@babel/parser@^7.9.0": - version "7.9.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" - integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== +"@babel/parser@^7.0.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.0.tgz#a9d7e11aead25d3b422d17b2c6502c8dddef6a5d" + integrity sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw== -"@babel/parser@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7" - integrity sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q== - -"@babel/plugin-proposal-async-generator-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" - integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== +"@babel/plugin-proposal-async-generator-functions@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" + integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" - integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== +"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" + integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-dynamic-import@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" + integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" - integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== +"@babel/plugin-proposal-export-namespace-from@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz#570d883b91031637b3e2958eea3c438e62c05f54" + integrity sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" + integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" - integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== +"@babel/plugin-proposal-logical-assignment-operators@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8" + integrity sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" - integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" + integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz#eb5ae366118ddca67bed583b53d7554cad9951bb" - integrity sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA== +"@babel/plugin-proposal-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" + integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz#7a093586fcb18b08266eb1a7177da671ac575b63" - integrity sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A== +"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" + integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.9.5" + "@babel/plugin-transform-parameters" "^7.10.4" -"@babel/plugin-proposal-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" - integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== +"@babel/plugin-proposal-optional-catch-binding@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" + integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz#ae10b3214cb25f7adb1f3bc87ba42ca10b7e2543" - integrity sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" - integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== +"@babel/plugin-proposal-optional-chaining@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" + integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" - integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== +"@babel/plugin-proposal-private-methods@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" + integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.8" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-unicode-property-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz#b646c3adea5f98800c9ab45105ac34d06cd4a47f" - integrity sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ== +"@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" + integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-async-generators@^7.8.0": version "7.8.4" @@ -486,6 +477,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-class-properties@^7.0.0", "@babel/plugin-syntax-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" + integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" @@ -493,6 +491,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.10.4.tgz#53351dd7ae01995e567d04ce42af1a6e0ba846a6" + integrity sha512-yxQsX1dJixF4qEEdzVbst3SZQ58Nrooz8NV9Z9GL4byTE25BvJgl5lf0RECUf0fh28rZBb/RYTWn/eeKwCMrZQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-json-strings@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" @@ -500,12 +512,19 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz#521b06c83c40480f1e58b4fd33b92eceb1d6ea94" - integrity sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A== +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c" + integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": version "7.8.3" @@ -514,14 +533,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" - integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@^7.8.0": +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== @@ -542,638 +561,458 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" - integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== +"@babel/plugin-syntax-top-level-await@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" + integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-arrow-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" - integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== +"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" + integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" - integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== +"@babel/plugin-transform-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" + integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" -"@babel/plugin-transform-block-scoped-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" - integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== +"@babel/plugin-transform-block-scoped-functions@^7.0.0", "@babel/plugin-transform-block-scoped-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" + integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-block-scoping@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" - integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== +"@babel/plugin-transform-block-scoping@^7.0.0", "@babel/plugin-transform-block-scoping@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.5.tgz#b81b8aafefbfe68f0f65f7ef397b9ece68a6037d" + integrity sha512-6Ycw3hjpQti0qssQcA6AMSFDHeNJ++R6dIMnpRqUjFeBBTmTDPa8zgF90OVfTvAo11mXZTlVUViY1g8ffrURLg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - lodash "^4.17.13" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-classes@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz#46fd7a9d2bb9ea89ce88720477979fe0d71b21b8" - integrity sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w== +"@babel/plugin-transform-classes@^7.0.0", "@babel/plugin-transform-classes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" + integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-define-map" "^7.8.3" - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" globals "^11.1.0" -"@babel/plugin-transform-classes@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c" - integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg== +"@babel/plugin-transform-computed-properties@^7.0.0", "@babel/plugin-transform-computed-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" + integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-define-map" "^7.8.3" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-split-export-declaration" "^7.8.3" - globals "^11.1.0" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-computed-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" - integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== +"@babel/plugin-transform-destructuring@^7.0.0", "@babel/plugin-transform-destructuring@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" + integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-destructuring@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz#20ddfbd9e4676906b1056ee60af88590cc7aaa0b" - integrity sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ== +"@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" + integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-destructuring@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50" - integrity sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q== +"@babel/plugin-transform-duplicate-keys@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" + integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" - integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== +"@babel/plugin-transform-exponentiation-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" + integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-duplicate-keys@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" - integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== +"@babel/plugin-transform-flow-strip-types@^7.0.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.10.4.tgz#c497957f09e86e3df7296271e9eb642876bf7788" + integrity sha512-XTadyuqNst88UWBTdLjM+wEY7BFnY2sYtPyAidfC7M/QaZnSuIZpMvLxqGT7phAcnGyWh/XQFLKcGf04CnvxSQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-flow" "^7.10.4" -"@babel/plugin-transform-exponentiation-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" - integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== +"@babel/plugin-transform-for-of@^7.0.0", "@babel/plugin-transform-for-of@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" + integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-for-of@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz#6fe8eae5d6875086ee185dd0b098a8513783b47d" - integrity sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-for-of@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" - integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-function-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" - integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" - integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== +"@babel/plugin-transform-function-name@^7.0.0", "@babel/plugin-transform-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" + integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-member-expression-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" - integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== +"@babel/plugin-transform-literals@^7.0.0", "@babel/plugin-transform-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" + integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-modules-amd@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz#65606d44616b50225e76f5578f33c568a0b876a5" - integrity sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ== +"@babel/plugin-transform-member-expression-literals@^7.0.0", "@babel/plugin-transform-member-expression-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" + integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== dependencies: - "@babel/helper-module-transforms" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-modules-amd@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.6.tgz#8539ec42c153d12ea3836e0e3ac30d5aae7b258e" - integrity sha512-zoT0kgC3EixAyIAU+9vfaUVKTv9IxBDSabgHoUCBP6FqEJ+iNiN7ip7NBKcYqbfUDfuC2mFCbM7vbu4qJgOnDw== +"@babel/plugin-transform-modules-amd@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" + integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz#df251706ec331bd058a34bdd72613915f82928a5" - integrity sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg== - dependencies: - "@babel/helper-module-transforms" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-simple-access" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-commonjs@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz#64b7474a4279ee588cacd1906695ca721687c277" - integrity sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ== +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" + integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz#d8bbf222c1dbe3661f440f2f00c16e9bb7d0d420" - integrity sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg== - dependencies: - "@babel/helper-hoist-variables" "^7.8.3" - "@babel/helper-module-transforms" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-systemjs@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.6.tgz#207f1461c78a231d5337a92140e52422510d81a4" - integrity sha512-NW5XQuW3N2tTHim8e1b7qGy7s0kZ2OH3m5octc49K1SdAKGxYxeIx7hiIz05kS1R2R+hOWcsr1eYwcGhrdHsrg== +"@babel/plugin-transform-modules-systemjs@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" + integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== dependencies: - "@babel/helper-hoist-variables" "^7.8.3" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz#592d578ce06c52f5b98b02f913d653ffe972661a" - integrity sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw== +"@babel/plugin-transform-modules-umd@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" + integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== dependencies: - "@babel/helper-module-transforms" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-modules-umd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" - integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== +"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" + integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" -"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" - integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - -"@babel/plugin-transform-new-target@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" - integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== +"@babel/plugin-transform-new-target@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" + integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-object-super@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" - integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== +"@babel/plugin-transform-object-super@^7.0.0", "@babel/plugin-transform-object-super@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" + integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" -"@babel/plugin-transform-parameters@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz#1d5155de0b65db0ccf9971165745d3bb990d77d3" - integrity sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA== +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" + integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== dependencies: - "@babel/helper-call-delegate" "^7.8.3" - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-parameters@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795" - integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA== +"@babel/plugin-transform-property-literals@^7.0.0", "@babel/plugin-transform-property-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" + integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-property-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" - integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== +"@babel/plugin-transform-react-display-name@^7.0.0", "@babel/plugin-transform-react-display-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.4.tgz#b5795f4e3e3140419c3611b7a2a3832b9aef328d" + integrity sha512-Zd4X54Mu9SBfPGnEcaGcOrVAYOtjT2on8QZkLKEq1S/tHexG39d9XXGZv19VfRrDjPJzFmPfTAqOQS1pfFOujw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-display-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz#70ded987c91609f78353dd76d2fb2a0bb991e8e5" - integrity sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A== +"@babel/plugin-transform-react-jsx-development@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz#6ec90f244394604623880e15ebc3c34c356258ba" + integrity sha512-RM3ZAd1sU1iQ7rI2dhrZRZGv0aqzNQMbkIUCS1txYpi9wHQ2ZHNjo5TwX+UD6pvFW4AbWqLVYvKy5qJSAyRGjQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx-self@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.8.3.tgz#c4f178b2aa588ecfa8d077ea80d4194ee77ed702" - integrity sha512-01OT7s5oa0XTLf2I8XGsL8+KqV9lx3EZV+jxn/L2LQ97CGKila2YMroTkCEIE0HV/FF7CMSRsIAybopdN9NTdg== +"@babel/plugin-transform-react-jsx-self@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz#cd301a5fed8988c182ed0b9d55e9bd6db0bd9369" + integrity sha512-yOvxY2pDiVJi0axdTWHSMi5T0DILN+H+SaeJeACHKjQLezEzhLx9nEF9xgpBLPtkZsks9cnb5P9iBEi21En3gg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-jsx" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx-source@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz#951e75a8af47f9f120db731be095d2b2c34920e0" - integrity sha512-PLMgdMGuVDtRS/SzjNEQYUT8f4z1xb2BAT54vM1X5efkVuYBf5WyGUMbpmARcfq3NaglIwz08UVQK4HHHbC6ag== +"@babel/plugin-transform-react-jsx-source@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.5.tgz#34f1779117520a779c054f2cdd9680435b9222b4" + integrity sha512-wTeqHVkN1lfPLubRiZH3o73f4rfon42HpgxUSs86Nc+8QIcm/B9s8NNVXu/gwGcOyd7yDib9ikxoDLxJP0UiDA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-jsx" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz#4220349c0390fdefa505365f68c103562ab2fc4a" - integrity sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g== +"@babel/plugin-transform-react-jsx@^7.0.0", "@babel/plugin-transform-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2" + integrity sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A== dependencies: - "@babel/helper-builder-react-jsx" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-jsx" "^7.8.3" + "@babel/helper-builder-react-jsx" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-regenerator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz#b31031e8059c07495bf23614c97f3d9698bc6ec8" - integrity sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA== +"@babel/plugin-transform-react-pure-annotations@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz#3eefbb73db94afbc075f097523e445354a1c6501" + integrity sha512-+njZkqcOuS8RaPakrnR9KvxjoG1ASJWpoIv/doyWngId88JoFlPlISenGXjrVacZUIALGUr6eodRs1vmPnF23A== dependencies: - regenerator-transform "^0.14.0" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-regenerator@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" - integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== +"@babel/plugin-transform-regenerator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" + integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" - integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-shorthand-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" - integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" - integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-sticky-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" - integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-regex" "^7.8.3" - -"@babel/plugin-transform-template-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" - integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-typeof-symbol@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" - integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-unicode-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" - integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/preset-env@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.4.tgz#9dac6df5f423015d3d49b6e9e5fa3413e4a72c4e" - integrity sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w== - dependencies: - "@babel/compat-data" "^7.8.4" - "@babel/helper-compilation-targets" "^7.8.4" - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-proposal-async-generator-functions" "^7.8.3" - "@babel/plugin-proposal-dynamic-import" "^7.8.3" - "@babel/plugin-proposal-json-strings" "^7.8.3" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.8.3" - "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" - "@babel/plugin-proposal-optional-chaining" "^7.8.3" - "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" +"@babel/plugin-transform-reserved-words@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" + integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" + integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" + integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" + +"@babel/plugin-transform-sticky-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" + integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + +"@babel/plugin-transform-template-literals@^7.0.0", "@babel/plugin-transform-template-literals@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" + integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-typeof-symbol@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" + integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-escapes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" + integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" + integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.8.4": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796" + integrity sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg== + dependencies: + "@babel/compat-data" "^7.11.0" + "@babel/helper-compilation-targets" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-async-generator-functions" "^7.10.4" + "@babel/plugin-proposal-class-properties" "^7.10.4" + "@babel/plugin-proposal-dynamic-import" "^7.10.4" + "@babel/plugin-proposal-export-namespace-from" "^7.10.4" + "@babel/plugin-proposal-json-strings" "^7.10.4" + "@babel/plugin-proposal-logical-assignment-operators" "^7.11.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" + "@babel/plugin-proposal-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread" "^7.11.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" + "@babel/plugin-proposal-optional-chaining" "^7.11.0" + "@babel/plugin-proposal-private-methods" "^7.10.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-class-properties" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.8.3" - "@babel/plugin-transform-async-to-generator" "^7.8.3" - "@babel/plugin-transform-block-scoped-functions" "^7.8.3" - "@babel/plugin-transform-block-scoping" "^7.8.3" - "@babel/plugin-transform-classes" "^7.8.3" - "@babel/plugin-transform-computed-properties" "^7.8.3" - "@babel/plugin-transform-destructuring" "^7.8.3" - "@babel/plugin-transform-dotall-regex" "^7.8.3" - "@babel/plugin-transform-duplicate-keys" "^7.8.3" - "@babel/plugin-transform-exponentiation-operator" "^7.8.3" - "@babel/plugin-transform-for-of" "^7.8.4" - "@babel/plugin-transform-function-name" "^7.8.3" - "@babel/plugin-transform-literals" "^7.8.3" - "@babel/plugin-transform-member-expression-literals" "^7.8.3" - "@babel/plugin-transform-modules-amd" "^7.8.3" - "@babel/plugin-transform-modules-commonjs" "^7.8.3" - "@babel/plugin-transform-modules-systemjs" "^7.8.3" - "@babel/plugin-transform-modules-umd" "^7.8.3" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" - "@babel/plugin-transform-new-target" "^7.8.3" - "@babel/plugin-transform-object-super" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.8.4" - "@babel/plugin-transform-property-literals" "^7.8.3" - "@babel/plugin-transform-regenerator" "^7.8.3" - "@babel/plugin-transform-reserved-words" "^7.8.3" - "@babel/plugin-transform-shorthand-properties" "^7.8.3" - "@babel/plugin-transform-spread" "^7.8.3" - "@babel/plugin-transform-sticky-regex" "^7.8.3" - "@babel/plugin-transform-template-literals" "^7.8.3" - "@babel/plugin-transform-typeof-symbol" "^7.8.4" - "@babel/plugin-transform-unicode-regex" "^7.8.3" - "@babel/types" "^7.8.3" - browserslist "^4.8.5" - core-js-compat "^3.6.2" - invariant "^2.2.2" - levenary "^1.1.1" - semver "^5.5.0" - -"@babel/preset-env@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.6.tgz#df063b276c6455ec6fcfc6e53aacc38da9b0aea6" - integrity sha512-0gQJ9RTzO0heXOhzftog+a/WyOuqMrAIugVYxMYf83gh1CQaQDjMtsOpqOwXyDL/5JcWsrCm8l4ju8QC97O7EQ== - dependencies: - "@babel/compat-data" "^7.9.6" - "@babel/helper-compilation-targets" "^7.9.6" - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-proposal-async-generator-functions" "^7.8.3" - "@babel/plugin-proposal-dynamic-import" "^7.8.3" - "@babel/plugin-proposal-json-strings" "^7.8.3" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-proposal-numeric-separator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.9.6" - "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" - "@babel/plugin-proposal-optional-chaining" "^7.9.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-json-strings" "^7.8.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.8.0" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.8.3" - "@babel/plugin-transform-async-to-generator" "^7.8.3" - "@babel/plugin-transform-block-scoped-functions" "^7.8.3" - "@babel/plugin-transform-block-scoping" "^7.8.3" - "@babel/plugin-transform-classes" "^7.9.5" - "@babel/plugin-transform-computed-properties" "^7.8.3" - "@babel/plugin-transform-destructuring" "^7.9.5" - "@babel/plugin-transform-dotall-regex" "^7.8.3" - "@babel/plugin-transform-duplicate-keys" "^7.8.3" - "@babel/plugin-transform-exponentiation-operator" "^7.8.3" - "@babel/plugin-transform-for-of" "^7.9.0" - "@babel/plugin-transform-function-name" "^7.8.3" - "@babel/plugin-transform-literals" "^7.8.3" - "@babel/plugin-transform-member-expression-literals" "^7.8.3" - "@babel/plugin-transform-modules-amd" "^7.9.6" - "@babel/plugin-transform-modules-commonjs" "^7.9.6" - "@babel/plugin-transform-modules-systemjs" "^7.9.6" - "@babel/plugin-transform-modules-umd" "^7.9.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" - "@babel/plugin-transform-new-target" "^7.8.3" - "@babel/plugin-transform-object-super" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.9.5" - "@babel/plugin-transform-property-literals" "^7.8.3" - "@babel/plugin-transform-regenerator" "^7.8.7" - "@babel/plugin-transform-reserved-words" "^7.8.3" - "@babel/plugin-transform-shorthand-properties" "^7.8.3" - "@babel/plugin-transform-spread" "^7.8.3" - "@babel/plugin-transform-sticky-regex" "^7.8.3" - "@babel/plugin-transform-template-literals" "^7.8.3" - "@babel/plugin-transform-typeof-symbol" "^7.8.4" - "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.10.4" + "@babel/plugin-transform-arrow-functions" "^7.10.4" + "@babel/plugin-transform-async-to-generator" "^7.10.4" + "@babel/plugin-transform-block-scoped-functions" "^7.10.4" + "@babel/plugin-transform-block-scoping" "^7.10.4" + "@babel/plugin-transform-classes" "^7.10.4" + "@babel/plugin-transform-computed-properties" "^7.10.4" + "@babel/plugin-transform-destructuring" "^7.10.4" + "@babel/plugin-transform-dotall-regex" "^7.10.4" + "@babel/plugin-transform-duplicate-keys" "^7.10.4" + "@babel/plugin-transform-exponentiation-operator" "^7.10.4" + "@babel/plugin-transform-for-of" "^7.10.4" + "@babel/plugin-transform-function-name" "^7.10.4" + "@babel/plugin-transform-literals" "^7.10.4" + "@babel/plugin-transform-member-expression-literals" "^7.10.4" + "@babel/plugin-transform-modules-amd" "^7.10.4" + "@babel/plugin-transform-modules-commonjs" "^7.10.4" + "@babel/plugin-transform-modules-systemjs" "^7.10.4" + "@babel/plugin-transform-modules-umd" "^7.10.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" + "@babel/plugin-transform-new-target" "^7.10.4" + "@babel/plugin-transform-object-super" "^7.10.4" + "@babel/plugin-transform-parameters" "^7.10.4" + "@babel/plugin-transform-property-literals" "^7.10.4" + "@babel/plugin-transform-regenerator" "^7.10.4" + "@babel/plugin-transform-reserved-words" "^7.10.4" + "@babel/plugin-transform-shorthand-properties" "^7.10.4" + "@babel/plugin-transform-spread" "^7.11.0" + "@babel/plugin-transform-sticky-regex" "^7.10.4" + "@babel/plugin-transform-template-literals" "^7.10.4" + "@babel/plugin-transform-typeof-symbol" "^7.10.4" + "@babel/plugin-transform-unicode-escapes" "^7.10.4" + "@babel/plugin-transform-unicode-regex" "^7.10.4" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.9.6" - browserslist "^4.11.1" + "@babel/types" "^7.11.0" + browserslist "^4.12.0" core-js-compat "^3.6.2" invariant "^2.2.2" levenary "^1.1.1" semver "^5.5.0" "@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/preset-react@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.8.3.tgz#23dc63f1b5b0751283e04252e78cf1d6589273d2" - integrity sha512-9hx0CwZg92jGb7iHYQVgi0tOEHP/kM60CtWJQnmbATSPIQQ2xYzfoCI3EdqAhFBeeJwYMdWQuDUHMsuDbH9hyQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-transform-react-display-name" "^7.8.3" - "@babel/plugin-transform-react-jsx" "^7.8.3" - "@babel/plugin-transform-react-jsx-self" "^7.8.3" - "@babel/plugin-transform-react-jsx-source" "^7.8.3" - -"@babel/runtime-corejs3@^7.8.3": - version "7.9.2" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.9.2.tgz#26fe4aa77e9f1ecef9b776559bbb8e84d34284b7" - integrity sha512-HHxmgxbIzOfFlZ+tdeRKtaxWOMUoCG5Mu3wKeUmOxjYrwb3AAHgnmtCUbPPK11/raIWLIBK250t8E2BPO0p7jA== - dependencies: - core-js-pure "^3.0.0" - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.1.2", "@babel/runtime@^7.5.5": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308" - integrity sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ== - dependencies: - regenerator-runtime "^0.13.2" - -"@babel/runtime@^7.8.4": - version "7.9.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" - integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f" - integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.7.4", "@babel/template@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" - integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ== + version "0.1.3" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" + integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" -"@babel/template@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" - integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== +"@babel/preset-react@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.4.tgz#92e8a66d816f9911d11d4cc935be67adfc82dbcf" + integrity sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-display-name" "^7.10.4" + "@babel/plugin-transform-react-jsx" "^7.10.4" + "@babel/plugin-transform-react-jsx-development" "^7.10.4" + "@babel/plugin-transform-react-jsx-self" "^7.10.4" + "@babel/plugin-transform-react-jsx-source" "^7.10.4" + "@babel/plugin-transform-react-pure-annotations" "^7.10.4" + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.0.tgz#f10245877042a815e07f7e693faff0ae9d3a2aac" + integrity sha512-qArkXsjJq7H+T86WrIFV0Fnu/tNOkZ4cgXmjkzAu3b/58D5mFIO8JH/y77t7C9q0OdDRdh9s7Ue5GasYssxtXw== dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.6" - "@babel/types" "^7.8.6" + regenerator-runtime "^0.13.4" -"@babel/traverse@^7.7.4", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c" - integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.8.4" - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.8.4" - "@babel/types" "^7.8.3" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/traverse@^7.8.6": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2" - integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.5" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.0" - "@babel/types" "^7.9.5" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/traverse@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442" - integrity sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.6" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.6" - "@babel/types" "^7.9.6" +"@babel/template@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/traverse@7.11.0", "@babel/traverse@^7.0.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" + integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.0" + "@babel/types" "^7.11.0" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.4.4", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" - integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg== - dependencies: - "@babel/helper-validator-identifier" "^7.9.5" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@babel/types@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" - integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" + lodash "^4.17.19" -"@babel/types@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" - integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== +"@babel/types@7.11.0", "@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.4.4": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" + integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== dependencies: - "@babel/helper-validator-identifier" "^7.9.5" - lodash "^4.17.13" + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" to-fast-properties "^2.0.0" "@concordance/react@^2.0.0": @@ -1188,13 +1027,236 @@ resolved "https://registry.yarnpkg.com/@electerious/eslint-config/-/eslint-config-1.3.4.tgz#3043608a71bd51c5171b1776fa473b3efe4e964e" integrity sha512-gPvT+tMVWMyJzxW9Qi8xIZgWqSRvY3GWQw7tWJUO3RU05h+csVBrArmO7gSk8SHnfAzmE1OiH8rRI76dMjJixQ== +"@graphql-tools/batch-delegate@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/batch-delegate/-/batch-delegate-6.0.18.tgz#1031e4b025a1d946d4d05016632ca6d893140078" + integrity sha512-g/6aPcPSzusLK8wMF5ZhWaeR1/XRLwBIZsvutiUN7GxX2rP8YIHVnlghKmXjhId0GqaSAd7jMR7VKzbQre7CkQ== + dependencies: + "@graphql-tools/delegate" "6.0.18" + dataloader "2.0.0" + tslib "~2.0.0" + +"@graphql-tools/code-file-loader@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/code-file-loader/-/code-file-loader-6.0.18.tgz#71873bcd3d5d9d7dd4279afd45de8c8c28fdd4a2" + integrity sha512-V13hBezvcNZ+I1hoR+Q7bLH1pCxhZ9Nsn91bX+owhmOvn2W56dAn3RpGdnhoM7v6D6Uo2Zkdtqkaq1Pin4rexA== + dependencies: + "@graphql-tools/graphql-tag-pluck" "6.0.18" + "@graphql-tools/utils" "6.0.18" + fs-extra "9.0.1" + tslib "~2.0.0" + +"@graphql-tools/delegate@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-6.0.18.tgz#093e335e346cd26791222e066a3e5929bc38b79c" + integrity sha512-CmNTD60qcTEZM3bvOV2t3Zdj7veY0zgXXVXNgMC9Fx+D2dNdJFCwXdcPAF0SKqlJoj/alBDSl1U6nqYKT9fQOA== + dependencies: + "@ardatan/aggregate-error" "0.0.1" + "@graphql-tools/schema" "6.0.18" + "@graphql-tools/utils" "6.0.18" + is-promise "4.0.0" + tslib "~2.0.0" + +"@graphql-tools/git-loader@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/git-loader/-/git-loader-6.0.18.tgz#ac0cdc07fbc8549ec2ca08456b2f70d214c3f4ba" + integrity sha512-WR4K10+UtguMaN4/AqcJMRsTRy6Er9xKhehmEDMQTbu4pAICkLXyiSsA3f0jfhGBu6JudrzKD0HiaW6eWrMvVg== + dependencies: + "@graphql-tools/graphql-tag-pluck" "6.0.18" + "@graphql-tools/utils" "6.0.18" + +"@graphql-tools/github-loader@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/github-loader/-/github-loader-6.0.18.tgz#070655daf02f4c8cd316f6cf96ee0c916cece835" + integrity sha512-DqIuTiZvubN+uOtuuUyAJXHlgpsutyIGyNi+v/v9s4WO7oq+cE/Gc4dpmG6G8KHVXP7ngvMIGDDEXj4MGx1vpw== + dependencies: + "@graphql-tools/graphql-tag-pluck" "6.0.18" + "@graphql-tools/utils" "6.0.18" + cross-fetch "3.0.5" + +"@graphql-tools/graphql-file-loader@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-file-loader/-/graphql-file-loader-6.0.18.tgz#f2541c87dd8d41d8e621dd8ae60d2e21733a99b8" + integrity sha512-9EduQkDbLf8aDEalIZFCD3W+WKnkEihBPMq28J0rrnkpxAqSke631AA8wNsXurVlld4KMuPCSTDhttZMP27frA== + dependencies: + "@graphql-tools/import" "6.0.18" + "@graphql-tools/utils" "6.0.18" + fs-extra "9.0.1" + tslib "~2.0.0" + +"@graphql-tools/graphql-tag-pluck@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-6.0.18.tgz#54eee3bae27a1ac81cf24d92c3b1b8a8dff4d801" + integrity sha512-8qutnHQuiPiXSjMHwQGBHQuUA9El5Ful9ib0IdU5028sM239bJHqoYVM37Gf3gQ0QxVlrV9G1dxvuNv2KNmP+A== + dependencies: + "@babel/parser" "7.11.3" + "@babel/traverse" "7.11.0" + "@babel/types" "7.11.0" + "@graphql-tools/utils" "6.0.18" + optionalDependencies: + vue-template-compiler "^2.6.11" + +"@graphql-tools/import@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/import/-/import-6.0.18.tgz#37d434ca2130ee3360446ce3cb0e35d9dc62f68c" + integrity sha512-qGbVJOlC6dy+eu0A+lg5dFAsqYOF4uLxIWbvdGHj+4bkevkfVDuXvd5dvV3PY1f9GRS6c5pCGqOY9MsZmBTGog== + dependencies: + fs-extra "9.0.1" + resolve-from "5.0.0" + +"@graphql-tools/json-file-loader@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/json-file-loader/-/json-file-loader-6.0.18.tgz#e7fd75c9f16d34ba0e8d7b64b69ccf48f32d9f9b" + integrity sha512-a7/jkvZXgJlm2EOExCVT4zaZYXyp+pL1pjA8NWitmLIQwP0lIPzY64st/GvCrkDsO43RTltGCMFb66qPreIWWA== + dependencies: + "@graphql-tools/utils" "6.0.18" + fs-extra "9.0.1" + tslib "~2.0.0" + +"@graphql-tools/links@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/links/-/links-6.0.18.tgz#cc0d0542b98a12ee6a5763462255e9421343509d" + integrity sha512-r1unH0UqlUNT985zGfajhq5iysFDCeHB5I2mu+fdaAoIWQB+1dizUpwVkYarWX+u9W4OSNFrF9Hw8IwzKS+51Q== + dependencies: + "@graphql-tools/utils" "6.0.18" + apollo-link "1.2.14" + apollo-upload-client "14.1.1" + cross-fetch "3.0.5" + form-data "3.0.0" + is-promise "4.0.0" + tslib "~2.0.0" + +"@graphql-tools/load-files@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/load-files/-/load-files-6.0.18.tgz#e5976df1a657f47f22345ae194ba15be362721f8" + integrity sha512-vdYt3sp3Odw+v7VCHo08492MB2NbtHe/AoLWX6zQ9lQrbDBCA4WQTIUVPqUR0FkCLdoLC5es0eS/buruUqdcsw== + dependencies: + fs-extra "9.0.1" + globby "11.0.1" + unixify "1.0.0" + +"@graphql-tools/load@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/load/-/load-6.0.18.tgz#41a71707ff94d20740324fb659aa3fe021772bbe" + integrity sha512-DjaxkruBBRoR4twHOv8kzUp2ZP30s/Gvh92sm/EhxG89BgAXRZq5Ua5OqW/ASFvTa7x3V9PyfKsxTK5N3bOgtA== + dependencies: + "@graphql-tools/merge" "6.0.18" + "@graphql-tools/utils" "6.0.18" + globby "11.0.1" + import-from "3.0.0" + is-glob "4.0.1" + p-limit "3.0.2" + tslib "~2.0.0" + unixify "1.0.0" + valid-url "1.0.9" + +"@graphql-tools/merge@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-6.0.18.tgz#d105e16c6f5f874ddfdba3f3f4a2f676a6d2d04a" + integrity sha512-XAFbqMyXsExnuzgr5+JQC8mxsYp0aGIR0m+GbleQDZSlqDOL2maF5xM3dGOOkguz0Paa7ei/5UfnMXyRU3cW/w== + dependencies: + "@graphql-tools/schema" "6.0.18" + "@graphql-tools/utils" "6.0.18" + tslib "~2.0.0" + +"@graphql-tools/mock@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/mock/-/mock-6.0.18.tgz#f8fb2a34e532813dc4a916671d506a7be14854e2" + integrity sha512-fYQdy72KK80ho9/5VJUAREcFA5V23268Qc6tJLgMZzcjBBHUUmkaW+sh8mMK5xL95uFHBCYVq0sDw9TqsFGNEQ== + dependencies: + "@graphql-tools/schema" "6.0.18" + "@graphql-tools/utils" "6.0.18" + tslib "~2.0.0" + +"@graphql-tools/module-loader@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/module-loader/-/module-loader-6.0.18.tgz#82fee195e4dcfebccd7611be11ee94cdbe65ae9a" + integrity sha512-jI9jWBFILxSMt+dvsdYXv+Yug+Z/0yhaJDvRUDgaf7QPgqyI3DLByb9zcSp3jBgaiwx1TGdWSXKDMxUNGRr7YA== + dependencies: + "@graphql-tools/utils" "6.0.18" + tslib "~2.0.0" + +"@graphql-tools/relay-operation-optimizer@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-6.0.18.tgz#0089d4f222d323aae6d5b266daa5f2bc3689a14e" + integrity sha512-X11M/njvdeGUvER+oJCCFMmnoPPq1Y+W6AXWX8WKeaM4LxdMeYY9mAWfhUyNOX4XZlxUA6zNNH+QwBAyUyZvRA== + dependencies: + "@graphql-tools/utils" "6.0.18" + relay-compiler "10.0.1" + +"@graphql-tools/resolvers-composition@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/resolvers-composition/-/resolvers-composition-6.0.18.tgz#dd2bbfd2604f0584b63dd8d7fffbea5ce442e39e" + integrity sha512-zv3lBCldsWvg5H+yskA48aZt7XdlPJ+R+Y4I0xpM7f/pza+PsnE8pSqJsydi8C/57gC/QdW+AnRrkirn27Essg== + dependencies: + "@graphql-tools/utils" "6.0.18" + lodash "4.17.19" + +"@graphql-tools/schema@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-6.0.18.tgz#243eb370e4cded00767202bbabf0893f65c3f5b9" + integrity sha512-xrScjRX9pTSVxqiSkx7Hn/9rzxLweysINa5Pkirdkv5lJY4e0Db53osur0nG/+SJyUmIN70tUtuhEZq4Ezr/PA== + dependencies: + "@graphql-tools/utils" "6.0.18" + tslib "~2.0.0" + +"@graphql-tools/stitch@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/stitch/-/stitch-6.0.18.tgz#c39d54e8631a22dde92e66a9464d7772586e6a52" + integrity sha512-NZLcanKCH+AZHSAMtTnvNEgU8lZm4RBj7glWsFwQhGILfxkdk5R7MSmpjI7CgHMvG8vICD/RS9ziRINpVbj/oQ== + dependencies: + "@graphql-tools/batch-delegate" "6.0.18" + "@graphql-tools/delegate" "6.0.18" + "@graphql-tools/merge" "6.0.18" + "@graphql-tools/schema" "6.0.18" + "@graphql-tools/utils" "6.0.18" + "@graphql-tools/wrap" "6.0.18" + is-promise "4.0.0" + tslib "~2.0.0" + +"@graphql-tools/url-loader@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/url-loader/-/url-loader-6.0.18.tgz#0eeb4e195bf9d8edda78ad16bd2f05b9869d581a" + integrity sha512-rdKbLYyoiKiirFDIHN5/vpaAKB6Qkjc5j1cRbv7weQn0nIHHhj4ReMBvqSiISyierQ33ix5y4Pvo1VJPD+V4qQ== + dependencies: + "@graphql-tools/delegate" "6.0.18" + "@graphql-tools/utils" "6.0.18" + "@graphql-tools/wrap" "6.0.18" + "@types/websocket" "1.0.1" + cross-fetch "3.0.5" + subscriptions-transport-ws "0.9.17" + tslib "~2.0.0" + valid-url "1.0.9" + websocket "1.0.31" + +"@graphql-tools/utils@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-6.0.18.tgz#bba960f0ab327c8304089d41da0b7a3e00fe430f" + integrity sha512-8ntYuXJucBtjViOYljeKBzScfpVTnv7BfqIPU/WJ65h6nXD+qf8fMUR1C4MpCUeFvSjMiDSB5Z4enJmau/9D3A== + dependencies: + "@ardatan/aggregate-error" "0.0.1" + camel-case "4.1.1" + +"@graphql-tools/wrap@6.0.18": + version "6.0.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-6.0.18.tgz#a9a9bd8e1dac469671274153f419ab35317164ac" + integrity sha512-AHegxtawd+ivpUhI1gP4xQWWYPl5GvCmvzaas03DfrGlGcV/LyKJIzdZDEs2E4oCgwCU7F9UQMxgTsq+Dttn5Q== + dependencies: + "@graphql-tools/delegate" "6.0.18" + "@graphql-tools/schema" "6.0.18" + "@graphql-tools/utils" "6.0.18" + aggregate-error "3.0.1" + is-promise "4.0.0" + tslib "~2.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" - integrity sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg== + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== dependencies: camelcase "^5.3.1" find-up "^4.1.0" + get-package-type "^0.1.0" js-yaml "^3.13.1" resolve-from "^5.0.0" @@ -1224,6 +1286,59 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78= + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A= + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU= + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E= + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik= + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0= + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q= + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -1236,39 +1351,164 @@ dependencies: defer-to-connect "^1.0.1" +"@types/accepts@*": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575" + integrity sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ== + dependencies: + "@types/node" "*" + +"@types/body-parser@*": + version "1.19.0" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" + integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ== + dependencies: + "@types/connect" "*" + "@types/node" "*" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== -"@types/events@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" - integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== +"@types/connect@*": + version "3.4.33" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546" + integrity sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A== + dependencies: + "@types/node" "*" + +"@types/content-disposition@*": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.3.tgz#0aa116701955c2faa0717fc69cd1596095e49d96" + integrity sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg== + +"@types/cookies@*": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.4.tgz#26dedf791701abc0e36b5b79a5722f40e455f87b" + integrity sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw== + dependencies: + "@types/connect" "*" + "@types/express" "*" + "@types/keygrip" "*" + "@types/node" "*" + +"@types/express-serve-static-core@*": + version "4.17.9" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.9.tgz#2d7b34dcfd25ec663c25c85d76608f8b249667f1" + integrity sha512-DG0BYg6yO+ePW+XoDENYz8zhNGC3jDDEpComMYn7WJc4mY1Us8Rw9ax2YhJXxpyk2SF47PQAoQ0YyVT1a0bEkA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@*": + version "4.17.7" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.7.tgz#42045be6475636d9801369cd4418ef65cdb0dd59" + integrity sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/fs-capacitor@*": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz#17113e25817f584f58100fb7a08eed288b81956e" + integrity sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ== + dependencies: + "@types/node" "*" "@types/glob@^7.1.1": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" - integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + version "7.1.3" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" + integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w== dependencies: - "@types/events" "*" "@types/minimatch" "*" "@types/node" "*" +"@types/graphql-upload@^8.0.0": + version "8.0.3" + resolved "https://registry.yarnpkg.com/@types/graphql-upload/-/graphql-upload-8.0.3.tgz#b371edb5f305a2a1f7b7843a890a2a7adc55c3ec" + integrity sha512-hmLg9pCU/GmxBscg8GCr1vmSoEmbItNNxdD5YH2TJkXm//8atjwuprB+xJBK714JG1dkxbbhp5RHX+Pz1KsCMA== + dependencies: + "@types/express" "*" + "@types/fs-capacitor" "*" + "@types/koa" "*" + graphql "^14.5.3" + +"@types/http-assert@*": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.5.1.tgz#d775e93630c2469c2f980fc27e3143240335db3b" + integrity sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ== + "@types/js-cookie@2.2.6": version "2.2.6" resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.6.tgz#f1a1cb35aff47bc5cfb05cb0c441ca91e914c26f" integrity sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw== +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + +"@types/keygrip@*": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72" + integrity sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw== + +"@types/koa-compose@*": + version "3.2.5" + resolved "https://registry.yarnpkg.com/@types/koa-compose/-/koa-compose-3.2.5.tgz#85eb2e80ac50be95f37ccf8c407c09bbe3468e9d" + integrity sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ== + dependencies: + "@types/koa" "*" + +"@types/koa@*": + version "2.11.3" + resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.11.3.tgz#540ece376581b12beadf9a417dd1731bc31c16ce" + integrity sha512-ABxVkrNWa4O/Jp24EYI/hRNqEVRlhB9g09p48neQp4m3xL1TJtdWk2NyNQSMCU45ejeELMQZBYyfstyVvO2H3Q== + dependencies: + "@types/accepts" "*" + "@types/content-disposition" "*" + "@types/cookies" "*" + "@types/http-assert" "*" + "@types/keygrip" "*" + "@types/koa-compose" "*" + "@types/node" "*" + +"@types/long@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" + integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== + +"@types/mime@*": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.3.tgz#c893b73721db73699943bfc3653b1deb7faa4a3a" + integrity sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/node-fetch@2.5.7": + version "2.5.7" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" + integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*": - version "13.7.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.1.tgz#238eb34a66431b71d2aaddeaa7db166f25971a0d" - integrity sha512-Zq8gcQGmn4txQEJeiXo/KiLpon8TzAl0kmKH4zdWctPj05nWwp1ClMdAVEloqrQKfaC48PNLdgN/aVaLqUrluA== + version "14.0.27" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1" + integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g== + +"@types/node@^10.1.0": + version "10.17.28" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.28.tgz#0e36d718a29355ee51cec83b42d921299200f6d9" + integrity sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -1276,9 +1516,67 @@ integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== "@types/q@^1.5.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" - integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" + integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== + +"@types/qs@*": + version "6.9.4" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.4.tgz#a59e851c1ba16c0513ea123830dd639a0a15cb6a" + integrity sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ== + +"@types/range-parser@*": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" + integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== + +"@types/serve-static@*": + version "1.13.5" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.5.tgz#3d25d941a18415d3ab092def846e135a08bbcf53" + integrity sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ== + dependencies: + "@types/express-serve-static-core" "*" + "@types/mime" "*" + +"@types/websocket@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.1.tgz#039272c196c2c0e4868a0d8a1a27bbb86e9e9138" + integrity sha512-f5WLMpezwVxCLm1xQe/kdPpQIOmL0TXYx2O15VYfYzc7hTIdxiOoOvez+McSIw3b7z/1zGovew9YSL7+h4h7/Q== + dependencies: + "@types/node" "*" + +"@types/ws@^7.0.0": + version "7.2.6" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.2.6.tgz#516cbfb818310f87b43940460e065eb912a4178d" + integrity sha512-Q07IrQUSNpr+cXU4E4LtkSIBPie5GLZyyMC1QtQYRLWz701+XcoVygGUZgvLqElq1nU4ICldMYPnexlBsg3dqQ== + dependencies: + "@types/node" "*" + +"@types/zen-observable@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" + integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg== + +"@wry/context@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.5.2.tgz#f2a5d5ab9227343aa74c81e06533c1ef84598ec7" + integrity sha512-B/JLuRZ/vbEKHRUiGj6xiMojST1kHhu4WcreLfNN7q9DqQFrb97cWgf/kiYsPSUCAMVN0HzfFc8XjJdzgZzfjw== + dependencies: + tslib "^1.9.3" + +"@wry/equality@^0.1.2": + version "0.1.11" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.1.11.tgz#35cb156e4a96695aa81a9ecc4d03787bc17f1790" + integrity sha512-mwEVBDUVODlsQQ5dfuLUS5/Tf7jqUKyhKYHmVi4fPB6bDMOfWvUPJmKgS1Z7Za/sOI3vzWt4+O7yCiL/70MogA== + dependencies: + tslib "^1.9.3" + +"@wry/equality@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.2.0.tgz#a312d1b6a682d0909904c2bcd355b02303104fb7" + integrity sha512-Y4d+WH6hs+KZJUC8YKLYGarjGekBrhslDbf/R20oV+AakHPINSitHfDRQz3EGcEWc1luXYNUvMhawWtZVWNGvQ== + dependencies: + tslib "^1.9.3" "@xobotyi/scrollbar-width@1.9.5": version "1.9.5" @@ -1298,12 +1596,20 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -ackee-tracker@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/ackee-tracker/-/ackee-tracker-3.2.3.tgz#9e260ac5a52f2941d0665290e42b97832e4ecc9f" - integrity sha512-LZqwNn+pzzuKIKS93KLGlPeLIBHSmbT9MacWkjTDNDR8y9/7FvE92vxAYiD9Lx7n08fflZCrvTIw6I+d9825AA== +accept@^3.0.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/accept/-/accept-3.1.3.tgz#29c3e2b3a8f4eedbc2b690e472b9ebbdc7385e87" + integrity sha512-OgOEAidVEOKPup+Gv2+2wdH2AgVKI9LxsJ4hicdJ6cY0faUuZdZoi56kkXWlHp9qicN1nWQLmW5ZRGk+SBS5xg== + dependencies: + boom "7.x.x" + hoek "6.x.x" + +ackee-tracker@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ackee-tracker/-/ackee-tracker-4.0.0.tgz#b83a1def05cb0243163a8f03e80eca923df74451" + integrity sha512-HA1LAnci8WMv1Dtrl4L3JyFJaOzajxFhfVI856zIPceKVtPdKpJSEQxU1hFOzG5iFH7O6HfeZPPgtJZrkzCJFA== dependencies: - platform "^1.3.5" + platform "^1.3.6" acorn-jsx@^5.2.0: version "5.2.0" @@ -1319,22 +1625,17 @@ acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2, acorn-node@^1.6.1: acorn-walk "^7.0.0" xtend "^4.0.2" -acorn-walk@^7.0.0, acorn-walk@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e" - integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ== - -acorn@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" - integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== - -acorn@^7.1.1: +acorn-walk@^7.0.0, acorn-walk@^7.2.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe" - integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ== + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn@^7.0.0, acorn@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" + integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== -aggregate-error@^3.0.0: +aggregate-error@3.0.1, aggregate-error@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== @@ -1342,10 +1643,10 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: - version "6.11.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.11.0.tgz#c3607cbc8ae392d8a5a536f25b21f8e5f3f87fe9" - integrity sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA== +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3: + version "6.12.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" + integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -1369,12 +1670,10 @@ ansi-align@^3.0.0: dependencies: string-width "^3.0.0" -ansi-escapes@^4.2.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" - integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== - dependencies: - type-fest "^0.8.1" +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-regex@^2.0.0: version "2.1.1" @@ -1424,6 +1723,174 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" +apollo-cache-control@^0.11.1: + version "0.11.1" + resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.11.1.tgz#3bce0924ae7322a8b9f7ca1e2fb036d1fc9f1df5" + integrity sha512-6iHa8TkcKt4rx5SKRzDNjUIpCQX+7/FlZwD7vRh9JDnM4VH8SWhpj8fUR3CiEY8Kuc4ChXnOY8bCcMju5KPnIQ== + dependencies: + apollo-server-env "^2.4.5" + apollo-server-plugin-base "^0.9.1" + +apollo-datasource@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/apollo-datasource/-/apollo-datasource-0.7.2.tgz#1662ee93453a9b89af6f73ce561bde46b41ebf31" + integrity sha512-ibnW+s4BMp4K2AgzLEtvzkjg7dJgCaw9M5b5N0YKNmeRZRnl/I/qBTQae648FsRKgMwTbRQIvBhQ0URUFAqFOw== + dependencies: + apollo-server-caching "^0.5.2" + apollo-server-env "^2.4.5" + +apollo-engine-reporting-protobuf@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.2.tgz#b01812508a1c583328a8dc603769bc63b8895e7e" + integrity sha512-4wm9FR3B7UvJxcK/69rOiS5CAJPEYKufeRWb257ZLfX7NGFTMqvbc1hu4q8Ch7swB26rTpkzfsftLED9DqH9qg== + dependencies: + "@apollo/protobufjs" "^1.0.3" + +apollo-engine-reporting@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-2.3.0.tgz#3bb59f81aaf6b967ed098896a4a60a053b4eed5a" + integrity sha512-SbcPLFuUZcRqDEZ6mSs8uHM9Ftr8yyt2IEu0JA8c3LNBmYXSLM7MHqFe80SVcosYSTBgtMz8mLJO8orhYoSYZw== + dependencies: + apollo-engine-reporting-protobuf "^0.5.2" + apollo-graphql "^0.5.0" + apollo-server-caching "^0.5.2" + apollo-server-env "^2.4.5" + apollo-server-errors "^2.4.2" + apollo-server-plugin-base "^0.9.1" + apollo-server-types "^0.5.1" + async-retry "^1.2.1" + uuid "^8.0.0" + +apollo-env@^0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/apollo-env/-/apollo-env-0.6.5.tgz#5a36e699d39e2356381f7203493187260fded9f3" + integrity sha512-jeBUVsGymeTHYWp3me0R2CZRZrFeuSZeICZHCeRflHTfnQtlmbSXdy5E0pOyRM9CU4JfQkKDC98S1YglQj7Bzg== + dependencies: + "@types/node-fetch" "2.5.7" + core-js "^3.0.1" + node-fetch "^2.2.0" + sha.js "^2.4.11" + +apollo-graphql@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/apollo-graphql/-/apollo-graphql-0.5.0.tgz#7e9152093211b58352aa6504d8d39ec7241d6872" + integrity sha512-YSdF/BKPbsnQpxWpmCE53pBJX44aaoif31Y22I/qKpB6ZSGzYijV5YBoCL5Q15H2oA/v/02Oazh9lbp4ek3eig== + dependencies: + apollo-env "^0.6.5" + lodash.sortby "^4.7.0" + +apollo-link@1.2.14, apollo-link@^1.2.14: + version "1.2.14" + resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.14.tgz#3feda4b47f9ebba7f4160bef8b977ba725b684d9" + integrity sha512-p67CMEFP7kOG1JZ0ZkYZwRDa369w5PIjtMjvrQd/HnIV8FRsHRqLqK+oAZQnFa1DDdZtOtHTi+aMIW6EatC2jg== + dependencies: + apollo-utilities "^1.3.0" + ts-invariant "^0.4.0" + tslib "^1.9.3" + zen-observable-ts "^0.8.21" + +apollo-server-caching@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/apollo-server-caching/-/apollo-server-caching-0.5.2.tgz#bef5d5e0d48473a454927a66b7bb947a0b6eb13e" + integrity sha512-HUcP3TlgRsuGgeTOn8QMbkdx0hLPXyEJehZIPrcof0ATz7j7aTPA4at7gaiFHCo8gk07DaWYGB3PFgjboXRcWQ== + dependencies: + lru-cache "^5.0.0" + +apollo-server-core@^2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.16.1.tgz#5b5b8245ab9c0cb6c2367ec19ab855dea6ccea3a" + integrity sha512-nuwn5ZBbmzPwDetb3FgiFFJlNK7ZBFg8kis/raymrjd3eBGdNcOyMTJDl6J9673X9Xqp+dXQmFYDW/G3G8S1YA== + dependencies: + "@apollographql/apollo-tools" "^0.4.3" + "@apollographql/graphql-playground-html" "1.6.26" + "@types/graphql-upload" "^8.0.0" + "@types/ws" "^7.0.0" + apollo-cache-control "^0.11.1" + apollo-datasource "^0.7.2" + apollo-engine-reporting "^2.3.0" + apollo-server-caching "^0.5.2" + apollo-server-env "^2.4.5" + apollo-server-errors "^2.4.2" + apollo-server-plugin-base "^0.9.1" + apollo-server-types "^0.5.1" + apollo-tracing "^0.11.1" + fast-json-stable-stringify "^2.0.0" + graphql-extensions "^0.12.4" + graphql-tag "^2.9.2" + graphql-tools "^4.0.0" + graphql-upload "^8.0.2" + loglevel "^1.6.7" + sha.js "^2.4.11" + subscriptions-transport-ws "^0.9.11" + ws "^6.0.0" + +apollo-server-env@^2.4.5: + version "2.4.5" + resolved "https://registry.yarnpkg.com/apollo-server-env/-/apollo-server-env-2.4.5.tgz#73730b4f0439094a2272a9d0caa4079d4b661d5f" + integrity sha512-nfNhmGPzbq3xCEWT8eRpoHXIPNcNy3QcEoBlzVMjeglrBGryLG2LXwBSPnVmTRRrzUYugX0ULBtgE3rBFNoUgA== + dependencies: + node-fetch "^2.1.2" + util.promisify "^1.0.0" + +apollo-server-errors@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.4.2.tgz#1128738a1d14da989f58420896d70524784eabe5" + integrity sha512-FeGxW3Batn6sUtX3OVVUm7o56EgjxDlmgpTLNyWcLb0j6P8mw9oLNyAm3B+deHA4KNdNHO5BmHS2g1SJYjqPCQ== + +apollo-server-micro@^2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/apollo-server-micro/-/apollo-server-micro-2.16.1.tgz#937f97a92041f3ddabc36e57ece12adedddee913" + integrity sha512-iErTU9zltnVOvb8ZJ0cNL8WHKWiHgfSt03Hp4J30qMLVDRvXBsb9Wt/GvW/9si8NBMw84E0kDlQpsCrZ7O+c6A== + dependencies: + "@apollographql/graphql-playground-html" "1.6.26" + accept "^3.0.2" + apollo-server-core "^2.16.1" + apollo-server-types "^0.5.1" + micro "^9.3.2" + +apollo-server-plugin-base@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.9.1.tgz#a62ae9ab4e89790fd4cc5d123bb616da34e8e5fb" + integrity sha512-kvrX4Z3FdpjrZdHkyl5iY2A1Wvp4b6KQp00DeZqss7GyyKNUBKr80/7RQgBLEw7EWM7WB19j459xM/TjvW0FKQ== + dependencies: + apollo-server-types "^0.5.1" + +apollo-server-types@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.5.1.tgz#091c09652894d6532db9ba873574443adabf85b9" + integrity sha512-my2cPw+DAb2qVnIuBcsRKGyS28uIc2vjFxa1NpRoJZe9gK0BWUBk7wzXnIzWy3HZ5Er11e/40MPTUesNfMYNVA== + dependencies: + apollo-engine-reporting-protobuf "^0.5.2" + apollo-server-caching "^0.5.2" + apollo-server-env "^2.4.5" + +apollo-tracing@^0.11.1: + version "0.11.1" + resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.11.1.tgz#3e3a4ce4b21e57dcc57b10bbd539db243b752606" + integrity sha512-l7g+uILw7v32GA46IRXIx5XXbZhFI96BhSqrGK9yyvfq+NMcvVZrj3kIhRImPGhAjMdV+5biA/jztabElAbDjg== + dependencies: + apollo-server-env "^2.4.5" + apollo-server-plugin-base "^0.9.1" + +apollo-upload-client@14.1.1: + version "14.1.1" + resolved "https://registry.yarnpkg.com/apollo-upload-client/-/apollo-upload-client-14.1.1.tgz#2b21bb3424293a56ad9c4b9678395f5898f9b9be" + integrity sha512-6H6AW5habDHH/9XCJ8l2qlkaohwIcO+Lt/8P2908/yx0TC0oaiDNVu+0v2YE/5gA6NP0RvztUodzJUZJz27C0g== + dependencies: + "@apollo/client" "^3.0.2" + "@babel/runtime" "^7.10.5" + extract-files "^9.0.0" + +apollo-utilities@^1.0.1, apollo-utilities@^1.3.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.3.4.tgz#6129e438e8be201b6c55b0f13ce49d2c7175c9cf" + integrity sha512-pk2hiWrCXMAy2fRPwEyhvka+mqwzeP60Jr1tRYi5xru+3ko94HI9o6lK0CT33/w4RDlxWchmdhDCrvdr+pHCig== + dependencies: + "@wry/equality" "^0.1.2" + fast-json-stable-stringify "^2.0.0" + ts-invariant "^0.4.0" + tslib "^1.10.0" + append-transform@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" @@ -1466,7 +1933,7 @@ array-find-index@^1.0.1: resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= -array-includes@^3.0.3, array-includes@^3.1.1: +array-includes@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== @@ -1492,7 +1959,7 @@ array-uniq@^1.0.1: resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= -array.prototype.flat@^1.2.1: +array.prototype.flat@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ== @@ -1500,6 +1967,15 @@ array.prototype.flat@^1.2.1: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" +array.prototype.flatmap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz#1c13f84a178566042dd63de4414440db9222e443" + integrity sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + arrgv@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/arrgv/-/arrgv-1.0.2.tgz#025ed55a6a433cad9b604f8112fc4292715a6ec0" @@ -1515,6 +1991,11 @@ arrify@^2.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -1559,67 +2040,84 @@ async-foreach@^0.1.3: resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async-retry@^1.2.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.1.tgz#139f31f8ddce50c0870b0ba558a6079684aaed55" + integrity sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA== + dependencies: + retry "0.12.0" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + autoprefixer@^9.4.8: - version "9.7.4" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378" - integrity sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g== + version "9.8.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" + integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== dependencies: - browserslist "^4.8.3" - caniuse-lite "^1.0.30001020" - chalk "^2.4.2" + browserslist "^4.12.0" + caniuse-lite "^1.0.30001109" + colorette "^1.2.1" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.26" - postcss-value-parser "^4.0.2" + postcss "^7.0.32" + postcss-value-parser "^4.1.0" -ava@3.8.2: - version "3.8.2" - resolved "https://registry.yarnpkg.com/ava/-/ava-3.8.2.tgz#877c9eb861763a185bbabd54f359e1fbe57d1754" - integrity sha512-sph3oUsVTGsq4qbgeWys03QKCmXjkZUO3oPnFWXEW6g1SReCY9vuONGghMgw1G6VOzkg1k+niqJsOzwfO8h9Ng== +ava@3.11.1: + version "3.11.1" + resolved "https://registry.yarnpkg.com/ava/-/ava-3.11.1.tgz#580bfc974b858fb13f7ce948b9651da4e5b17bc8" + integrity sha512-yGPD0msa5Qronw7GHDNlLaB7oU5zryYtXeuvny40YV6TMskSghqK7Ky3NisM/sr+aqI3DY7sfmORx8dIWQgMoQ== dependencies: "@concordance/react" "^2.0.0" - acorn "^7.1.1" - acorn-walk "^7.1.1" + acorn "^7.3.1" + acorn-walk "^7.2.0" ansi-styles "^4.2.1" arrgv "^1.0.2" arrify "^2.0.1" callsites "^3.1.0" - chalk "^4.0.0" - chokidar "^3.4.0" + chalk "^4.1.0" + chokidar "^3.4.1" chunkd "^2.0.1" ci-info "^2.0.0" - ci-parallel-vars "^1.0.0" + ci-parallel-vars "^1.0.1" clean-yaml-object "^0.1.0" cli-cursor "^3.1.0" cli-truncate "^2.1.0" - code-excerpt "^2.1.1" + code-excerpt "^3.0.0" common-path-prefix "^3.0.0" - concordance "^4.0.0" + concordance "^5.0.0" convert-source-map "^1.7.0" currently-unhandled "^0.4.1" debug "^4.1.1" del "^5.1.0" - emittery "^0.6.0" + emittery "^0.7.1" equal-length "^1.0.0" figures "^3.2.0" - globby "^11.0.0" - ignore-by-default "^1.0.0" + globby "^11.0.1" + ignore-by-default "^2.0.0" import-local "^3.0.2" indent-string "^4.0.0" is-error "^2.2.2" - is-plain-object "^3.0.0" + is-plain-object "^4.1.1" is-promise "^4.0.0" - lodash "^4.17.15" + lodash "^4.17.19" matcher "^3.0.0" md5-hex "^3.0.1" mem "^6.1.0" ms "^2.1.2" - ora "^4.0.4" + ora "^4.0.5" p-map "^4.0.0" picomatch "^2.2.2" pkg-conf "^3.1.0" @@ -1636,7 +2134,7 @@ ava@3.8.2: trim-off-newlines "^1.0.1" update-notifier "^4.1.0" write-file-atomic "^3.0.3" - yargs "^15.3.1" + yargs "^15.4.1" aws-sign2@~0.7.0: version "0.7.0" @@ -1644,16 +2142,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" - integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== - -babel-plugin-dynamic-import-node@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== - dependencies: - object.assign "^4.1.0" + version "1.10.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" + integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA== babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" @@ -1662,11 +2153,54 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" +babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: + version "7.0.0-beta.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" + integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== + +babel-preset-fbjs@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.3.0.tgz#a6024764ea86c8e06a22d794ca8b69534d263541" + integrity sha512-7QTLTCd2gwB2qGoi5epSULMHugSVgpcVt5YAeiFO9ABLrutDQzKfGwzxgZHLpugq8qMdg/DhRZDZ5CLKxBkEbw== + dependencies: + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-class-properties" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoped-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-member-expression-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-property-literals" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" + babelify@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-10.0.0.tgz#fe73b1a22583f06680d8d072e25a1e0d1d1d7fb5" integrity sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg== +backo2@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" + integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -1685,9 +2219,9 @@ bcrypt-pbkdf@^1.0.0: tweetnacl "^0.14.3" binary-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" - integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== bl@^2.2.0: version "2.2.0" @@ -1710,20 +2244,32 @@ bluebird@3.5.1: integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA== blueimp-md5@^2.10.0: - version "2.12.0" - resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.12.0.tgz#be7367938a889dec3ffbb71138617c117e9c130a" - integrity sha512-zo+HIdIhzojv6F1siQPqPFROyVy7C50KzHv/k/Iz+BtvtVzSHXiMXOpq2wCfNkeBqdCv+V8XOV96tsEt2W/3rQ== + version "2.17.0" + resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.17.0.tgz#f4fcac088b115f7b4045f19f5da59e9d01b1bb96" + integrity sha512-x5PKJHY5rHQYaADj6NwPUR2QRCUVSggPzrUKkeENpj871o9l9IefJbO2jkT5UvYykeOK9dx0VmkIo6dZ+vThYw== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: + version "4.11.9" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" + integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== + +bn.js@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.2.tgz#c9686902d3c9a27729f43ab10f9d79c2004da7b0" + integrity sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA== boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +boom@7.x.x: + version "7.3.0" + resolved "https://registry.yarnpkg.com/boom/-/boom-7.3.0.tgz#733a6d956d33b0b1999da3fe6c12996950d017b9" + integrity sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A== + dependencies: + hoek "6.x.x" + bowser@^1.7.3: version "1.9.4" resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.9.4.tgz#890c58a2813a9d3243704334fa81b96a5c150c9a" @@ -1813,7 +2359,7 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0: +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= @@ -1822,17 +2368,19 @@ browserify-rsa@^4.0.0: randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= - dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" + version "4.2.0" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.0.tgz#545d0b1b07e6b2c99211082bf1b12cce7a0b0e11" + integrity sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.2" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" browserify-zlib@~0.2.0: version "0.2.0" @@ -1842,16 +2390,16 @@ browserify-zlib@~0.2.0: pako "~1.0.5" browserify@^16.5.0: - version "16.5.0" - resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.5.0.tgz#a1c2bc0431bec11fd29151941582e3f645ede881" - integrity sha512-6bfI3cl76YLAnCZ75AGu/XPOsqUhRyc0F/olGIJeCxtfxF2HvPKEcmjU9M8oAPxl4uBY1U7Nry33Q6koV3f2iw== + version "16.5.1" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.5.1.tgz#3c13c97436802930d5c3ae28658ddc33bfd37dc2" + integrity sha512-EQX0h59Pp+0GtSRb5rL6OTfrttlzv+uyaUVlK6GX3w11SQ0jKPKyjC/54RhPR2ib2KmfcELM06e8FxcI5XNU2A== dependencies: JSONStream "^1.0.3" assert "^1.4.0" browser-pack "^6.0.1" browser-resolve "^1.11.0" browserify-zlib "~0.2.0" - buffer "^5.0.2" + buffer "~5.2.1" cached-path-relative "^1.0.0" concat-stream "^1.6.0" console-browserify "^1.1.0" @@ -1869,7 +2417,7 @@ browserify@^16.5.0: inherits "~2.0.1" insert-module-globals "^7.0.0" labeled-stream-splicer "^2.0.0" - mkdirp "^0.5.0" + mkdirp-classic "^0.5.2" module-deps "^6.0.0" os-browserify "~0.3.0" parents "^1.0.1" @@ -1895,24 +2443,22 @@ browserify@^16.5.0: vm-browserify "^1.0.0" xtend "^4.0.0" -browserslist@^4.0.0, browserslist@^4.8.3, browserslist@^4.8.5: - version "4.8.7" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.7.tgz#ec8301ff415e6a42c949d0e66b405eb539c532d0" - integrity sha512-gFOnZNYBHrEyUML0xr5NJ6edFaaKbTFX9S9kQHlYfCP0Rit/boRIz4G+Avq6/4haEKJXdGGUnoolx+5MWW2BoA== +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.8.5: + version "4.13.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.13.0.tgz#42556cba011e1b0a2775b611cba6a8eca18e940d" + integrity sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ== dependencies: - caniuse-lite "^1.0.30001027" - electron-to-chromium "^1.3.349" - node-releases "^1.1.49" + caniuse-lite "^1.0.30001093" + electron-to-chromium "^1.3.488" + escalade "^3.0.1" + node-releases "^1.1.58" -browserslist@^4.11.1: - version "4.12.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" - integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== dependencies: - caniuse-lite "^1.0.30001043" - electron-to-chromium "^1.3.413" - node-releases "^1.1.53" - pkg-up "^2.0.0" + node-int64 "^0.4.0" bson@^1.1.4: version "1.1.4" @@ -1929,10 +2475,10 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= -buffer@^5.0.2: - version "5.4.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" - integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A== +buffer@~5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" + integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1942,6 +2488,13 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= +busboy@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b" + integrity sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw== + dependencies: + dicer "0.3.0" + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -1999,6 +2552,14 @@ callsites@^3.0.0, callsites@^3.1.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camel-case@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547" + integrity sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q== + dependencies: + pascal-case "^3.1.1" + tslib "^1.10.0" + camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" @@ -2012,11 +2573,6 @@ camelcase@^2.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= - camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -2032,15 +2588,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001027: - version "1.0.30001027" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001027.tgz#283e2ef17d94889cc216a22c6f85303d78ca852d" - integrity sha512-7xvKeErvXZFtUItTHgNtLgS9RJpVnwBlWX8jSo/BO8VsF6deszemZSkJJJA1KOKrXuzZH4WALpAJdq5EyfgMLg== - -caniuse-lite@^1.0.30001043: - version "1.0.30001054" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001054.tgz#7e82fc42d927980b0ce1426c4813df12381e1a75" - integrity sha512-jiKlTI6Ur8Kjfj8z0muGrV6FscpRvefcQVPSuMuXnvRCfExU7zlVLNjmOz1TnurWgUrAY7MMmjyy+uTgIl1XHw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001109: + version "1.0.30001109" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001109.tgz#a9f3f26a0c3753b063d7acbb48dfb9c0e46f2b19" + integrity sha512-4JIXRodHzdS3HdK8nSgIqXYLExOvG+D2/EenSvcub2Kp3QEADjo2v2oUn5g0n0D+UNwG9BtwKOyGcSq2qvQXvQ== caseless@~0.12.0: version "0.12.0" @@ -2075,43 +2626,23 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" - integrity sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A== +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - check-more-types@2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= -chokidar@^3.2.2: - version "3.3.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" - integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.3.0" - optionalDependencies: - fsevents "~2.1.2" - -chokidar@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8" - integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ== +chokidar@^3.2.2, chokidar@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1" + integrity sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -2133,10 +2664,10 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -ci-parallel-vars@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ci-parallel-vars/-/ci-parallel-vars-1.0.0.tgz#af97729ed1c7381911ca37bcea263d62638701b3" - integrity sha512-u6dx20FBXm+apMi+5x7UVm6EH7BL1gc4XrcnQewjcB7HWRcor/V5qWc3RG2HwpgDJ26gIi2DSEu3B7sXynAw/g== +ci-parallel-vars@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz#e87ff0625ccf9d286985b29b4ada8485ca9ffbc2" + integrity sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" @@ -2174,9 +2705,9 @@ cli-cursor@^3.1.0: restore-cursor "^3.1.0" cli-spinners@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" - integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== + version "2.4.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.4.0.tgz#c6256db216b878cfba4720e719cec7cf72685d7f" + integrity sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA== cli-truncate@^2.1.0: version "2.1.0" @@ -2186,19 +2717,14 @@ cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" cliui@^6.0.0: version "6.0.0" @@ -2230,10 +2756,10 @@ coa@^2.0.2: chalk "^2.4.1" q "^1.1.2" -code-excerpt@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-2.1.1.tgz#5fe3057bfbb71a5f300f659ef2cc0a47651ba77c" - integrity sha512-tJLhH3EpFm/1x7heIW0hemXJTUU5EWl2V0EIX558jp05Mt1U6DVryCgkp3l37cxqs+DNbNgxG43SkwJXpQ14Jw== +code-excerpt@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-3.0.0.tgz#fcfb6748c03dba8431c19f5474747fad3f250f10" + integrity sha512-VHNTVhd7KsLGOqfX3SyeO8RyYPMp1GJOg194VITk04WMYCv4plV68YWe6TJZxd9MhobjtpMRnVky01gqZsalaw== dependencies: convert-to-spaces "^1.0.1" @@ -2282,6 +2808,11 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" +colorette@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== + combine-source-map@^0.8.0, combine-source-map@~0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" @@ -2292,14 +2823,14 @@ combine-source-map@^0.8.0, combine-source-map@~0.8.0: lodash.memoize "~3.0.3" source-map "~0.5.3" -combined-stream@^1.0.6, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" -commander@^2.20.0: +commander@^2.20.0, commander@^2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -2329,21 +2860,18 @@ concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@~1.6.0: readable-stream "^2.2.2" typedarray "^0.0.6" -concordance@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/concordance/-/concordance-4.0.0.tgz#5932fdee397d129bdbc3a1885fbe69839b1b7e15" - integrity sha512-l0RFuB8RLfCS0Pt2Id39/oCPykE01pyxgAFypWTlaGRgvLkZrtczZ8atEHpTeEIW+zYWXTBuA9cCSeEOScxReQ== +concordance@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/concordance/-/concordance-5.0.0.tgz#6d4552f76c78301dd65e748c26af2cf131f9dd49" + integrity sha512-stOCz9ffg0+rytwTaL2njUOIyMfANwfwmqc9Dr4vTUS/x/KkVFlWx9Zlzu6tHYtjKxxaCF/cEAZgPDac+n35sg== dependencies: - date-time "^2.1.0" - esutils "^2.0.2" - fast-diff "^1.1.2" + date-time "^3.1.0" + esutils "^2.0.3" + fast-diff "^1.2.0" js-string-escape "^1.0.1" - lodash.clonedeep "^4.5.0" - lodash.flattendeep "^4.4.0" - lodash.islength "^4.0.1" - lodash.merge "^4.6.1" - md5-hex "^2.0.0" - semver "^5.5.1" + lodash "^4.17.15" + md5-hex "^3.0.1" + semver "^7.3.2" well-known-symbols "^2.0.0" configstore@^5.0.1: @@ -2401,24 +2929,29 @@ convert-to-spaces@^1.0.1: integrity sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU= copy-to-clipboard@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.2.1.tgz#b1a1137100e5665d5a96015cb579e30e90e07c44" - integrity sha512-btru1Q6RD9wbonIvEU5EfnhIRGHLo//BGXQ1hNAD2avIs/nBZlpbOeKtv3mhoUByN4DB9Cb6/vXBymj1S43KmA== + version "3.3.1" + resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" + integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== dependencies: toggle-selection "^1.0.6" core-js-compat@^3.6.2: - version "3.6.4" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.4.tgz#938476569ebb6cda80d339bcf199fae4f16fff17" - integrity sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA== + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" + integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== dependencies: - browserslist "^4.8.3" + browserslist "^4.8.5" semver "7.0.0" -core-js-pure@^3.0.0: - version "3.6.4" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a" - integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw== +core-js@^2.4.1: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + +core-js@^3.0.1: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" + integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -2454,7 +2987,7 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.0.0" -create-hash@^1.1.0, create-hash@^1.1.2: +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== @@ -2465,7 +2998,7 @@ create-hash@^1.1.0, create-hash@^1.1.2: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -2478,34 +3011,32 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: sha.js "^2.4.8" cron-parser@^2.7.3: - version "2.13.0" - resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.13.0.tgz#6f930bb6f2931790d2a9eec83b3ec276e27a6725" - integrity sha512-UWeIpnRb0eyoWPVk+pD3TDpNx3KCFQeezO224oJIkktBrcW6RoAPOx5zIKprZGfk6vcYSmA8yQXItejSaDBhbQ== + version "2.15.0" + resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.15.0.tgz#04803cd51d8efcfcc6f83ac08e60f3f8c40c7ec5" + integrity sha512-rMFkrQw8+oG5OuwjiXesup4KeIlEG/IU82YtG4xyAHbO5jhKmYaHPp/ZNhq9+7TjSJ65E3zV3kQPUbmXSff2/g== dependencies: - is-nan "^1.2.1" - moment-timezone "^0.5.25" + is-nan "^1.3.0" + moment-timezone "^0.5.31" + +cross-fetch@3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.5.tgz#2739d2981892e7ab488a7ad03b92df2816e03f4c" + integrity sha512-FFLcLtraisj5eteosnX1gf01qYDCOc4fDy0+euOt8Kn9YBY2NtXL/pCoYPavw24NIQkQqm5ZOLsGD5Zzj0gyew== + dependencies: + node-fetch "2.6.0" cross-spawn@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI= - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" - integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" -cross-spawn@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.2.tgz#d0d7dcfa74e89115c7619f4f721a94e1fdb716d6" - integrity sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw== +cross-spawn@^7.0.0, cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" @@ -2577,7 +3108,7 @@ css-tree@1.0.0-alpha.37: mdn-data "2.0.4" source-map "^0.6.1" -css-tree@^1.0.0-alpha.28: +css-tree@1.0.0-alpha.39, css-tree@^1.0.0-alpha.28: version "1.0.0-alpha.39" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb" integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA== @@ -2585,20 +3116,20 @@ css-tree@^1.0.0-alpha.28: mdn-data "2.0.6" source-map "^0.6.1" -css-unit-converter@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" - integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= - css-what@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" - integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== + version "3.3.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.3.0.tgz#10fec696a9ece2e591ac772d759aacabac38cd39" + integrity sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg== -cssesc@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" - integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssfilter@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" + integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4= cssnano-preset-default@^4.0.7: version "4.0.7" @@ -2669,16 +3200,16 @@ cssnano@^4.1.10: postcss "^7.0.0" csso@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d" - integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903" + integrity sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ== dependencies: - css-tree "1.0.0-alpha.37" + css-tree "1.0.0-alpha.39" csstype@^2.5.5: - version "2.6.9" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.9.tgz#05141d0cd557a56b8891394c1911c40c8a98d098" - integrity sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q== + version "2.6.13" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.13.tgz#a6893015b90e84dd6e85d0e3b442a1e84f2dbe0f" + integrity sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A== currently-unhandled@^0.4.1: version "0.4.1" @@ -2687,6 +3218,14 @@ currently-unhandled@^0.4.1: dependencies: array-find-index "^1.0.1" +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + dash-ast@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dash-ast/-/dash-ast-1.0.0.tgz#12029ba5fb2f8aa6f0a861795b23c1b4b6c27d37" @@ -2699,18 +3238,38 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -date-fns@^2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.13.0.tgz#d7b8a0a2d392e8d88a8024d0a46b980bbfdbd708" - integrity sha512-xm0c61mevGF7f0XpCGtDTGpzEFC/1fpLXHbmFpxZZQJuvByIK2ozm6cSYuU+nxFYOPh2EuCfzUwlTEFwKG+h5w== +dataloader@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.0.0.tgz#41eaf123db115987e21ca93c005cd7753c55fe6f" + integrity sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ== + +date-fns-tz@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/date-fns-tz/-/date-fns-tz-1.0.10.tgz#30fef0038f80534fddd8e133a6b8ca55ba313748" + integrity sha512-cHQAz0/9uDABaUNDM80Mj1FL4ODlxs1xEY4b0DQuAooO2UdNKvDkNbV8ogLnxLbv02Ru1HXFcot0pVvDRBgptg== + +date-fns@^2.15.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.15.0.tgz#424de6b3778e4e69d3ff27046ec136af58ae5d5f" + integrity sha512-ZCPzAMJZn3rNUvvQIMlXhDr4A+Ar07eLeGsGREoWU19a3Pqf5oYa+ccd+B3F6XVtQY6HANMFdOQ8A+ipFnvJdQ== -date-time@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/date-time/-/date-time-2.1.0.tgz#0286d1b4c769633b3ca13e1e62558d2dbdc2eba2" - integrity sha512-/9+C44X7lot0IeiyfgJmETtRMhBidBYM2QFFIkGa0U1k+hSyY87Nw7PY3eDqpvCBm7I3WCSfPeZskW/YYq6m4g== +date-time@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/date-time/-/date-time-3.1.0.tgz#0d1e934d170579f481ed8df1e2b8ff70ee845e1e" + integrity sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg== dependencies: time-zone "^1.0.0" +de-indent@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" + integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0= + +debounce-promise@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/debounce-promise/-/debounce-promise-3.1.2.tgz#320fb8c7d15a344455cd33cee5ab63530b6dc7c5" + integrity sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg== + debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -2739,7 +3298,7 @@ debug@^3.2.6: dependencies: ms "^2.1.1" -decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: +decamelize@^1.1.2, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -2838,6 +3397,16 @@ depd@1.1.1: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" integrity sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k= +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +deprecated-decorator@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz#00966317b7a12fe92f3cc831f7583af329b86c37" + integrity sha1-AJZjF7ehL+kvPMgx91g68ym4bDc= + deps-sort@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.1.tgz#9dfdc876d2bcec3386b6829ac52162cda9fa208d" @@ -2865,6 +3434,13 @@ detective@^5.2.0: defined "^1.0.0" minimist "^1.1.1" +dicer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872" + integrity sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA== + dependencies: + streamsearch "0.1.2" + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -2966,20 +3542,15 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -electron-to-chromium@^1.3.349: - version "1.3.349" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.349.tgz#663f26a69d348a462df47b4d7ab162a2f29bbcb7" - integrity sha512-uEb2zs6EJ6OZIqaMsCSliYVgzE/f7/s1fLWqtvRtHg/v5KBF2xds974fUnyatfxIDgkqzQVwFtam5KExqywx0Q== - -electron-to-chromium@^1.3.413: - version "1.3.432" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.432.tgz#3bf7b191978ff2e8bc3caf811bb52b1e9f9eab25" - integrity sha512-/GdNhXyLP5Yl2322CUX/+Xi8NhdHBqL6lD9VJVKjH6CjoPGakvwZ5CpKgj/oOlbzuWWjOvMjDw1bBuAIRCNTlw== +electron-to-chromium@^1.3.488: + version "1.3.516" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.516.tgz#03ec071b061e462b786bf7e7ce226fd7ab7cf1f6" + integrity sha512-WDM5AAQdOrvLqSX8g3Zd5AujBXfMxf96oeZkff0U2HF5op3tjShE+on2yay3r1UD4M9I3p0iHpAS4+yV8U8A9A== -elliptic@^6.0.0: - version "6.5.2" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" - integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== +elliptic@^6.0.0, elliptic@^6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" + integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2989,10 +3560,10 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" -emittery@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.6.0.tgz#e85312468d77c3ed9a6adf43bb57d34849e0c95a" - integrity sha512-6EMRGr9KzYWp8DzHFZsKVZBsMO6QhAeHMeHND8rhyBNCHKMLpgW9tZv40bwN3rAIKRS5CxcK8oLRKUJSB9h7yQ== +emittery@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.1.tgz#c02375a927a40948c0345cc903072597f5270451" + integrity sha512-d34LN4L6h18Bzz9xpoku2nPwKxCPlPMr3EEKTkoEBi+1/+b0lcRkRJ1UVyyZaKNeqGR3swcGl6s390DNO4YVgQ== emoji-regex@^7.0.1: version "7.0.3" @@ -3004,6 +3575,13 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +encoding@^0.1.11: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -3011,10 +3589,17 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" + integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== equal-length@^1.0.0: version "1.0.1" @@ -3035,22 +3620,22 @@ error-stack-parser@^2.0.6: dependencies: stackframe "^1.1.1" -es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2: - version "1.17.4" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184" - integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ== +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5: + version "1.17.6" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" + integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.1.5" - is-regex "^1.0.5" + is-callable "^1.2.0" + is-regex "^1.1.0" object-inspect "^1.7.0" object-keys "^1.1.1" object.assign "^4.1.0" - string.prototype.trimleft "^2.1.1" - string.prototype.trimright "^2.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" es-to-primitive@^1.2.1: version "1.2.1" @@ -3061,11 +3646,42 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + es6-error@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +escalade@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" + integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ== + escape-goat@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" @@ -3086,44 +3702,45 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-import-resolver-node@^0.3.2: - version "0.3.3" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404" - integrity sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg== +eslint-import-resolver-node@^0.3.3: + version "0.3.4" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" + integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== dependencies: debug "^2.6.9" resolve "^1.13.1" -eslint-module-utils@^2.4.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz#7878f7504824e1b857dd2505b59a8e5eda26a708" - integrity sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q== +eslint-module-utils@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" + integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA== dependencies: debug "^2.6.9" pkg-dir "^2.0.0" -eslint-plugin-import@^2.20.2: - version "2.20.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz#91fc3807ce08be4837141272c8b99073906e588d" - integrity sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg== +eslint-plugin-import@^2.22.0: + version "2.22.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz#92f7736fe1fde3e2de77623c838dd992ff5ffb7e" + integrity sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg== dependencies: - array-includes "^3.0.3" - array.prototype.flat "^1.2.1" + array-includes "^3.1.1" + array.prototype.flat "^1.2.3" contains-path "^0.1.0" debug "^2.6.9" doctrine "1.5.0" - eslint-import-resolver-node "^0.3.2" - eslint-module-utils "^2.4.1" + eslint-import-resolver-node "^0.3.3" + eslint-module-utils "^2.6.0" has "^1.0.3" minimatch "^3.0.4" - object.values "^1.1.0" + object.values "^1.1.1" read-pkg-up "^2.0.0" - resolve "^1.12.0" + resolve "^1.17.0" + tsconfig-paths "^3.9.0" -eslint-plugin-react-hooks@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.0.0.tgz#81196b990043cde339e25c6662aeebe32ac52d01" - integrity sha512-YKBY+kilK5wrwIdQnCF395Ya6nDro3EAMoe+2xFkmyklyhF16fH83TrQOo9zbZIDxBsXFgBbywta/0JKRNFDkw== +eslint-plugin-react-hooks@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.0.8.tgz#a9b1e3d57475ccd18276882eff3d6cba00da7a56" + integrity sha512-6SSb5AiMCPd8FDJrzah+Z4F44P2CdOaK026cXFV+o/xSRzfOiV1FNFeLl2z6xm3yqWOQEZ5OfVgiec90qV2xrQ== eslint-plugin-react-native-globals@^0.1.1: version "0.1.2" @@ -3137,48 +3754,47 @@ eslint-plugin-react-native@^3.8.1: dependencies: eslint-plugin-react-native-globals "^0.1.1" -eslint-plugin-react@^7.19.0: - version "7.19.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz#6d08f9673628aa69c5559d33489e855d83551666" - integrity sha512-SPT8j72CGuAP+JFbT0sJHOB80TX/pu44gQ4vXH/cq+hQTiY2PuZ6IHkqXJV6x1b28GDdo1lbInjKUrrdUf0LOQ== +eslint-plugin-react@^7.20.6: + version "7.20.6" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.6.tgz#4d7845311a93c463493ccfa0a19c9c5d0fd69f60" + integrity sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg== dependencies: array-includes "^3.1.1" + array.prototype.flatmap "^1.2.3" doctrine "^2.1.0" has "^1.0.3" - jsx-ast-utils "^2.2.3" - object.entries "^1.1.1" + jsx-ast-utils "^2.4.1" + object.entries "^1.1.2" object.fromentries "^2.0.2" object.values "^1.1.1" prop-types "^15.7.2" - resolve "^1.15.1" - semver "^6.3.0" + resolve "^1.17.0" string.prototype.matchall "^4.0.2" - xregexp "^4.3.0" -eslint-scope@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" - integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== +eslint-scope@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" + integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" - integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== +eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.0.0.tgz#c35dfd04a4372110bd78c69a8d79864273919a08" - integrity sha512-qY1cwdOxMONHJfGqw52UOpZDeqXy8xmD0u8CT6jIstil72jkhURC704W8CFyTPDPllz4z4lu0Ql1+07PG/XdIg== +eslint@^7.7.0: + version "7.7.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.7.0.tgz#18beba51411927c4b64da0a8ceadefe4030d6073" + integrity sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -3186,10 +3802,11 @@ eslint@^7.0.0: cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - eslint-visitor-keys "^1.1.0" - espree "^7.0.0" + enquirer "^2.3.5" + eslint-scope "^5.1.0" + eslint-utils "^2.1.0" + eslint-visitor-keys "^1.3.0" + espree "^7.2.0" esquery "^1.2.0" esutils "^2.0.2" file-entry-cache "^5.0.1" @@ -3199,12 +3816,11 @@ eslint@^7.0.0: ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" is-glob "^4.0.0" js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" - lodash "^4.17.14" + lodash "^4.17.19" minimatch "^3.0.4" natural-compare "^1.4.0" optionator "^0.9.1" @@ -3217,14 +3833,14 @@ eslint@^7.0.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.0.0.tgz#8a7a60f218e69f120a842dc24c5a88aa7748a74e" - integrity sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw== +espree@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.2.0.tgz#1c263d5b513dbad0ac30c4991b93ac354e948d69" + integrity sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g== dependencies: - acorn "^7.1.1" + acorn "^7.3.1" acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.1.0" + eslint-visitor-keys "^1.3.0" esprima@^4.0.0: version "4.0.1" @@ -3255,11 +3871,16 @@ estraverse@^5.1.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== -esutils@^2.0.0, esutils@^2.0.2: +esutils@^2.0.2, esutils@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +eventemitter3@^3.1.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" + integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== + events@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/events/-/events-2.1.0.tgz#2a9a1e18e6106e0e812aa9ebd4a819b3c29c0ba5" @@ -3273,19 +3894,22 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +ext@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" + integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== + dependencies: + type "^2.0.0" + extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" +extract-files@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" + integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== extsprintf@1.3.0: version "1.3.0" @@ -3297,26 +3921,27 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fast-deep-equal@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" - integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: +fast-diff@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== fast-glob@^3.0.3, fast-glob@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" - integrity sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g== + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" glob-parent "^5.1.0" merge2 "^1.3.0" micromatch "^4.0.2" + picomatch "^2.2.1" fast-json-stable-stringify@^2.0.0: version "2.1.0" @@ -3344,11 +3969,37 @@ fastest-stable-stringify@^1.0.1: integrity sha1-kSLUBtTJ2YvqZEpraFPVh0uHsCg= fastq@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" - integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== + version "1.8.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" + integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== dependencies: - reusify "^1.0.0" + bser "2.1.1" + +fbjs-css-vars@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" + integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== + +fbjs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-1.0.0.tgz#52c215e0883a3c86af2a7a776ed51525ae8e0a5a" + integrity sha512-MUgcMEJaFhCaF1QtWGnmq9ZDRAzECTCRAF7O6UZIlAlkTs1SasiX9aP0Iw7wfD2mJ7wDTNfg2w7u5fSCwJk1OA== + dependencies: + core-js "^2.4.1" + fbjs-css-vars "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.18" figures@^2.0.0: version "2.0.0" @@ -3357,13 +4008,6 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" - integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== - dependencies: - escape-string-regexp "^1.0.5" - figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -3386,12 +4030,12 @@ fill-range@^7.0.1: to-regex-range "^5.0.1" find-cache-dir@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.2.0.tgz#e7fe44c1abc1299f516146e563108fd1006c1874" - integrity sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg== + version "3.3.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== dependencies: commondir "^1.0.1" - make-dir "^3.0.0" + make-dir "^3.0.2" pkg-dir "^4.1.0" find-up@^1.0.0: @@ -3434,9 +4078,9 @@ flat-cache@^2.0.1: write "1.0.3" flatted@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" - integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== foreground-child@^2.0.0: version "2.0.0" @@ -3451,6 +4095,15 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +form-data@3.0.0, form-data@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" + integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -3466,9 +4119,24 @@ formbase@^12.0.1: integrity sha512-BuvRQhEKtJBMc1I3gcwkh/kSXWIOReNzFgD04l5fhnCOOblu39TA6rQpYNDr8ETY5mVBxsXi2QoqMzRLjmVCqA== fromentries@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.2.0.tgz#e6aa06f240d6267f913cea422075ef88b63e7897" - integrity sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ== + version "1.2.1" + resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.2.1.tgz#64c31665630479bc993cd800d53387920dc61b4d" + integrity sha512-Xu2Qh8yqYuDhQGOhD5iJGninErSfI9A3FrriD3tjUgV5VbJFeH8vfgZ9HnC6jWN80QDVNQK5vmxRAmEAp7Mevw== + +fs-capacitor@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-2.0.4.tgz#5a22e72d40ae5078b4fe64fe4d08c0d3fc88ad3c" + integrity sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA== + +fs-extra@9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" + integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^1.0.0" fs.realpath@^1.0.0: version "1.0.0" @@ -3476,9 +4144,9 @@ fs.realpath@^1.0.0: integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@~2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" - integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== fsify@^3.0.0: version "3.0.0" @@ -3540,16 +4208,16 @@ get-assigned-identifiers@^1.2.0: resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" integrity sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ== -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" @@ -3577,13 +4245,13 @@ getpass@^0.1.1: assert-plus "^1.0.0" glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" - integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== dependencies: is-glob "^4.0.1" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -3608,12 +4276,24 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^12.1.0: - version "12.3.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" - integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw== + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== dependencies: type-fest "^0.8.1" +globby@11.0.1, globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + globby@^10.0.1: version "10.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" @@ -3628,18 +4308,6 @@ globby@^10.0.1: merge2 "^1.2.3" slash "^3.0.0" -globby@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.0.tgz#56fd0e9f0d4f8fb0c456f1ab0dee96e1380bc154" - integrity sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" - slash "^3.0.0" - globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" @@ -3652,12 +4320,12 @@ globby@^6.1.0: pinkie-promise "^2.0.0" globule@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.1.tgz#90a25338f22b7fbeb527cee63c629aea754d33b9" - integrity sha512-OVyWOHgw29yosRHCHo7NncwR1hW5ew0W/UrvtwvjefVJeQ26q4/8r8FmPsSF1hJ93IgWkyv16pCTz6WblMzm/g== + version "1.3.2" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4" + integrity sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA== dependencies: glob "~7.1.1" - lodash "~4.17.12" + lodash "~4.17.10" minimatch "~3.0.2" got@^9.6.0: @@ -3677,10 +4345,90 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" -graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + +graphql-extensions@^0.12.4: + version "0.12.4" + resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.12.4.tgz#c0aa49a20f983a2da641526d1e505996bd2b4188" + integrity sha512-GnR4LiWk3s2bGOqIh6V1JgnSXw2RCH4NOgbCFEWvB6JqWHXTlXnLZ8bRSkCiD4pltv7RHUPWqN/sGh8R6Ae/ag== + dependencies: + "@apollographql/apollo-tools" "^0.4.3" + apollo-server-env "^2.4.5" + apollo-server-types "^0.5.1" + +graphql-scalars@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/graphql-scalars/-/graphql-scalars-1.2.6.tgz#a934ed63c91054db00cde41b9beeddb09b606729" + integrity sha512-k/88kZVXIuUKQuVLokokkKU2lnFEZ9aTn7O0fDweJpISd0pP5fQU1wzPN0jarH4Lnadr4092PfyIUtCcKzkeAw== + +graphql-tag@^2.11.0, graphql-tag@^2.9.2: + version "2.11.0" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.11.0.tgz#1deb53a01c46a7eb401d6cb59dec86fa1cccbffd" + integrity sha512-VmsD5pJqWJnQZMUeRwrDhfgoyqcfwEkvtpANqcoUG8/tOLkwNgU9mzub/Mc78OJMhHjx7gfAMTxzdG43VGg3bA== + +graphql-tools@^4.0.0: + version "4.0.8" + resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-4.0.8.tgz#e7fb9f0d43408fb0878ba66b522ce871bafe9d30" + integrity sha512-MW+ioleBrwhRjalKjYaLQbr+920pHBgy9vM/n47sswtns8+96sRn5M/G+J1eu7IMeKWiN/9p6tmwCHU7552VJg== + dependencies: + apollo-link "^1.2.14" + apollo-utilities "^1.0.1" + deprecated-decorator "^0.1.6" + iterall "^1.1.3" + uuid "^3.1.0" + +graphql-tools@^6.0.18: + version "6.0.18" + resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-6.0.18.tgz#49a58be81ff638f155200522f9a80e569a7c09dd" + integrity sha512-/difTiShNtRnB0K8DqYQrjTwXwCvs+DNQpfrJ/bYtAQHeyif9OhuaZHjjuibTQcNvwpbKi/enm1/JmUrRg/hIA== + dependencies: + "@graphql-tools/batch-delegate" "6.0.18" + "@graphql-tools/code-file-loader" "6.0.18" + "@graphql-tools/delegate" "6.0.18" + "@graphql-tools/git-loader" "6.0.18" + "@graphql-tools/github-loader" "6.0.18" + "@graphql-tools/graphql-file-loader" "6.0.18" + "@graphql-tools/graphql-tag-pluck" "6.0.18" + "@graphql-tools/import" "6.0.18" + "@graphql-tools/json-file-loader" "6.0.18" + "@graphql-tools/links" "6.0.18" + "@graphql-tools/load" "6.0.18" + "@graphql-tools/load-files" "6.0.18" + "@graphql-tools/merge" "6.0.18" + "@graphql-tools/mock" "6.0.18" + "@graphql-tools/module-loader" "6.0.18" + "@graphql-tools/relay-operation-optimizer" "6.0.18" + "@graphql-tools/resolvers-composition" "6.0.18" + "@graphql-tools/schema" "6.0.18" + "@graphql-tools/stitch" "6.0.18" + "@graphql-tools/url-loader" "6.0.18" + "@graphql-tools/utils" "6.0.18" + "@graphql-tools/wrap" "6.0.18" + +graphql-upload@^8.0.2: + version "8.1.0" + resolved "https://registry.yarnpkg.com/graphql-upload/-/graphql-upload-8.1.0.tgz#6d0ab662db5677a68bfb1f2c870ab2544c14939a" + integrity sha512-U2OiDI5VxYmzRKw0Z2dmfk0zkqMRaecH9Smh1U277gVgVe9Qn+18xqf4skwr4YJszGIh7iQDZ57+5ygOK9sM/Q== + dependencies: + busboy "^0.3.1" + fs-capacitor "^2.0.4" + http-errors "^1.7.3" + object-path "^0.11.4" + +graphql@^14.5.3: + version "14.7.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.7.0.tgz#7fa79a80a69be4a31c27dda824dc04dac2035a72" + integrity sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA== + dependencies: + iterall "^1.2.2" + +graphql@^15.3.0: + version "15.3.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278" + integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w== har-schema@^2.0.0: version "2.0.0" @@ -3688,11 +4436,11 @@ har-schema@^2.0.0: integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: - ajv "^6.5.5" + ajv "^6.12.3" har-schema "^2.0.0" has-ansi@^2.0.0: @@ -3735,12 +4483,13 @@ has@^1.0.0, has@^1.0.3: function-bind "^1.1.1" hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" @@ -3751,13 +4500,18 @@ hash.js@^1.0.0, hash.js@^1.0.3: minimalistic-assert "^1.0.1" hasha@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.1.0.tgz#dd05ccdfcfe7dab626247ce2a58efe461922f4ca" - integrity sha512-OFPDWmzPN1l7atOV1TgBVmNtBxaIysToK6Ve9DK+vT6pYuklw/nPNT+HJbZi0KDcI6vWB+9tgvZ5YD7fA3CXcA== + version "5.2.0" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.0.tgz#33094d1f69c40a4a6ac7be53d5fe3ff95a269e0c" + integrity sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw== dependencies: is-stream "^2.0.0" type-fest "^0.8.0" +he@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + hex-color-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" @@ -3772,7 +4526,12 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.3.0: +hoek@6.x.x: + version "6.1.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c" + integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ== + +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -3780,9 +4539,14 @@ hoist-non-react-statics@^3.3.0: react-is "^16.7.0" hosted-git-info@^2.1.4: - version "2.8.5" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" - integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== + version "2.8.8" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" + integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== + +hotkeys-js@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/hotkeys-js/-/hotkeys-js-3.8.1.tgz#fa7051f73bf1dc92a8b8d580a40b247f91966376" + integrity sha512-YlhVQtyG9f1b7GhtzdhR0Pl+cImD1ZrKI6zYUa7QLd0zuThiL7RzZ+ANJyy7z+kmcCpNYBf5PjBa3CjiQ5PFpw== hsl-regex@^1.0.0: version "1.0.0" @@ -3800,9 +4564,9 @@ html-comment-regex@^1.1.0: integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== html-escaper@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.0.tgz#71e87f931de3fe09e56661ab9a29aadec707b491" - integrity sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig== + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== htmlescape@^1.1.0: version "1.1.1" @@ -3810,9 +4574,9 @@ htmlescape@^1.1.0: integrity sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E= http-cache-semantics@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#13eeb612424bb113d52172c28a13109c46fa85d7" - integrity sha512-Z2EICWNJou7Tr9Bd2M2UqDJq3A9F2ePG9w3lIpjoyuSyXFP9QbniJVu3XQYytuw5ebmG7dXSXO9PgAjJG8DDKA== + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== http-errors@1.6.2: version "1.6.2" @@ -3824,6 +4588,17 @@ http-errors@1.6.2: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" +http-errors@^1.7.3: + version "1.8.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507" + integrity sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -3838,47 +4613,64 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +human-number@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/human-number/-/human-number-1.0.5.tgz#ab4b184f488f2237eeecac52d695ffbd0fe278de" + integrity sha512-U0vVDQuPGvvHKWAhI89rmiGChRTGCWRQ86J//zQDtlhyFFgKmJ7ehmAiUOXQBKUHGO7XZ3Z1bbhKE8zTuh5iVw== + dependencies: + round-to "~4.1.0" + hyphenate-style-name@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48" - integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ== + version "1.0.4" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" + integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ== -iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== +iconv-lite@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01" + integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ== dependencies: - safer-buffer ">= 2.1.2 < 3" + safer-buffer ">= 2.1.2 < 3.0.0" ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== -ignore-by-default@^1.0.0, ignore-by-default@^1.0.1: +ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= +ignore-by-default@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-2.0.0.tgz#537092018540640459569fe7c8c7a408af581146" + integrity sha512-+mQSgMRiFD3L3AOxLYOCxjIq4OnAmo5CIuC+lj5ehCJcPtV++QacEV7FdpzvYxH6DaOySWzQU6RR0lPLy37ckA== + ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== ignore@^5.1.1, ignore@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" - integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== -immer@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/immer/-/immer-6.0.5.tgz#77187d13b71c6cee40dde3b8e87a50a7a636d630" - integrity sha512-Q2wd90qrgFieIpLzAO2q9NLEdmyp/sr76Ml4Vm5peUKgyTa2CQa3ey8zuzwSKOlKH7grCeGBGUcLLVCVW1aguA== +immer@^7.0.7: + version "7.0.7" + resolved "https://registry.yarnpkg.com/immer/-/immer-7.0.7.tgz#9dfe713d49bf871cc59aedfce59b1992fa37a977" + integrity sha512-Q8yYwVADJXrNfp1ZUAh4XDHkcoE3wpdpb4mC5abDSajs2EbW8+cGdPyAnglMyLnm7EF6ojD2xBFX7L5i4TIytw== + +immutable@~3.7.6: + version "3.7.6" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b" + integrity sha1-E7TTyxK++hVIKib+Gy665kAHHks= import-fresh@^2.0.0: version "2.0.0" @@ -3896,6 +4688,13 @@ import-fresh@^3.0.0: parent-module "^1.0.0" resolve-from "^4.0.0" +import-from@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-3.0.0.tgz#055cfec38cd5a27d8057ca51376d7d3bf0891966" + integrity sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ== + dependencies: + resolve-from "^5.0.0" + import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" @@ -3915,9 +4714,9 @@ imurmurhash@^0.1.4: integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= in-publish@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" - integrity sha1-4g/146KvwmkDILbcVSaCqcf631E= + version "2.0.1" + resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.1.tgz#948b1a535c8030561cea522f73f78f4be357e00c" + integrity sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ== indent-string@^2.1.0: version "2.1.0" @@ -3949,7 +4748,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3984,25 +4783,6 @@ inline-style-prefixer@^4.0.0: bowser "^1.7.3" css-in-js-utils "^2.0.0" -inquirer@^7.0.0: - version "7.0.4" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.4.tgz#99af5bde47153abca23f5c7fc30db247f39da703" - integrity sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ== - dependencies: - ansi-escapes "^4.2.1" - chalk "^2.4.2" - cli-cursor "^3.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.15" - mute-stream "0.0.8" - run-async "^2.2.0" - rxjs "^6.5.3" - string-width "^4.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - insert-module-globals@^7.0.0: version "7.2.0" resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.0.tgz#ec87e5b42728479e327bd5c5c71611ddfb4752ba" @@ -4035,11 +4815,6 @@ invariant@^2.2.2, invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - irregular-plurals@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-3.2.0.tgz#b19c490a0723798db51b235d7e39add44dab0822" @@ -4072,10 +4847,10 @@ is-buffer@^1.1.0: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.4, is-callable@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" - integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-callable@^1.1.4, is-callable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" + integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== is-ci@^2.0.0: version "2.0.0" @@ -4138,7 +4913,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: +is-glob@4.0.1, is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -4146,9 +4921,9 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: is-extglob "^2.1.1" is-installed-globally@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.1.tgz#679afef819347a72584617fd19497f010b8ed35f" - integrity sha512-oiEcGoQbGc+3/iijAijrK2qFpkNoNjsHOm/5V5iaeydyrS/hnwaRCEgH5cpW0P3T1lSjV5piB7S5b5lEugNLhg== + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" + integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== dependencies: global-dirs "^2.0.1" is-path-inside "^3.0.1" @@ -4158,7 +4933,7 @@ is-interactive@^1.0.0: resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== -is-nan@^1.2.1: +is-nan@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.0.tgz#85d1f5482f7051c2019f5673ccebdb06f3b0db03" integrity sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ== @@ -4221,36 +4996,29 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= -is-plain-object@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928" - integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg== - dependencies: - isobject "^4.0.0" - -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= +is-plain-object@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-4.1.1.tgz#1a14d6452cbd50790edc7fdaa0aed5a40a35ebb5" + integrity sha512-5Aw8LLVsDlZsETVMhoMXzqsXwQqr/0vlnBYzIXJbYo2F4yYlhLHs+Ez7Bod7IIQKWkJbJfxrWD7pA1Dw1TKrwA== -is-promise@^4.0.0: +is-promise@4.0.0, is-promise@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== -is-regex@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" - integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== +is-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" + integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== dependencies: - has "^1.0.3" + has-symbols "^1.0.1" is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== -is-stream@1.1.0: +is-stream@1.1.0, is-stream@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= @@ -4324,10 +5092,13 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= -isobject@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" - integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== +isomorphic-fetch@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" isstream@~0.1.2: version "0.1.2" @@ -4347,14 +5118,11 @@ istanbul-lib-hook@^3.0.0: append-transform "^2.0.0" istanbul-lib-instrument@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz#61f13ac2c96cfefb076fe7131156cc05907874e6" - integrity sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== dependencies: "@babel/core" "^7.7.5" - "@babel/parser" "^7.7.5" - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" "@istanbuljs/schema" "^0.1.2" istanbul-lib-coverage "^3.0.0" semver "^6.3.0" @@ -4398,10 +5166,15 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +iterall@^1.1.3, iterall@^1.2.1, iterall@^1.2.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" + integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== + js-base64@^2.1.8: - version "2.5.2" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209" - integrity sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ== + version "2.6.3" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.3.tgz#7afdb9b57aa7717e15d370b66e8f36a9cb835dc3" + integrity sha512-fiUvdfCaAXoQTHdKMgTvg6IkecXDcVz6V5rlftUTclF9IKBjMizvSdQaCl/z/6TApDeby5NL+axYou3i0mu1Pg== js-cookie@^2.2.1: version "2.2.1" @@ -4419,9 +5192,9 @@ js-string-escape@^1.0.1: integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.10.0, js-yaml@^3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + version "3.14.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -4478,10 +5251,10 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" - integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== dependencies: minimist "^1.2.0" @@ -4492,6 +5265,15 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" +jsonfile@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" + integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg== + dependencies: + universalify "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -4512,12 +5294,12 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -jsx-ast-utils@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz#8a9364e402448a3ce7f14d357738310d9248054f" - integrity sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA== +jsx-ast-utils@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" + integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w== dependencies: - array-includes "^3.0.3" + array-includes "^3.1.1" object.assign "^4.1.0" kareem@2.3.1: @@ -4552,13 +5334,6 @@ lazy-ass@1.6.0: resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= - dependencies: - invert-kv "^1.0.0" - lcov-parse@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" @@ -4654,21 +5429,11 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= - lodash.flattendeep@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= -lodash.islength@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.islength/-/lodash.islength-4.0.1.tgz#4e9868d452575d750affd358c979543dc20ed577" - integrity sha1-Tpho1FJXXXUK/9NYyXlUPcIO1Xc= - lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -4679,20 +5444,20 @@ lodash.memoize@~3.0.3: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= -lodash.merge@^4.6.1: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.0.0, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@~4.17.12: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@4.17.19, lodash@^4.0.0, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@~4.17.10: + version "4.17.19" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" + integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== log-driver@^1.2.7: version "1.2.7" @@ -4706,11 +5471,21 @@ log-symbols@^3.0.0: dependencies: chalk "^2.4.2" +loglevel@^1.6.7: + version "1.6.8" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" + integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA== + long-timeout@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514" integrity sha1-lyHXiLR+C8taJMLivuGg2lXatRQ= +long@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -4726,6 +5501,13 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" +lower-case@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7" + integrity sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ== + dependencies: + tslib "^1.10.0" + lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -4744,10 +5526,17 @@ lru-cache@^4.0.1: pseudomap "^1.0.2" yallist "^2.1.2" -make-dir@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.2.tgz#04a1acbf22221e1d6ef43559f43e05a90dbb4392" - integrity sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w== +lru-cache@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^3.0.0, make-dir@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" @@ -4770,13 +5559,6 @@ matcher@^3.0.0: dependencies: escape-string-regexp "^4.0.0" -md5-hex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" - integrity sha1-0FiOnxx0lUSS7NJKwKxs6ZfZLjM= - dependencies: - md5-o-matic "^0.1.1" - md5-hex@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-3.0.1.tgz#be3741b510591434b2784d79e556eefc2c9a8e5c" @@ -4784,11 +5566,6 @@ md5-hex@^3.0.1: dependencies: blueimp-md5 "^2.10.0" -md5-o-matic@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" - integrity sha1-givM1l4RfFFPqxdrJZRdVBAKA8M= - md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -4838,11 +5615,11 @@ meow@^3.7.0: trim-newlines "^1.0.0" merge2@^1.2.3, merge2@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" - integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micro@^9.3.4: +micro@^9.3.2, micro@^9.3.4: version "9.3.4" resolved "https://registry.yarnpkg.com/micro/-/micro-9.3.4.tgz#745a494e53c8916f64fb6a729f8cbf2a506b35ad" integrity sha512-smz9naZwTG7qaFnEZ2vn248YZq9XR+XoOH3auieZbkhDL4xLOxiE+KqG8qqnBeKfXA9c1uEFGCxPN1D+nT6N7w== @@ -4875,17 +5652,17 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.43.0: - version "1.43.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" - integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== +mime-db@1.44.0: + version "1.44.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" + integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.26" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" - integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== + version "2.1.27" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" + integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== dependencies: - mime-db "1.43.0" + mime-db "1.44.0" mimic-fn@^2.1.0: version "2.1.0" @@ -4893,9 +5670,9 @@ mimic-fn@^2.1.0: integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== mimic-fn@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.0.0.tgz#76044cfa8818bbf6999c5c9acadf2d3649b14b4b" - integrity sha512-PiVO95TKvhiwgSwg1IdLYlCTdul38yZxZMIcnDSFIBUm4BNZha2qpQ4GpJ++15bHoKDtrW2D69lMfFwdFYtNZQ== + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" + integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" @@ -4919,27 +5696,22 @@ minimatch@^3.0.4, minimatch@~3.0.2: dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minimist@^1.2.5: +minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: - minimist "0.0.8" + minimist "^1.2.5" mocked-env@^1.3.2: version "1.3.2" @@ -4972,22 +5744,22 @@ module-deps@^6.0.0: through2 "^2.0.0" xtend "^4.0.0" -moment-timezone@^0.5.25: - version "0.5.27" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.27.tgz#73adec8139b6fe30452e78f210f27b1f346b8877" - integrity sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw== +moment-timezone@^0.5.31: + version "0.5.31" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.31.tgz#9c40d8c5026f0c7ab46eda3d63e49c155148de05" + integrity sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA== dependencies: moment ">= 2.9.0" "moment@>= 2.9.0": - version "2.24.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" - integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== + version "2.27.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.27.0.tgz#8bff4e3e26a236220dfe3e36de756b6ebaa0105d" + integrity sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ== -mongodb@3.5.7: - version "3.5.7" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.5.7.tgz#6dcfff3bdbf67a53263dcca1647c265eea1d065d" - integrity sha512-lMtleRT+vIgY/JhhTn1nyGwnSMmJkJELp+4ZbrjctrnBxuLbj6rmLuJFz8W2xUzUqWmqoyVxJLYuC58ZKpcTYQ== +mongodb@3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.6.0.tgz#babd7172ec717e2ed3f85e079b3f1aa29dce4724" + integrity sha512-/XWWub1mHZVoqEsUppE0GV7u9kanLvHxho6EvBxQbShXTKYF9trhZC2NzbulRGeG7xMJHD8IOWRcdKx5LPjAjQ== dependencies: bl "^2.2.0" bson "^1.1.4" @@ -5002,20 +5774,20 @@ mongoose-legacy-pluralize@1.0.2: resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4" integrity sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ== -mongoose@^5.9.13: - version "5.9.13" - resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.9.13.tgz#fa4af761a0b1d10471daa23aafcc775b04b6db42" - integrity sha512-MsFdJAaCTVbDA3gYskUEpUN1kThL7sp4zh8N9rGt0+9vYMn28q92NLK90vGssM9qjOGWp8HqLeT1fBgfMZDnKA== +mongoose@^5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.10.0.tgz#05a35f5a3d8485613c9988aeb9548285a97083f7" + integrity sha512-5itAvBMVDG4+zTDtuLg/IyoTxEMgvpOSHnigQ9Cyh8LR4BEgMAChJj7JSaGkg+tr1AjCSY9DgSdU8bHqCOoxXg== dependencies: bson "^1.1.4" kareem "2.3.1" - mongodb "3.5.7" + mongodb "3.6.0" mongoose-legacy-pluralize "1.0.2" mpath "0.7.0" mquery "3.2.2" ms "2.1.2" regexp-clone "1.0.0" - safe-buffer "5.1.2" + safe-buffer "5.2.1" sift "7.0.1" sliced "1.0.1" @@ -5050,15 +5822,15 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.13.2: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== +nan@^2.13.2, nan@^2.14.0: + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" + integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== nano-css@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.2.1.tgz#73b8470fa40b028a134d3393ae36bbb34b9fa332" - integrity sha512-T54okxMAha0+de+W8o3qFtuWhTxYvqQh2ku1cYEqTTP9mR62nWV2lLK9qRuAGWmoaYWhU7K4evT9Lc1iF65wuw== + version "5.3.0" + resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.3.0.tgz#9d3cd29788d48b6a07f52aa4aec7cf4da427b6b5" + integrity sha512-uM/9NGK9/E9/sTpbIZ/bQ9xOLOIHZwrrb/CRlbDHBU/GFS7Gshl24v/WJhwsVViWkpOXUmiZ66XO7fSB4Wd92Q== dependencies: css-tree "^1.0.0-alpha.28" csstype "^2.5.5" @@ -5079,11 +5851,32 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -node-fetch@^2.6.0: +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +no-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8" + integrity sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw== + dependencies: + lower-case "^2.0.1" + tslib "^1.10.0" + +node-fetch@2.6.0, node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== +node-fetch@^1.0.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + node-gyp@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" @@ -5102,6 +5895,11 @@ node-gyp@^3.8.0: tar "^2.0.0" which "1" +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + node-preload@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" @@ -5109,22 +5907,15 @@ node-preload@^0.2.1: dependencies: process-on-spawn "^1.0.0" -node-releases@^1.1.49: - version "1.1.49" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.49.tgz#67ba5a3fac2319262675ef864ed56798bb33b93e" - integrity sha512-xH8t0LS0disN0mtRCh+eByxFPie+msJUBL/lJDBuap53QGiYPa9joh83K4pCZgWJ+2L4b9h88vCVdXQ60NO2bg== - dependencies: - semver "^6.3.0" - -node-releases@^1.1.53: - version "1.1.53" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" - integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ== +node-releases@^1.1.58: + version "1.1.60" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" + integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== node-sass@^4.11.0: - version "4.13.1" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.13.1.tgz#9db5689696bb2eec2c32b98bfea4c7a2e992d0a3" - integrity sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw== + version "4.14.1" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5" + integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g== dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -5140,7 +5931,7 @@ node-sass@^4.11.0: node-gyp "^3.8.0" npmlog "^4.0.0" request "^2.88.0" - sass-graph "^2.2.4" + sass-graph "2.2.5" stdout-stream "^1.4.0" "true-case-path" "^1.0.2" @@ -5153,10 +5944,10 @@ node-schedule@^1.3.2: long-timeout "0.1.1" sorted-array-functions "^1.0.0" -nodemon@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.3.tgz#e9c64df8740ceaef1cb00e1f3da57c0a93ef3714" - integrity sha512-lLQLPS90Lqwc99IHe0U94rDgvjo+G9I4uEIxRG3evSLROcqQ9hwc0AxlSHKS4T1JW/IMj/7N5mthiN58NL/5kw== +nodemon@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.4.tgz#55b09319eb488d6394aa9818148c0c2d1c04c416" + integrity sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ== dependencies: chokidar "^3.2.2" debug "^3.2.6" @@ -5193,6 +5984,13 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package- semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -5214,9 +6012,9 @@ normalize-url@^4.1.0: integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== normalize-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-5.0.0.tgz#f46c9dc20670495e4e18fbd1b4396e41d199f63c" - integrity sha512-bAEm2fx8Dq/a35Z6PIRkkBBJvR56BbEJvhpNtvCZ4W9FyORSna77fn+xtYFjqk5JpBS+fMnAOG/wFgkQBmB7hw== + version "5.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-5.1.0.tgz#04b8f1b34ea49ff713fc20b2218eba41fb9974a3" + integrity sha512-UxHuSWsSAmzSqN+DSjasaZWQ3QPtEisHdlr4y9MJ5zg0RcImv5fQt8QM0izJSCdsdmhJGK+ubcTpJXwVDmwSVQ== normalize.css@^8.0.0: version "8.0.1" @@ -5240,6 +6038,11 @@ nth-check@^1.0.2: dependencies: boolbase "~1.0.0" +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" @@ -5250,10 +6053,10 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= -nyc@^15.0.1: - version "15.0.1" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.0.1.tgz#bd4d5c2b17f2ec04370365a5ca1fc0ed26f9f93d" - integrity sha512-n0MBXYBYRqa67IVt62qW1r/d9UH/Qtr7SF1w/nQLJ9KxvWF6b2xCHImRAixHN9tnMMYHC2P14uo6KddNGwMgGg== +nyc@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" + integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== dependencies: "@istanbuljs/load-nyc-config" "^1.0.0" "@istanbuljs/schema" "^0.1.2" @@ -5263,6 +6066,7 @@ nyc@^15.0.1: find-cache-dir "^3.2.0" find-up "^4.1.0" foreground-child "^2.0.0" + get-package-type "^0.1.0" glob "^7.1.6" istanbul-lib-coverage "^3.0.0" istanbul-lib-hook "^3.0.0" @@ -5293,15 +6097,20 @@ object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-inspect@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" - integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + version "1.8.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" + integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== +object-path@^0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.4.tgz#370ae752fbf37de3ea70a861c23bba8915691949" + integrity sha1-NwrnUvvzfePqcKhhwju6iRVpGUk= + object.assign@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" @@ -5312,14 +6121,13 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.entries@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b" - integrity sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ== +object.entries@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" + integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" + es-abstract "^1.17.5" has "^1.0.3" object.fromentries@^2.0.2: @@ -5358,12 +6166,19 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: wrappy "1" onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + version "5.1.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.1.tgz#5c8016847b0d67fcedb7eef254751cfcdc7e9418" + integrity sha512-ZpZpjcJeugQfWsfyQlshVoowIIQ1qBGSVll4rfDq6JJVO//fesjoX808hXWfBjY+ROZgpKDI5TRSRBSoJiZ8eg== dependencies: mimic-fn "^2.1.0" +optimism@^0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.12.1.tgz#933f9467b9aef0e601655adb9638f893e486ad02" + integrity sha512-t8I7HM1dw0SECitBYAqFOVHoBAHEQBTeKjIL9y9ImHzAVkdyPK4ifTgM4VJRDtTUY4r/u5Eqxs4XcGPHaoPkeQ== + dependencies: + "@wry/context" "^0.5.2" + optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -5376,10 +6191,10 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -ora@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.4.tgz#e8da697cc5b6a47266655bf68e0fb588d29a545d" - integrity sha512-77iGeVU1cIdRhgFzCK8aw1fbtT1B/iZAvWjS+l/o1x0RShMgxHUZaD2yDpWsNCPwXg9z1ZA78Kbdvr8kBmG/Ww== +ora@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.5.tgz#7410b5cc2d99fa637fd5099bbb9f02bfbb5a361e" + integrity sha512-jCDgm9DqvRcNIAEv2wZPrh7E5PcQiDUnbnWbAfu4NGAE2ZNqPFbDixmWldy1YG2QfLeQhuiu6/h5VRrk6cG50w== dependencies: chalk "^3.0.0" cli-cursor "^3.1.0" @@ -5400,14 +6215,7 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= - dependencies: - lcid "^1.0.0" - -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: +os-tmpdir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= @@ -5430,6 +6238,13 @@ p-defer@^1.0.0: resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= +p-limit@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + dependencies: + p-try "^2.0.0" + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -5438,9 +6253,9 @@ p-limit@^1.1.0: p-try "^1.0.0" p-limit@^2.0.0, p-limit@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" - integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" @@ -5533,7 +6348,7 @@ parents@^1.0.0, parents@^1.0.1: dependencies: path-platform "~0.11.15" -parse-asn1@^5.0.0: +parse-asn1@^5.0.0, parse-asn1@^5.1.5: version "5.1.5" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== @@ -5561,9 +6376,9 @@ parse-json@^4.0.0: json-parse-better-errors "^1.0.1" parse-json@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" - integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + version "5.0.1" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.1.tgz#7cfe35c1ccd641bce3981467e6c2ece61b3b3878" + integrity sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ== dependencies: "@babel/code-frame" "^7.0.0" error-ex "^1.3.1" @@ -5575,6 +6390,14 @@ parse-ms@^2.1.0: resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== +pascal-case@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f" + integrity sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA== + dependencies: + no-case "^3.0.3" + tslib "^1.10.0" + path-browserify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" @@ -5644,9 +6467,9 @@ path-type@^4.0.0: integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== pbkdf2@^3.0.3: - version "3.0.17" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== + version "3.1.1" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" + integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -5664,12 +6487,7 @@ permit@^0.2.4: resolved "https://registry.yarnpkg.com/permit/-/permit-0.2.4.tgz#3af2c8f5bd798f771be50eb59cecd1da6459a383" integrity sha512-Mp2XTEMD3mPsZIWq3bp0claE4IxXKa4C6nhSDPZgGri8Q4CLjEjAQrP/xGKq2548a2KFENmA1V7W0Lob8kTuzw== -picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7: - version "2.2.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" - integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== - -picomatch@^2.2.1, picomatch@^2.2.2: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1, picomatch@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== @@ -5731,17 +6549,10 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" - integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= - dependencies: - find-up "^2.1.0" - -platform@^1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.5.tgz#fb6958c696e07e2918d2eeda0f0bc9448d733444" - integrity sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q== +platform@^1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7" + integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg== plur@^4.0.0: version "4.0.0" @@ -5751,14 +6562,13 @@ plur@^4.0.0: irregular-plurals "^3.2.0" postcss-calc@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" - integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" + integrity sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ== dependencies: - css-unit-converter "^1.1.1" - postcss "^7.0.5" - postcss-selector-parser "^5.0.0-rc.4" - postcss-value-parser "^3.3.1" + postcss "^7.0.27" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.2" postcss-colormin@^4.0.3: version "4.0.3" @@ -5988,12 +6798,12 @@ postcss-selector-parser@^3.0.0: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^5.0.0-rc.4: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" - integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== +postcss-selector-parser@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" + integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== dependencies: - cssesc "^2.0.0" + cssesc "^3.0.0" indexes-of "^1.0.1" uniq "^1.0.1" @@ -6016,20 +6826,20 @@ postcss-unique-selectors@^4.0.1: postcss "^7.0.0" uniqs "^2.0.0" -postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.1: +postcss-value-parser@^3.0.0: version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" - integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.26, postcss@^7.0.5: - version "7.0.26" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587" - integrity sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA== +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.27, postcss@^7.0.32: + version "7.0.32" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" + integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -6052,11 +6862,6 @@ pretty-ms@^7.0.0: dependencies: parse-ms "^2.1.0" -private@^0.1.6, private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -6079,6 +6884,13 @@ progress@^2.0.0: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + dependencies: + asap "~2.0.3" + prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" @@ -6094,14 +6906,14 @@ pseudomap@^1.0.2: integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.28: - version "1.7.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" - integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== pstree.remy@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.7.tgz#c76963a28047ed61542dc361aa26ee55a7fa15f3" - integrity sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A== + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== public-encrypt@^4.0.0: version "4.0.3" @@ -6215,27 +7027,34 @@ react-dom@^16.13.1: prop-types "^15.6.2" scheduler "^0.19.1" -react-error-boundary@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-2.2.1.tgz#32ed74386a90482060cc2fea948bb7135465c4cb" - integrity sha512-8SZMkJRFUb0JuluHKwuUtkh5vvVWBg3O/bJIWgNMhMJv529aG//TmcphR3cSMhCWjz1vFZDb4taJd6pmwP5mEQ== +react-error-boundary@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-2.3.1.tgz#bd6c8a9777224b6a1153c5f63e1ac86bf039f657" + integrity sha512-w1i++MM5GV6WTnM3MtLdw9CNXxqydkZwbwNDT9GBFBaWs0sp21z27DGIevb3fism1T+LGfdWgTFlhaq7G1pIMA== dependencies: - "@babel/runtime" "^7.9.6" + "@babel/runtime" "^7.10.5" -react-fast-compare@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.1.1.tgz#0becf31e3812fa70dc231e259f40d892d4767900" - integrity sha512-SCsAORWK59BvauR2L1BTdjQbJcSGJJz03U0awektk2hshLKrITDDFTlgGCqIZpTDlPC/NFlZee6xTMzXPVLiHw== +react-fast-compare@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" + integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== + +react-hotkeys-hook@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/react-hotkeys-hook/-/react-hotkeys-hook-2.2.2.tgz#ed47e3753b85cf7c1123ec9121282397cf875fe9" + integrity sha512-5XBGCSleJZ7AzQ+wCoFeJj/myByIzqgR3D97xRNEQsGOsFvXLp4V8rbDbHceTqGq7WDjQmX96zegViz8U5CwMQ== + dependencies: + hotkeys-js "3.8.1" react-is@^16.7.0, react-is@^16.8.1, react-is@^16.9.0: - version "16.12.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" - integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-redux@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d" - integrity sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA== +react-redux@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.1.tgz#8dedf784901014db2feca1ab633864dee68ad985" + integrity sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg== dependencies: "@babel/runtime" "^7.5.5" hoist-non-react-statics "^3.3.0" @@ -6243,24 +7062,30 @@ react-redux@^7.2.0: prop-types "^15.7.2" react-is "^16.9.0" -react-use@^14.2.0: - version "14.2.0" - resolved "https://registry.yarnpkg.com/react-use/-/react-use-14.2.0.tgz#abac033fae5e358599b7e38084ff11b02e5d4868" - integrity sha512-vwC7jsBsiDENLrXGPqIH3W4mMS2j24h5jp4ol3jiiUQzZhCaG+ihumrShJxBI59hXso1pLHAePRQAg/fJjDcaQ== +react-universal-interface@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b" + integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw== + +react-use@^15.3.3: + version "15.3.3" + resolved "https://registry.yarnpkg.com/react-use/-/react-use-15.3.3.tgz#f16de7a16286c446388e8bd99680952fc3dc9a95" + integrity sha512-nYb94JbmDCaLZg3sOXmFW8HN+lXWxnl0caspXoYfZG1CON8JfLN9jMOyxRDUpm7dUq7WZ5mIept/ByqBQKJ0wQ== dependencies: "@types/js-cookie" "2.2.6" "@xobotyi/scrollbar-width" "1.9.5" copy-to-clipboard "^3.2.0" - fast-deep-equal "^3.1.1" + fast-deep-equal "^3.1.3" fast-shallow-equal "^1.0.0" js-cookie "^2.2.1" nano-css "^5.2.1" + react-universal-interface "^0.6.2" resize-observer-polyfill "^1.5.1" screenfull "^5.0.0" set-harmonic-interval "^1.0.1" throttle-debounce "^2.1.0" ts-easing "^0.2.0" - tslib "^1.10.0" + tslib "^2.0.0" react@^16.13.1: version "16.13.1" @@ -6335,7 +7160,7 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6: +readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -6344,13 +7169,6 @@ readable-stream@^3.0.6: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdirp@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17" - integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ== - dependencies: - picomatch "^2.0.7" - readdirp@~3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" @@ -6384,13 +7202,6 @@ redux@^4.0.5: loose-envify "^1.4.0" symbol-observable "^1.2.0" -regenerate-unicode-properties@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" - integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" @@ -6399,34 +7210,21 @@ regenerate-unicode-properties@^8.2.0: regenerate "^1.4.0" regenerate@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== - -regenerator-runtime@^0.13.2: - version "0.13.3" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" - integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== + version "1.4.1" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f" + integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A== regenerator-runtime@^0.13.4: - version "0.13.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" - integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== - -regenerator-transform@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" - integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== - dependencies: - private "^0.1.6" + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== regenerator-transform@^0.14.2: - version "0.14.4" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" - integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== + version "0.14.5" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== dependencies: "@babel/runtime" "^7.8.4" - private "^0.1.8" regexp-clone@1.0.0, regexp-clone@^1.0.0: version "1.0.0" @@ -6446,18 +7244,6 @@ regexpp@^3.1.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== -regexpu-core@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" - integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.1.0" - regjsgen "^0.5.0" - regjsparser "^0.6.0" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.1.0" - regexpu-core@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" @@ -6471,9 +7257,9 @@ regexpu-core@^4.7.0: unicode-match-property-value-ecmascript "^1.2.0" registry-auth-token@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479" - integrity sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA== + version "4.2.0" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.0.tgz#1d37dffda72bbecd0f581e4715540213a65eb7da" + integrity sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w== dependencies: rc "^1.2.8" @@ -6484,17 +7270,10 @@ registry-url@^5.0.0: dependencies: rc "^1.2.8" -regjsgen@^0.5.0, regjsgen@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" - integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== - -regjsparser@^0.6.0: - version "0.6.3" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.3.tgz#74192c5805d35e9f5ebe3c1fb5b40d40a8a38460" - integrity sha512-8uZvYbnfAtEm9Ab8NTb3hdLwL4g/LQzEYP7Xs27T96abJCCE2d6r3cPZPQEsLKy0vRSGVNG+/zVGtLr86HQduA== - dependencies: - jsesc "~0.5.0" +regjsgen@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== regjsparser@^0.6.4: version "0.6.4" @@ -6503,6 +7282,36 @@ regjsparser@^0.6.4: dependencies: jsesc "~0.5.0" +relay-compiler@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/relay-compiler/-/relay-compiler-10.0.1.tgz#d3029a5121cad52e1e55073210365b827cee5f3b" + integrity sha512-hrTqh81XXxPB4EgvxPmvojICr0wJnRoumxOsMZnS9dmhDHSqcBAT7+C3+rdGm5sSdNH8mbMcZM7YSPDh8ABxQw== + dependencies: + "@babel/core" "^7.0.0" + "@babel/generator" "^7.5.0" + "@babel/parser" "^7.0.0" + "@babel/runtime" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + babel-preset-fbjs "^3.3.0" + chalk "^4.0.0" + fb-watchman "^2.0.0" + fbjs "^1.0.0" + glob "^7.1.1" + immutable "~3.7.6" + nullthrows "^1.1.1" + relay-runtime "10.0.1" + signedsource "^1.0.0" + yargs "^15.3.1" + +relay-runtime@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/relay-runtime/-/relay-runtime-10.0.1.tgz#c83bd7e6e37234ece2a62a254e37dd199a4f74f9" + integrity sha512-sPYiuosq+5gQ7zXs2EKg2O8qRSsF8vmMYo6SIHEi4juBLg1HrdTEvqcaNztc2ZFmUc4vYZpTbbS4j/TZCtHuyA== + dependencies: + "@babel/runtime" "^7.0.0" + fbjs "^1.0.0" + release-zalgo@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" @@ -6510,6 +7319,11 @@ release-zalgo@^1.0.0: dependencies: es6-error "^4.0.1" +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" @@ -6555,11 +7369,6 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= - require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" @@ -6585,6 +7394,11 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" +resolve-from@5.0.0, resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" @@ -6600,20 +7414,15 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.1.4, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.4.0: - version "1.15.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" - integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== +resolve@^1.1.4, resolve@^1.10.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.4.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== dependencies: path-parse "^1.0.6" @@ -6632,7 +7441,12 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -reusify@^1.0.0: +retry@0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= + +reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== @@ -6701,6 +7515,11 @@ rosid-handler-sass@^7.0.0: node-sass "^4.11.0" postcss "^7.0.14" +round-to@~4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/round-to/-/round-to-4.1.0.tgz#148d768d18b2f127f78e6648cb8b0a5943c416bf" + integrity sha512-H/4z+4QdWS82iMZ23+5St302Mv2jJws0hUvEogrD6gC8NN6Z5TalDtbg51owCrVy4V/4c8ePvwVLNtlhEfPo5g== + rtl-css-js@^1.9.0: version "1.14.0" resolved "https://registry.yarnpkg.com/rtl-css-js/-/rtl-css-js-1.14.0.tgz#daa4f192a92509e292a0519f4b255e6e3c076b7d" @@ -6708,41 +7527,27 @@ rtl-css-js@^1.9.0: dependencies: "@babel/runtime" "^7.1.2" -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= - dependencies: - is-promise "^2.1.0" - run-parallel@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== -rxjs@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" - integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== - dependencies: - tslib "^1.9.0" - -s-ago@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/s-ago/-/s-ago-2.1.0.tgz#70ac180803cbb6af22480caa379215d6abb6b50e" - integrity sha512-7leN5IaS79lNyO3s47NHQfMBgYLjx0IEWipN1VSf5uX7Jp1N8sX/2TrNJX30MPM63admF10hQOZFCzej8O4t3g== +s-ago@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/s-ago/-/s-ago-2.2.0.tgz#4143a9d0176b3100dcf649c78e8a1ec8a59b1312" + integrity sha512-t6Q/aFCCJSBf5UUkR/WH0mDHX8EGm2IBQ7nQLobVLsdxOlkryYMbOlwu2D4Cf7jPUp0v1LhfPgvIZNoi9k8lUA== safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -6754,15 +7559,15 @@ saslprep@^1.0.0: dependencies: sparse-bitfield "^3.0.3" -sass-graph@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" - integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k= +sass-graph@2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8" + integrity sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag== dependencies: glob "^7.0.0" lodash "^4.0.0" scss-tokenizer "^0.2.3" - yargs "^7.0.0" + yargs "^13.3.2" sax@~1.2.4: version "1.2.4" @@ -6797,7 +7602,7 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.4.1, semver@^5.5.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -6812,7 +7617,7 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.2.1: +semver@^7.2.1, semver@^7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== @@ -6837,12 +7642,22 @@ set-harmonic-interval@^1.0.1: resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz#e1773705539cdfb80ce1c3d99e7f298bb3995249" integrity sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g== +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + setprototypeof@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" integrity sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ= -sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8, sha.js@~2.4.4: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== @@ -6903,9 +7718,9 @@ sift@7.0.1: integrity sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g== signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== signale@^1.4.0: version "1.4.0" @@ -6916,10 +7731,15 @@ signale@^1.4.0: figures "^2.0.0" pkg-conf "^2.1.0" -simple-concat@^1.0.0: +signedsource@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= + resolved "https://registry.yarnpkg.com/signedsource/-/signedsource-1.0.0.tgz#1ddace4981798f93bd833973803d80d52e93ad6a" + integrity sha1-HdrOSYF5j5O9gzlzgD2A1S6TrWo= + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== simple-swizzle@^0.2.2: version "0.2.2" @@ -6961,7 +7781,7 @@ sorted-array-functions@^1.0.0: resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.2.0.tgz#43265b21d6e985b7df31621b1c11cc68d8efc7c3" integrity sha512-sWpjPhIZJtqO77GN+LD8dDsDKcWZ9GCOJNqKzi1tvtjGIzwfoyuRH8S0psunmc6Z5P+qfDqztSbwYR5X/e1UTg== -source-map-support@^0.5.19: +source-map-support@^0.5.19, source-map-support@~0.5.12: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== @@ -6969,14 +7789,6 @@ source-map-support@^0.5.19: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@~0.5.12: - version "0.5.16" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" - integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map@0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" @@ -7024,22 +7836,22 @@ spawn-wrap@^2.0.0: which "^2.0.1" spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" @@ -7089,9 +7901,9 @@ stack-utils@^2.0.2: escape-string-regexp "^2.0.0" stackframe@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.1.1.tgz#ffef0a3318b1b60c3b58564989aca5660729ec71" - integrity sha512-0PlYhdKh6AfFxRyK/v+6/k+/mMfyiEBbTM5L94D0ZytQnJ166wuwoTYLHFWGbs2dpA8Rgq763KGWmN1EQEYHRQ== + version "1.2.0" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" + integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA== stacktrace-gps@^3.0.4: version "3.0.4" @@ -7110,7 +7922,7 @@ stacktrace-js@^2.0.0: stack-generator "^2.0.5" stacktrace-gps "^3.0.4" -"statuses@>= 1.3.1 < 2": +"statuses@>= 1.3.1 < 2", "statuses@>= 1.5.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= @@ -7139,14 +7951,14 @@ stream-combiner2@^1.1.1: readable-stream "^2.0.2" stream-http@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.0.tgz#22fb33fe9b4056b4eccf58bd8f400c4b993ffe57" - integrity sha512-cuB6RgO7BqC4FBYzmnvhob5Do3wIdIsXAgGycHJnW+981gHqoYcYz9lqjJrk8WXRddbwPuqPYRl+bag6mYv4lw== + version "3.1.1" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.1.tgz#0370a8017cf8d050b9a8554afe608f043eaff564" + integrity sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg== dependencies: builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^3.0.6" - xtend "^4.0.0" + inherits "^2.0.4" + readable-stream "^3.6.0" + xtend "^4.0.2" stream-splicer@^2.0.0: version "2.0.1" @@ -7156,7 +7968,12 @@ stream-splicer@^2.0.0: inherits "^2.0.1" readable-stream "^2.0.2" -string-width@^1.0.1, string-width@^1.0.2: +streamsearch@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" + integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= + +string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= @@ -7173,7 +7990,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: +string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== @@ -7203,21 +8020,21 @@ string.prototype.matchall@^4.0.2: regexp.prototype.flags "^1.3.0" side-channel "^1.0.2" -string.prototype.trimleft@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" - integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== +string.prototype.trimend@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" + integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== dependencies: define-properties "^1.1.3" - function-bind "^1.1.1" + es-abstract "^1.17.5" -string.prototype.trimright@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" - integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== +string.prototype.trimstart@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" + integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== dependencies: define-properties "^1.1.3" - function-bind "^1.1.1" + es-abstract "^1.17.5" string_decoder@^1.1.1: version "1.3.0" @@ -7247,7 +8064,7 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.1.0: +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== @@ -7286,9 +8103,9 @@ strip-indent@^1.0.1: get-stdin "^4.0.1" strip-json-comments@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180" - integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w== + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== strip-json-comments@~2.0.1: version "2.0.1" @@ -7316,6 +8133,17 @@ subarg@^1.0.0: dependencies: minimist "^1.1.0" +subscriptions-transport-ws@0.9.17, subscriptions-transport-ws@^0.9.11: + version "0.9.17" + resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.17.tgz#e30e40f0caae0d2781903c01a8cb51b6e2682098" + integrity sha512-hNHi2N80PBz4T0V0QhnnsMGvG3XDFDS9mS6BhZ3R12T6EBywC8d/uJscsga0cVO4DKtXCkCRrWm2sOYrbOdhEA== + dependencies: + backo2 "^1.0.2" + eventemitter3 "^3.1.0" + iterall "^1.2.1" + symbol-observable "^1.0.4" + ws "^5.2.0" + supertap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supertap/-/supertap-1.0.0.tgz#bd9751c7fafd68c68cf8222a29892206a119fa9e" @@ -7372,7 +8200,7 @@ svgo@^1.0.0: unquote "~1.1.1" util.promisify "~1.0.0" -symbol-observable@^1.2.0: +symbol-observable@^1.0.4, symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== @@ -7414,9 +8242,9 @@ term-size@^2.1.0: integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== terser@^4.0.0: - version "4.6.3" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.3.tgz#e33aa42461ced5238d352d2df2a67f21921f8d87" - integrity sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ== + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -7442,9 +8270,9 @@ text-table@^0.2.0: integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= throttle-debounce@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5" - integrity sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg== + version "2.2.1" + resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.2.1.tgz#fbd933ae6793448816f7d5b3cae259d464c98137" + integrity sha512-i9hAVld1f+woAiyNGqWelpDD5W1tpMroL3NofTz9xzwq6acWBlO2dC8k5EFSZepU6oOINtV5Q3aSPoRg7o4+fA== through2@^2.0.0: version "2.0.5" @@ -7454,7 +8282,7 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -"through@>=2.2.7 <3", through@^2.3.6: +"through@>=2.2.7 <3": version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -7476,13 +8304,6 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -7505,6 +8326,11 @@ toggle-selection@^1.0.6: resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + touch@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" @@ -7542,10 +8368,32 @@ ts-easing@^0.2.0: resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec" integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ== -tslib@^1.10.0, tslib@^1.9.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +ts-invariant@^0.4.0, ts-invariant@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.4.4.tgz#97a523518688f93aafad01b0e80eb803eb2abd86" + integrity sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA== + dependencies: + tslib "^1.9.3" + +tsconfig-paths@^3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" + integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + +tslib@^1.10.0, tslib@^1.9.3: + version "1.13.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" + integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + +tslib@^2.0.0, tslib@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" + integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== tty-browserify@0.0.1: version "0.0.1" @@ -7586,6 +8434,16 @@ type-fest@^0.8.0, type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" + integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -7598,6 +8456,11 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +ua-parser-js@^0.7.18: + version "0.7.21" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777" + integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ== + umd@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" @@ -7634,20 +8497,15 @@ unicode-match-property-ecmascript@^1.0.4: unicode-canonical-property-names-ecmascript "^1.0.4" unicode-property-aliases-ecmascript "^1.0.4" -unicode-match-property-value-ecmascript@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" - integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== - unicode-match-property-value-ecmascript@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" - integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== uniq@^1.0.1: version "1.0.1" @@ -7666,6 +8524,18 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" +universalify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" + integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== + +unixify@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090" + integrity sha1-OmQcjC/7zk2mg6XHDwOkYpQMIJA= + dependencies: + normalize-path "^2.1.1" + unpipe@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -7727,7 +8597,7 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -util.promisify@~1.0.0: +util.promisify@^1.0.0, util.promisify@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== @@ -7751,7 +8621,7 @@ util@~0.10.1: dependencies: inherits "2.0.3" -uuid@^3.3.2, uuid@^3.3.3: +uuid@^3.1.0, uuid@^3.3.2, uuid@^3.3.3: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -7761,15 +8631,20 @@ uuid@^7.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== -uuid@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" - integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== +uuid@^8.0.0, uuid@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea" + integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ== v8-compile-cache@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" - integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" + integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== + +valid-url@1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" + integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA= validate-npm-package-license@^3.0.1: version "3.0.4" @@ -7798,6 +8673,14 @@ vm-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +vue-template-compiler@^2.6.11: + version "2.6.11" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz#c04704ef8f498b153130018993e56309d4698080" + integrity sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA== + dependencies: + de-indent "^1.0.2" + he "^1.1.0" + wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" @@ -7805,15 +8688,26 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +websocket@1.0.31: + version "1.0.31" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.31.tgz#e5d0f16c3340ed87670e489ecae6144c79358730" + integrity sha512-VAouplvGKPiKFDTeCCO65vYHsyay8DqoBSlzIO3fayrfOgU94lQN5a1uWVnFrMLceTJw/+fQXR5PGbUVRaHshQ== + dependencies: + debug "^2.2.0" + es5-ext "^0.10.50" + nan "^2.14.0" + typedarray-to-buffer "^3.1.5" + yaeti "^0.0.6" + well-known-symbols@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/well-known-symbols/-/well-known-symbols-2.0.0.tgz#e9c7c07dbd132b7b84212c8174391ec1f9871ba5" integrity sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q== -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= +whatwg-fetch@>=0.10.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.2.0.tgz#8e134f701f0a4ab5fda82626f113e2b647fd16dc" + integrity sha512-SdGPoQMMnzVYThUbSrEvqTlkvC1Ux27NehaJ/GUHBfNrh5Mjg+1/uRyFMwVnxO2MrikMWvWAqUGgQOfVU4hT7w== which-module@^2.0.0: version "2.0.0" @@ -7853,13 +8747,14 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" wrap-ansi@^6.2.0: version "6.2.0" @@ -7875,17 +8770,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.1.tgz#558328352e673b5bb192cf86500d60b230667d4b" - integrity sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -write-file-atomic@^3.0.3: +write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== @@ -7902,82 +8787,94 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" +ws@^5.2.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" + integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== + dependencies: + async-limiter "~1.0.0" + +ws@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" + xdg-basedir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== -xregexp@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50" - integrity sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g== +xss@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.8.tgz#32feb87feb74b3dcd3d404b7a68ababf10700535" + integrity sha512-3MgPdaXV8rfQ/pNn16Eio6VXYPTkqwa0vc7GkiymmY/DqR1SE/7VPAAVZz1GJsJFrllMYO3RHfEaiUGjab6TNw== dependencies: - "@babel/runtime-corejs3" "^7.8.3" + commander "^2.20.3" + cssfilter "0.0.10" xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= - y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yargs-parser@^16.1.0: - version "16.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-16.1.0.tgz#73747d53ae187e7b8dbe333f95714c76ea00ecf1" - integrity sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^18.1.1: - version "18.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.2.tgz#2f482bea2136dbde0861683abea7756d30b504f1" - integrity sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ== +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= - dependencies: - camelcase "^3.0.0" - -yargs@^15.0.2: - version "15.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.1.0.tgz#e111381f5830e863a89550bd4b136bb6a5f37219" - integrity sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg== +yargs@^13.3.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" + cliui "^5.0.0" + find-up "^3.0.0" get-caller-file "^2.0.1" require-directory "^2.1.1" require-main-filename "^2.0.0" set-blocking "^2.0.0" - string-width "^4.2.0" + string-width "^3.0.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^16.1.0" + yargs-parser "^13.1.2" -yargs@^15.3.1: - version "15.3.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" - integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== +yargs@^15.0.2, yargs@^15.3.1, yargs@^15.4.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: cliui "^6.0.0" decamelize "^1.2.0" @@ -7989,23 +8886,17 @@ yargs@^15.3.1: string-width "^4.2.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^18.1.1" + yargs-parser "^18.1.2" -yargs@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^5.0.0" +zen-observable-ts@^0.8.21: + version "0.8.21" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz#85d0031fbbde1eba3cd07d3ba90da241215f421d" + integrity sha512-Yj3yXweRc8LdRMrCC8nIc4kkjWecPAUVh0TI0OUrWXx6aX790vLcDlWca6I4vsyCGH3LpWxq0dJRcMOFoVqmeg== + dependencies: + tslib "^1.9.3" + zen-observable "^0.8.0" + +zen-observable@^0.8.0, zen-observable@^0.8.14: + version "0.8.15" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" + integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==