diff --git a/.github/ISSUE_TEMPLATE/--bug-report.md b/.github/ISSUE_TEMPLATE/--bug-report.md index b0d61217880..417f1eee1f8 100644 --- a/.github/ISSUE_TEMPLATE/--bug-report.md +++ b/.github/ISSUE_TEMPLATE/--bug-report.md @@ -5,6 +5,10 @@ label: bug --- +**If you need support for Nightscout, PLEASE DO NOT FILE A TICKET HERE** +For support, please post a question to the "CGM in The Cloud" group in Facebook +(https://www.facebook.com/groups/cgminthecloud) or visit the WeAreNotWaiting Discord at https://discord.gg/zg7CvCQ + **Describe the bug** A clear and concise description of what the bug is. diff --git a/.github/ISSUE_TEMPLATE/--feature-request--.md b/.github/ISSUE_TEMPLATE/--feature-request--.md index a94a261abf8..293efbc9c1e 100644 --- a/.github/ISSUE_TEMPLATE/--feature-request--.md +++ b/.github/ISSUE_TEMPLATE/--feature-request--.md @@ -4,6 +4,10 @@ about: Suggest an idea for this project --- +**If you need support for Nightscout, PLEASE DO NOT FILE A TICKET HERE** +For support, please post a question to the "CGM in The Cloud" group in Facebook +(https://www.facebook.com/groups/cgminthecloud) or visit the WeAreNotWaiting Discord at https://discord.gg/zg7CvCQ + **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] diff --git a/.github/ISSUE_TEMPLATE/--individual-troubleshooting-help.md b/.github/ISSUE_TEMPLATE/--individual-troubleshooting-help.md deleted file mode 100644 index ff6e27b7682..00000000000 --- a/.github/ISSUE_TEMPLATE/--individual-troubleshooting-help.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -name: "\U0001F198Individual troubleshooting help" -about: Getting help with your own individual setup of Nightscout - ---- - -Having issues getting Nightscout up and running? Instead of creating an issue here, please use one of the existing support channels for Nightscout. - -The main support channel is on Facebook: please join the CGM In The Cloud Facebook group (https://www.facebook.com/groups/cgminthecloud) and start a post there. - -**Suggestions to include in your post when you are asking for help:** -1. Include what you are trying to do: ("*I am trying to set up Nightscout for the first time.*") -2. Include which step you are on and what the problem is: ("*I deployed on Heroku, but I'm not seeing any BG data.*") -3. If possible, include a link to the version of documentation you are following ("*I'm following the OpenAPS Nightscout setup docs (https://openaps.readthedocs.io/en/latest/docs/While%20You%20Wait%20For%20Gear/nightscout-setup.html#nightscout-setup-with-heroku)*") - -Other places you can find support and assistance for Nightscout include Gitter's [nightscout/public](https://gitter.im/nightscout/public) channel. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000000..659a213d692 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Troubleshooting Documentation + url: http://nightscout.github.io/troubleshoot/troublehoot/ + about: Having trouble with Nightscout? Please check our step by step troubleshooting instructions. + - name: Nightscout Community Support in Facebook + url: https://www.facebook.com/groups/cgminthecloud + about: If you're a Nightscout user and have trouble with your site, please post questions here. We don't have the resources to answer support questions posted here as tickets. + - name: Nightscout Community Support in Discord + url: https://discord.gg/zg7CvCQ + about: If you're a Nightscout user and have trouble with your site, please post questions here. We don't have the resources to answer support questions posted here as tickets. diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000000..ab1a7b17096 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,68 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# ******** NOTE ******** + +name: "CodeQL" + +on: + push: + branches: [ dev ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ master ] + schedule: + - cron: '43 23 * * 3' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + language: [ 'javascript' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 23cc61e5ef7..e661a61ab7b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,6 @@ name: CI test -on: [push] +on: [push, pull_request] jobs: build: @@ -9,7 +9,7 @@ jobs: strategy: matrix: - node-version: [10.x, 12.x] + node-version: [12.x] steps: - uses: actions/checkout@v1 @@ -21,12 +21,14 @@ jobs: run: npm install - name: Install MongoDB run: | - wget -qO - https://www.mongodb.org/static/pgp/server-3.6.asc | sudo apt-key add - - echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list + wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add - + echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list sudo apt-get update sudo apt-get install -y mongodb-org - sudo apt-get install -y --allow-downgrades mongodb-org=3.6.14 mongodb-org-server=3.6.14 mongodb-org-shell=3.6.14 mongodb-org-mongos=3.6.14 mongodb-org-tools=3.6.14 + sudo apt-get install -y --allow-downgrades mongodb-org=4.4.0 mongodb-org-server=4.4.0 mongodb-org-shell=4.4.0 mongodb-org-mongos=4.4.0 mongodb-org-tools=4.4.0 - name: Start MongoDB run: sudo systemctl start mongod - - name: Run tests + - name: Run Tests run: npm run-script test-ci + - name: Send Coverage + run: npm run-script coverage diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c8e87e2db4a..7beea2d51a3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,7 +34,7 @@ [coverage-img]: https://img.shields.io/coveralls/nightscout/cgm-remote-monitor/master.svg [coverage-url]: https://coveralls.io/r/nightscout/cgm-remote-monitor?branch=master [discord-img]: https://img.shields.io/discord/629952586895851530?label=discord%20chat -[discord-url]: https://discordapp.com/channels/629952586895851530/629952669967974410 +[discord-url]: https://discord.gg/rTKhrqz ## Installation for development @@ -181,6 +181,7 @@ Also if you can't code, it's possible to contribute by improving the documentati [@unsoluble]: https://github.com/unsoluble [@viderehh]: https://github.com/viderehh [@OpossumGit]: https://github.com/OpossumGit +[@Bartlomiejsz]: https://github.com/Bartlomiejsz | Contribution area | List of contributors | | ------------------------------------- | ---------------------------------- | @@ -252,7 +253,7 @@ Languages with less than 90% coverage will be removed in a future Nightscout ver | 한국어 (`ko`)|Please volunteer|Needs attention: 80.6%| | Norsk (Bokmål) (`nb`)|Please volunteer|OK| | Nederlands (`nl`)|[@PieterGit]|OK| -| Polski (`pl`)|Please volunteer|OK| +| Polski (`pl`)|[@Bartlomiejsz]|OK| | Português (Brasil) (`pt`)|Please volunteer|OK| | Română (`ro`)|Please volunteer|OK| | Русский (`ru`)|[@apanasef]|OK| diff --git a/README.md b/README.md index f4a0452dd9d..b6860841242 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Nightscout Web Monitor (a.k.a. cgm-remote-monitor) [![Codacy Badge][codacy-img]][codacy-url] [![Discord chat][discord-img]][discord-url] -[![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://azuredeploy.net/) [![Deploy to Heroku][heroku-img]][heroku-url] [![Update your site][update-img]][update-fork] +[![Deploy to Heroku][heroku-img]][heroku-url] [![Update your site][update-img]][update-fork] This acts as a web-based CGM (Continuous Glucose Monitor) to allow multiple caregivers to remotely view a patient's glucose data in @@ -20,10 +20,21 @@ and blood glucose values are predicted 0.5 hours ahead using an autoregressive second order model. Alarms are generated for high and low values, which can be cleared by any watcher of the data. -# [#WeAreNotWaiting](https://twitter.com/hashtag/wearenotwaiting?src=hash&vertical=default&f=images) and [this](https://vimeo.com/109767890) is why. +# Looking for documentation? -Community maintained fork of the -[original cgm-remote-monitor][original]. +## End user? + +Nightscout documentation is currently split to two locations. This page lists all the configuration options in +Nightscout and is useful for users who've already gone through the installation process. IF you're looking +for the documentation that looks like it's written for non-programmers, that's located at [nightscout.github.io](https://nightscout.github.io/). + +Older documentation is available at [nightscout.info](http://nightscout.info). + +## Developer? + +See [CONTRIBUTING.md](CONTRIBUTING.md) + +## [#WeAreNotWaiting](https://twitter.com/hashtag/wearenotwaiting?src=hash&vertical=default&f=images) and [this](https://vimeo.com/109767890) is why. [![Coverage Status](https://coveralls.io/repos/github/nightscout/cgm-remote-monitor/badge.svg?branch=master)](https://coveralls.io/github/nightscout/cgm-remote-monitor?branch=master) @@ -38,34 +49,36 @@ Community maintained fork of the [discord-img]: https://img.shields.io/discord/629952586895851530?label=discord%20chat [discord-url]: https://discord.gg/rTKhrqz [heroku-img]: https://www.herokucdn.com/deploy/button.png -[heroku-url]: https://heroku.com/deploy +[heroku-url]: https://heroku.com/deploy?template=https://github.com/nightscout/cgm-remote-monitor [update-img]: update.png [update-fork]: http://nightscout.github.io/pages/update-fork/ [original]: https://github.com/rnpenguin/cgm-remote-monitor + **Table of Contents** - [Install](#install) - [Supported configurations:](#supported-configurations) - - [Minimum browser requirements for viewing the site:](#minimum-browser-requirements-for-viewing-the-site) + - [Recommended minimum browser versions for using Nightscout:](#recommended-minimum-browser-versions-for-using-nightscout) - [Windows installation software requirements:](#windows-installation-software-requirements) - [Installation notes for users with nginx or Apache reverse proxy for SSL/TLS offloading:](#installation-notes-for-users-with-nginx-or-apache-reverse-proxy-for-ssltls-offloading) - [Installation notes for Microsoft Azure, Windows:](#installation-notes-for-microsoft-azure-windows) +- [Development](#development) - [Usage](#usage) - [Updating my version?](#updating-my-version) - - [What is my mongo string?](#what-is-my-mongo-string) - [Configure my uploader to match](#configure-my-uploader-to-match) - [Nightscout API](#nightscout-api) - [Example Queries](#example-queries) - [Environment](#environment) - [Required](#required) - - [Features/Labs](#featureslabs) + - [Features](#features) - [Alarms](#alarms) - [Core](#core) - [Predefined values for your browser settings (optional)](#predefined-values-for-your-browser-settings-optional) - [Predefined values for your server settings (optional)](#predefined-values-for-your-server-settings-optional) + - [Views](#views) - [Plugins](#plugins) - [Default Plugins](#default-plugins) - [`delta` (BG Delta)](#delta-bg-delta) @@ -97,7 +110,7 @@ Community maintained fork of the - [`openaps` (OpenAPS)](#openaps-openaps) - [`loop` (Loop)](#loop-loop) - [`override` (Override Mode)](#override-override-mode) - - [`xdripjs` (xDrip-js)](#xdripjs-xdripjs) + - [`xdripjs` (xDrip-js)](#xdripjs-xdrip-js) - [`alexa` (Amazon Alexa)](#alexa-amazon-alexa) - [`googlehome` (Google Home/DialogFLow)](#googlehome-google-homedialogflow) - [`speech` (Speech)](#speech-speech) @@ -109,6 +122,7 @@ Community maintained fork of the - [Setting environment variables](#setting-environment-variables) - [Vagrant install](#vagrant-install) - [More questions?](#more-questions) + - [Browser testing suite provided by](#browser-testing-suite-provided-by) - [License](#license) @@ -117,13 +131,20 @@ Community maintained fork of the ## Supported configurations: -If you plan to use Nightscout, we recommend using [Heroku](http://www.nightscout.info/wiki/welcome/set-up-nightscout-using-heroku), as Nightscout can reach the usage limits of the free Azure plan and cause it to shut down for hours or days. If you end up needing a paid tier, the $7/mo Heroku plan is also much cheaper than the first paid tier of Azure. Currently, the only added benefit to choosing the $7/mo Heroku plan vs the free Heroku plan is a section showing site use metrics for performance (such as response time). This has limited benefit to the average Nightscout user. In short, Heroku is the free and best option for Nightscout hosting. +If you plan to use Nightscout, we recommend using [Heroku](https://nightscout.github.io/nightscout/new_user/) as this is free and easy to use. +We used to recommend hostig at Azure, but the resource needs of Nightscout have grown over the years and Azure won't comfortably run Nightscout +anymore in the free tier. If you're hosting in Azure and looking to update your site, we recommend you +[switch from Azure to Heroku](http://openaps.readthedocs.io/en/latest/docs/While%20You%20Wait%20For%20Gear/nightscout-setup.html#switching-from-azure-to-heroku) +as you're likely to hit issues in the process of updating the site. + +- [Nightscout Setup with Heroku](https://nightscout.github.io/nightscout/new_user/) (recommended) -- [Nightscout Setup with Heroku](http://www.nightscout.info/wiki/welcome/set-up-nightscout-using-heroku) (recommended) -- [Nightscout Setup with Microsoft Azure](http://www.nightscout.info/wiki/faqs-2/azure-2) (not recommended, please -[switch from Azure to Heroku](http://openaps.readthedocs.io/en/latest/docs/While%20You%20Wait%20For%20Gear/nightscout-setup.html#switching-from-azure-to-heroku) ) -- Linux based install (Debian, Ubuntu, Raspbian) install with own Node.JS and MongoDB install (see software requirements below) -- Windows based install with own Node.JS and MongoDB install (see software requirements below) +While you can install Nightscout on a virtual server or a Raspberry Pi, we do not recommend this unless you have at least some +experience hosting Node applications and development using the toolchain in use with Nightscout. Heroku automates all of the +hosting for you and even many of the dvelopers run their production sites in Heroku due to convenience. + +If you're a hosting provider and want to provide our users additional free hosting options, +you're welcome to issue a documentation pull request with instructions on how to setup Nightscout on your system. ## Recommended minimum browser versions for using Nightscout: @@ -142,7 +163,7 @@ Some features may not work with devices/browsers on the older end of these requi ## Windows installation software requirements: -- [Node.js](http://nodejs.org/) Latest Node 8 LTS (Node 8.15.1 or later) or Node 10 LTS (Node 10.16.0 or later; Node 10.15.2 works for Azure). Node versions that do not have the latest security patches will not work. Use [Install instructions for Node](https://nodejs.org/en/download/package-manager/) or use `setup.sh`) +- [Node.js](http://nodejs.org/) Latest Node 12 LTS. Node versions that do not have the latest security patches will not work. Use [Install instructions for Node](https://nodejs.org/en/download/package-manager/) or use `setup.sh`) - [MongoDB](https://www.mongodb.com/download-center?jmp=nav#community) 3.x or later. MongoDB 2.4 is only supported for Raspberry Pi. As a non-root user clone this repo then install dependencies into the root of the project: @@ -174,10 +195,8 @@ Want to help with development, or just see how Nightscout works? Great! See [CON # Usage -The data being uploaded from the server to the client is from a -MongoDB server such as [mLab][mLab]. +The data being uploaded from the server to the client is from a MongoDB server such as [MongoDB Atlas][https://www.mongodb.com]. -[mLab]: https://mlab.com/ [autoconfigure]: https://nightscout.github.io/pages/configure/ [mongostring]: https://nightscout.github.io/pages/mongostring/ @@ -286,12 +305,13 @@ To learn more about the Nightscout API, visit https://YOUR-SITE.com/api-docs/ or * `SHOW_PLUGINS` - enabled plugins that should have their visualizations shown, defaults to all enabled * `SHOW_FORECAST` (`ar2`) - plugin forecasts that should be shown by default, supports space delimited values such as `"ar2 openaps"` * `LANGUAGE` (`en`) - language of Nightscout. If not available english is used - * Currently supported language codes are: bg (Български), cs (Čeština), de (Deutsch), dk (Dansk), el (Ελληνικά), en (English), es (Español), fi (Suomi), fr (Français), he (עברית), hr (Hrvatski), it (Italiano), ko (한국어), nb (Norsk (Bokmål)), nl (Nederlands), pl (Polski), pt (Português (Brasil)), ro (Română), ru (Русский), sk (Slovenčina), sv (Svenska), tr (Turkish), zh_cn (中文(简体)), zh_tw (中文(繁體)) + * Currently supported language codes are: bg (Български), cs (Čeština), de (Deutsch), dk (Dansk), el (Ελληνικά), en (English), es (Español), fi (Suomi), fr (Français), he (עברית), hr (Hrvatski), hu (magyar), it (Italiano), ko (한국어), nb (Norsk (Bokmål)), nl (Nederlands), pl (Polski), pt (Português (Brasil)), ro (Română), ru (Русский), sk (Slovenčina), sv (Svenska), tr (Turkish), zh_cn (中文(简体)), zh_tw (中文(繁體)) * `SCALE_Y` (`log`) - The type of scaling used for the Y axis of the charts system wide. * The default `log` (logarithmic) option will let you see more detail towards the lower range, while still showing the full CGM range. * The `linear` option has equidistant tick marks; the range used is dynamic so that space at the top of chart isn't wasted. * The `log-dynamic` is similar to the default `log` options, but uses the same dynamic range and the `linear` scale. * `EDIT_MODE` (`on`) - possible values `on` or `off`. Enables the icon allowing for editing of treatments in the main view. + * `BOLUS_RENDER_OVER` (1) - U value over which the bolus values are rendered on the chart if the 'x U and Over' option is selected. This value can be an integer or a float, e.g. 0.3, 1.5, 2, etc... ### Predefined values for your server settings (optional) * `INSECURE_USE_HTTP` (`false`) - Redirect unsafe http traffic to https. Possible values `false`, or `true`. Your site redirects to `https` by default. If you don't want that from Nightscout, but want to implement that with a Nginx or Apache proxy, set `INSECURE_USE_HTTP` to `true`. Note: This will allow (unsafe) http traffic to your Nightscout instance and is not recommended. @@ -303,11 +323,35 @@ To learn more about the Nightscout API, visit https://YOUR-SITE.com/api-docs/ or ### Views - There are a few alternate web views available from the main menu that display a simplified BG stream. (If you launch one of these in a fullscreen view in iOS, you can use a left-to-right swipe gesture to exit the view.) + Nightscout allows to create custom, simplified views using a predefined set of elements. This option is available under `[+]` link in the main menu. + + List of available items: + * `SGV` - Sensor Glucose Value + * `SGV age` - time since the last SGV read + * `SGV delta` - change of SGV in the last 5 minutes + * `Trend arrow` - icon of the SG trend + * `Time` - current time + * `Line break` - invisible item that will move following items to the next line (by default all are showing on the same level) + + All visible items have `Size` property which allows to customize the view even more. Also, all items may appear multiple times on the view. + + Apart from adding items, it is possible to customize other aspects of the views, like selecting `Color` or `Black` background. The first one will indicate current BG threshold (green = in range; blue = below range; yellow = above range; red = urgent below/above). + `Show SGV age` option will make `SGV age` item appear `Always` or only if the predefined threshold is reached: `Only after threshold`. Breaching `SGV age threshold` will also make `Color` background turn grey and strike through `SGV`. + `Clock view configurator` will generate an URL (available under `Open my clock view!` link) that could be bookmarked. + + There are a few default views available from the main menu: * `Clock` - Shows current BG, trend arrow, and time of day. Grey text on a black background. - * `Color` - Shows current BG and trend arrow. White text on a background that changes color to indicate current BG threshold (green = in range; blue = below range; yellow = above range; red = urgent below/above). Set `SHOW_CLOCK_DELTA` to `true` to show BG change in the last 5 minutes, set `SHOW_CLOCK_LAST_TIME` to `true` to always show BG age. + * `Color` - Shows current BG and trend arrow. White text on a color background. * `Simple` - Shows current BG. Grey text on a black background. + If you launch one of these views in a fullscreen view in iOS, you can use a left-to-right swipe gesture to exit the view. + +### Split View + + Some users will need easy access to multiple Nightscout views at the same time. We have a special view for this case, accessed on /split path on your Nightscout URL. The view supports any number of sites between 1 to 8 way split, where the content for the screen can be loaded from multiple Nightscout instances. Note you still need to host separate instances for each Nightscout being monitored including the one that hosts the split view page - these variables only add the ability to load multiple views into one browser page. To set the URLs from which the content is loaded, set: + * `FRAME_URL_1` - URL where content is loaded, for the first view (increment the number up to 8 to get more views) + * `FRAME_NAME_1` - Name for the first split view portion of the screen (increment the number to name more views) + ### Plugins Plugins are used extend the way information is displayed, how notifications are sent, alarms are triggered, and more. @@ -431,14 +475,15 @@ To learn more about the Nightscout API, visit https://YOUR-SITE.com/api-docs/ or * `BASAL_RENDER` (`none`) - Possible values are `none`, `default`, or `icicle` (inverted) ##### `bridge` (Share2Nightscout bridge) - Glucose reading directly from the Share service, uses these extended settings: - * `BRIDGE_USER_NAME` - Your user name for the Share service. + Glucose reading directly from the Dexcom Share service, uses these extended settings: + * `BRIDGE_USER_NAME` - Your username for the Share service. * `BRIDGE_PASSWORD` - Your password for the Share service. - * `BRIDGE_INTERVAL` (`150000` *2.5 minutes*) - The time to wait between each update. + * `BRIDGE_INTERVAL` (`150000` *2.5 minutes*) - The time (in milliseconds) to wait between each update. * `BRIDGE_MAX_COUNT` (`1`) - The number of records to attempt to fetch per update. * `BRIDGE_FIRST_FETCH_COUNT` (`3`) - Changes max count during the very first update only. * `BRIDGE_MAX_FAILURES` (`3`) - How many failures before giving up. - * `BRIDGE_MINUTES` (`1400`) - The time window to search for new data per update (default is one day in minutes). + * `BRIDGE_MINUTES` (`1400`) - The time window to search for new data per update (the default value is one day in minutes). + * `BRIDGE_SERVER` (``) - The default blank value is used to fetch data from Dexcom servers in the US. Set to (`EU`) to fetch from European servers instead. ##### `mmconnect` (MiniMed Connect bridge) Transfer real-time MiniMed Connect data from the Medtronic CareLink server into Nightscout ([read more](https://github.com/mddub/minimed-connect-to-nightscout)) @@ -522,12 +567,34 @@ For remote overrides, the following extended settings must be configured: Enabled [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) so other websites can make request to your Nightscout site, uses these extended settings: * `CORS_ALLOW_ORIGIN` (`*`) - The list of sites that are allow to make requests +##### `dbsize` (Database Size) + Show size of Nightscout Database, as a percentage of declared available space or in MiB. + + Many deployments of Nightscout use free tier of MongoDB Atlas on Heroku, which is limited in size. After some time, as volume of stored data grows, it may happen that this limit is reached and system is unable to store new data. This plugin provides pill that indicates size of Database and shows (when configured) alarms regarding reaching space limit. + + **IMPORTANT:** This plugin can only check how much space database already takes, _but cannot infer_ max size available on server for it. To have correct alarms and realistic percentage, `DBSIZE_MAX` need to be properly set - according to your mongoDB hosting configuration. + + **NOTE:** This plugin rely on db.stats() for reporting _logical_ size of database, which may be different than _physical_ size of database on server. It may work for free tier of MongoDB on Atlas, since it calculate quota according to logical size too, but may fail for other hostings or self-hosted database with quota based on physical size. + + **NOTE:** MongoDB Atlas quota is for **all** databases in cluster, while each instance will get only size of **its own database only**. It is ok when you only have **one** database in cluster (most common scenario) but will not work for multiple parallel databases. In such case, spliting known quota equally beetween databases and setting `DBSIZE_MAX` to that fraction may help, but wont be precise. + + All sizes are expressed as integers, in _Mebibytes_ `1 MiB == 1024 KiB == 1024*1024 B` + + * `DBSIZE_MAX` (`496`) - Maximal allowed size of database on your mongoDB server, in MiB. You need to adjust that value to match your database hosting limits - default value is for standard Heroku mongoDB free tier. + * `DBSIZE_WARN_PERCENTAGE` (`60`) - Threshold to show first warning about database size. When database reach this percentage of `DBSIZE_MAX` size - pill will show size in yellow. + * `DBSIZE_URGENT_PERCENTAGE` (`75`) - Threshold to show urgent warning about database size. When database reach this percentage of `DBSIZE_MAX` size, it is urgent to do backup and clean up old data. At this percentage info pill turns red. + * `DBSIZE_ENABLE_ALERTS` (`false`) - Set to `true` to enable notifications about database size. + * `DBSIZE_IN_MIB` (`false`) - Set to `true` to display size of database in MiB-s instead of default percentage. + + This plugin should be enabled by default, if needed can be diasabled by adding `dbsize` to the list of disabled plugins, for example: `DISABLE="dbsize"`. + #### Extended Settings Some plugins support additional configuration using extra environment variables. These are prefixed with the name of the plugin and a `_`. For example setting `MYPLUGIN_EXAMPLE_VALUE=1234` would make `extendedSettings.exampleValue` available to the `MYPLUGIN` plugin. Plugins only have access to their own extended settings, all the extended settings of client plugins will be sent to the browser. * `DEVICESTATUS_ADVANCED` (`true`) - Defaults to true. Users who only have a single device uploading data to Nightscout can set this to false to reduce the data use of the site. + * `DEVICESTATUS_DAYS` (`1`) - Defaults to 1, can optionally be set to 2. Users can use this to show 48 hours of device status data for in retro mode, rather than the default 24 hours. Setting this value to 2 will roughly double the bandwidth usage of nightscout, so users with a data cap may not want to update this setting. #### Pushover In addition to the normal web based alarms, there is also support for [Pushover](https://pushover.net/) based alarms and notifications. @@ -583,7 +650,7 @@ For remote overrides, the following extended settings must be configured: Treatment Profile Fields: * `timezone` (Time Zone) - time zone local to the patient. *Should be set.* - * `units` (Profile Units) - blood glucose units used in the profile, either "mgdl" or "mmol" + * `units` (Profile Units) - blood glucose units used in the profile, either "mg/dl" or "mmol" * `dia` (Insulin duration) - value should be the duration of insulin action to use in calculating how much insulin is left active. Defaults to 3 hours. * `carbs_hr` (Carbs per Hour) - The number of carbs that are processed per hour, for more information see [#DIYPS](http://diyps.org/2014/05/29/determining-your-carbohydrate-absorption-rate-diyps-lessons-learned/). * `carbratio` (Carb Ratio) - grams per unit of insulin. diff --git a/app.js b/app.js index 7c6f67b1ee1..2a94b1dd3e9 100644 --- a/app.js +++ b/app.js @@ -7,6 +7,7 @@ const bodyParser = require('body-parser'); const path = require('path'); const fs = require('fs'); +const ejs = require('ejs'); function create (env, ctx) { var app = express(); @@ -25,50 +26,73 @@ function create (env, ctx) { } }); if (secureHstsHeader) { // Add HSTS (HTTP Strict Transport Security) header - console.info('Enabled SECURE_HSTS_HEADER (HTTP Strict Transport Security)'); - const helmet = require('helmet'); - var includeSubDomainsValue = env.secureHstsHeaderIncludeSubdomains; - var preloadValue = env.secureHstsHeaderPreload; - app.use(helmet({ - hsts: { - maxAge: 31536000 - , includeSubDomains: includeSubDomainsValue - , preload: preloadValue - } - , frameguard: false - })); - if (env.secureCsp) { + + const enableCSP = env.secureCsp ? true : false; + + let cspPolicy = false; + + if (enableCSP) { var secureCspReportOnly = env.secureCspReportOnly; if (secureCspReportOnly) { console.info('Enabled SECURE_CSP (Content Security Policy header). Not enforcing. Report only.'); } else { console.info('Enabled SECURE_CSP (Content Security Policy header). Enforcing.'); } - app.use(helmet.contentSecurityPolicy({ //TODO make NS work without 'unsafe-inline' + + let frameAncestors = ["'self'"]; + + for (let i = 0; i <= 8; i++) { + let u = env.settings['frameUrl' + i]; + if (u) { + frameAncestors.push(u); + } + } + + cspPolicy = { //TODO make NS work without 'unsafe-inline' directives: { defaultSrc: ["'self'"] - , styleSrc: ["'self'", 'https://fonts.googleapis.com/', "'unsafe-inline'"] + , styleSrc: ["'self'", 'https://fonts.googleapis.com/', 'https://fonts.gstatic.com/', "'unsafe-inline'"] , scriptSrc: ["'self'", "'unsafe-inline'"] - , fontSrc: ["'self'", 'https://fonts.gstatic.com/', 'data:'] + , fontSrc: ["'self'", 'https://fonts.googleapis.com/', 'https://fonts.gstatic.com/', 'data:'] , imgSrc: ["'self'", 'data:'] - , objectSrc: ["'none'"], // Restricts , , and elements - reportUri: '/report-violation' - , frameAncestors: ["'none'"], // Clickjacking protection, using frame-ancestors - baseUri: ["'none'"], // Restricts use of the tag - formAction: ["'self'"], // Restricts where
contents may be submitted + , objectSrc: ["'none'"] // Restricts , , and elements + , reportUri: '/report-violation' + , baseUri: ["'none'"] // Restricts use of the tag + , formAction: ["'self'"] // Restricts where contents may be submitted + , connectSrc: ["'self'", "ws:", "wss:", 'https://fonts.googleapis.com/', 'https://fonts.gstatic.com/'] + , frameSrc: ["'self'"] + , frameAncestors: frameAncestors } , reportOnly: secureCspReportOnly - })); + }; + } + + + console.info('Enabled SECURE_HSTS_HEADER (HTTP Strict Transport Security)'); + const helmet = require('helmet'); + var includeSubDomainsValue = env.secureHstsHeaderIncludeSubdomains; + var preloadValue = env.secureHstsHeaderPreload; + app.use(helmet({ + hsts: { + maxAge: 31536000 + , includeSubDomains: includeSubDomainsValue + , preload: preloadValue + } + , frameguard: false + , contentSecurityPolicy: cspPolicy + })); + + if (enableCSP) { + app.use(helmet.referrerPolicy({ policy: 'no-referrer' })); - app.use(helmet.featurePolicy({ features: { payment: ["'none'"], } })); app.use(bodyParser.json({ type: ['json', 'application/csp-report'] })); app.post('/report-violation', (req, res) => { if (req.body) { - console.log('CSP Violation: ', req.body) + console.log('CSP Violation: ', req.body); } else { - console.log('CSP Violation: No data received!') + console.log('CSP Violation: No data received!'); } - res.status(204).end() + res.status(204).end(); }) } } @@ -79,21 +103,61 @@ function create (env, ctx) { app.set('view engine', 'ejs'); // this allows you to render .html files as templates in addition to .ejs app.engine('html', require('ejs').renderFile); - app.engine('appcache', require('ejs').renderFile); app.set("views", path.join(__dirname, "views/")); let cacheBuster = 'developmentMode'; + let lastModified = new Date(); + let busterPath = '/tmp/cacheBusterToken'; + if (process.env.NODE_ENV !== 'development') { - if (fs.existsSync(process.cwd() + '/tmp/cacheBusterToken')) { - cacheBuster = fs.readFileSync(process.cwd() + '/tmp/cacheBusterToken').toString().trim(); - } else { - cacheBuster = fs.readFileSync(__dirname + '/tmp/cacheBusterToken').toString().trim(); - } + busterPath = process.cwd() + busterPath; + } else { + busterPath = __dirname + busterPath; + } + + if (fs.existsSync(busterPath)) { + cacheBuster = fs.readFileSync(busterPath).toString().trim(); + var stats = fs.statSync(busterPath); + lastModified = stats.mtime; } app.locals.cachebuster = cacheBuster; + app.get("/robots.txt", (req, res) => { + res.setHeader('Content-Type', 'text/plain'); + res.send(['User-agent: *','Disallow: /'].join('\n')); + }); + + app.get("/sw.js", (req, res) => { + res.setHeader('Content-Type', 'application/javascript'); + if (process.env.NODE_ENV !== 'development') { + res.setHeader('Last-Modified', lastModified.toUTCString()); + } + res.send(ejs.render(fs.readFileSync( + require.resolve(`${__dirname}/views/service-worker.js`), + { encoding: 'utf-8' }), + { locals: app.locals} + )); + }); + + // Allow static resources to be cached for week + var maxAge = 7 * 24 * 60 * 60 * 1000; + + if (process.env.NODE_ENV === 'development') { + maxAge = 1; + console.log('Development environment detected, setting static file cache age to 1 second'); + } + + var staticFiles = express.static(env.static_files, { + maxAge + }); + + // serve the static content + app.use(staticFiles); + if (ctx.bootErrors && ctx.bootErrors.length > 0) { - app.get('*', require('./lib/server/booterror')(ctx)); + const bootErrorView = require('./lib/server/booterror')(env, ctx); + bootErrorView.setLocals(app.locals); + app.get('*', bootErrorView); return app; } @@ -131,41 +195,58 @@ function create (env, ctx) { } })); - const clockviews = require('./lib/server/clocks.js')(env, ctx); - clockviews.setLocals(app.locals); - - app.use("/clock", clockviews); - - app.get("/", (req, res) => { - res.render("index.html", { - locals: app.locals - }); - }); - var appPages = { - "/clock-color.html": "clock-color.html" - , "/admin": "adminindex.html" - , "/profile": "profileindex.html" - , "/food": "foodindex.html" - , "/bgclock.html": "bgclock.html" - , "/report": "reportindex.html" - , "/translations": "translationsindex.html" - , "/clock.html": "clock.html" + "/": { + file: "index.html" + , type: "index" + } + , "/admin": { + file: "adminindex.html" + , title: 'Admin Tools' + , type: 'admin' + } + , "/food": { + file: "foodindex.html" + , title: 'Food Editor' + , type: 'food' + } + , "/profile": { + file: "profileindex.html" + , title: 'Profile Editor' + , type: 'profile' + } + , "/report": { + file: "reportindex.html" + , title: 'Nightscout reporting' + , type: 'report' + } + , "/translations": { + file: "translationsindex.html" + , title: 'Nightscout translations' + , type: 'translations' + } + , "/split": { + file: "frame.html" + , title: '8-user view' + , type: 'index' + } }; Object.keys(appPages).forEach(function(page) { app.get(page, (req, res) => { - res.render(appPages[page], { - locals: app.locals + res.render(appPages[page].file, { + locals: app.locals, + title: appPages[page].title ? appPages[page].title : '', + type: appPages[page].type ? appPages[page].type : '', + settings: env.settings }); }); }); - app.get("/appcache/*", (req, res) => { - res.render("nightscout.appcache", { - locals: app.locals - }); - }); + const clockviews = require('./lib/server/clocks.js')(env, ctx); + clockviews.setLocals(app.locals); + + app.use("/clock", clockviews); app.use('/api', bodyParser({ limit: 1048576 * 50 @@ -199,44 +280,15 @@ function create (env, ctx) { res.sendFile(__dirname + '/swagger.yaml'); }); - if (env.settings.isEnabled('dumps')) { - var heapdump = require('heapdump'); - app.get('/api/v2/dumps/start', function(req, res) { - var path = new Date().toISOString() + '.heapsnapshot'; - path = path.replace(/:/g, '-'); - console.info('writing dump to', path); - heapdump.writeSnapshot(path); - res.send('wrote dump to ' + path); - }); - } - - // app.get('/package.json', software); - - // Allow static resources to be cached for week - var maxAge = 7 * 24 * 60 * 60 * 1000; - - if (process.env.NODE_ENV === 'development') { - maxAge = 1; - console.log('Development environment detected, setting static file cache age to 1 second'); - - app.get('/nightscout.appcache', function(req, res) { - res.sendStatus(404); - }); - } - - var staticFiles = express.static(env.static_files, { - maxAge - }); - - // serve the static content - app.use(staticFiles); - // API docs const swaggerUi = require('swagger-ui-express'); + const swaggerUseSchema = schema => (...args) => swaggerUi.setup(schema)(...args); const swaggerDocument = require('./swagger.json'); + const swaggerDocumentApiV3 = require('./lib/api3/swagger.json'); - app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); + app.use('/api-docs', swaggerUi.serve, swaggerUseSchema(swaggerDocument)); + app.use('/api3-docs', swaggerUi.serve, swaggerUseSchema(swaggerDocumentApiV3)); app.use('/swagger-ui-dist', (req, res) => { res.redirect(307, '/api-docs'); diff --git a/app.json b/app.json index 3d86d59bfa2..9f77094f565 100644 --- a/app.json +++ b/app.json @@ -2,6 +2,11 @@ "name": "CGM Remote Monitor", "repository": "https://github.com/nightscout/cgm-remote-monitor", "env": { + "MONGODB_URI": { + "description": "The MongoDB Connection String to connect to your MongoDB cluster. If you don't have this from MongoDB Atlas, please re-read installation instructions at http://nightscout.github.io/nightscout/new_user/ before continuing", + "value": "", + "required": true + }, "ALARM_HIGH": { "description": "Default setting for new browser views, for the High alarm (triggered when BG crosses BG_TARGET_TOP). ('on' or 'off')", "value": "on", @@ -72,6 +77,11 @@ "value": "180", "required": false }, + "BOLUS_RENDER_OVER": { + "description": "U value over which the bolus values are rendered on the chart if the 'x U and Over' option is selected.", + "value": "1", + "required": false + }, "BRIDGE_PASSWORD": { "description": "Your Dexcom account password, to receive CGM data from the Dexcom Share service. Also make sure to include 'bridge' in your ENABLE line.", "value": "", @@ -99,7 +109,7 @@ }, "ENABLE": { "description": "Plugins to enable for your site. Must be a space-delimited, lower-case list. Include the word 'bridge' here if you are receiving data from the Dexcom Share service. Include 'mmconnect' if you are bridging from the MiniMed CareLink service.", - "value": "careportal basal", + "value": "careportal basal dbsize", "required": false }, "MMCONNECT_USER_NAME": { @@ -117,11 +127,6 @@ "value": "US", "required": false }, - "MONGO_COLLECTION": { - "description": "The Mongo collection where CGM data is stored.", - "value": "entries", - "required": true - }, "NIGHT_MODE": { "description": "Default setting for new browser views, for whether Night Mode should be enabled. ('on' or 'off')", "value": "off", @@ -129,7 +134,7 @@ }, "SHOW_PLUGINS": { "description": "Default setting for whether or not these plugins are checked (active) by default, not merely enabled. Include plugins here as in the ENABLE line; space-separated and lower-case.", - "value": "careportal", + "value": "careportal dbsize", "required": false }, "SHOW_RAWBG": { @@ -149,7 +154,6 @@ } }, "addons": [ - "mongolab:sandbox", "papertrail" ] } diff --git a/assets/fonts/Nightscout Plugin Icons.json b/assets/fonts/Nightscout Plugin Icons.json new file mode 100644 index 00000000000..65874c15679 --- /dev/null +++ b/assets/fonts/Nightscout Plugin Icons.json @@ -0,0 +1,87 @@ +{ + "metadata": { + "name": "Nightscout Plugin Icons", + "lastOpened": 0, + "created": 1580075608590 + }, + "iconSets": [ + { + "selection": [ + { + "order": 2, + "id": 0, + "name": "database", + "prevSize": 32, + "code": 59649, + "tempChar": "" + } + ], + "id": 2, + "metadata": { + "name": "Plugin Icons", + "importSize": { + "width": 16, + "height": 18 + } + }, + "height": 1024, + "prevSize": 32, + "icons": [ + { + "id": 0, + "paths": [ + "M455.111 0c-251.449 0-455.111 101.831-455.111 227.556s203.662 227.556 455.111 227.556 455.111-101.831 455.111-227.556-203.662-227.556-455.111-227.556zM0 341.333v170.667c0 125.724 203.662 227.556 455.111 227.556s455.111-101.831 455.111-227.556v-170.667c0 125.724-203.662 227.556-455.111 227.556s-455.111-101.831-455.111-227.556zM0 625.778v170.667c0 125.724 203.662 227.556 455.111 227.556s455.111-101.831 455.111-227.556v-170.667c0 125.724-203.662 227.556-455.111 227.556s-455.111-101.831-455.111-227.556z" + ], + "attrs": [ + {} + ], + "width": 910, + "isMulticolor": false, + "isMulticolor2": false, + "grid": 0, + "tags": [ + "plugins" + ] + } + ], + "invisible": false, + "colorThemes": [] + } + ], + "preferences": { + "showGlyphs": true, + "showQuickUse": true, + "showQuickUse2": true, + "showSVGs": true, + "fontPref": { + "prefix": "plugicon-", + "metadata": { + "fontFamily": "pluginicons", + "majorVersion": 1, + "minorVersion": 0 + }, + "metrics": { + "emSize": 1024, + "baseline": 6.25, + "whitespace": 50 + }, + "embed": false, + "showSelector": false, + "showMetrics": false, + "showMetadata": false, + "showVersion": false + }, + "imagePref": { + "prefix": "icon-", + "png": true, + "useClassSelector": true, + "color": 0, + "bgColor": 16777215, + "classSelector": ".icon" + }, + "historySize": 50, + "showCodes": true, + "gridSize": 16 + }, + "uid": -1 +} \ No newline at end of file diff --git a/assets/fonts/README.md b/assets/fonts/README.md new file mode 100644 index 00000000000..b6b98ea4322 --- /dev/null +++ b/assets/fonts/README.md @@ -0,0 +1,29 @@ +How to upgrade icons in icon-fonts on Nightscout +================================================ + +This guide is fol developers regarding how to add new icon to Nightscout. + +Nightscout use icon fonts to render icons. Each icon is glyph (like - letter, or more like emoji character) inside custom made font file. +That way we have nice, vector icons, that are small, scalable, looks good on each platform, and are easy to embed inside CSS. + +To extend existing icon set.: + +1. Prepare minimalist, black & white icon in SVG tool of choice, and optimize it (you can use Inkscape) to be small in size and render good at small sizes. +2. Use https://icomoon.io/app and import accompanied JSON project file (`Nightscout Plugin Icons.json`) +3. Add SVG as new glyph. Remember to take care to set proper character code and CSS name +4. Save new version of JSON project file and store in this folder +5. Generate font, download zip file and unpack it to get `fonts/pluginicons.svg` and `fonts/pluginicons.woff` +6. Update `statc/css/main.css` file + * In section of `@font-face` with `font-family: 'pluginicons'` + * update part after `data:application/font-woff;charset=utf-8;base64,` with Base64-encoded content of just generated `pluginicons.woff` font + * update part after `data:application/font-svg;charset=utf-8;base64,` with Base64-encoded content of just generated `pluginicons.svg` font + * copy/update all entries `.plugicon-****:before { content: "****"; }` from generated font `style.css` into `statc/css/main.css` +7. Do not forget to update `Nightscout Plugin Icons.json` in this repo (´download updated project from icomoon.io) + +Hints +----- + +* You can find many useful online tools to encode file into Base64, like: https://base64.guru/converter/encode/file +* Do not split Base64 output - it should be one LONG line +* Since update process is **manual** and generated fonts & updated CSS sections are **binary** - try to avoid **git merge conflicts** by speaking with other developers if you plan to add new icon +* When in doubt - check `git log` and reach last contributor for guidelines :) diff --git a/azuredeploy.json b/azuredeploy.json index dc89c0ad956..bff5e3c41f7 100644 --- a/azuredeploy.json +++ b/azuredeploy.json @@ -173,7 +173,7 @@ }, "enable": { "type": "string", - "defaultValue": "basal bwp cage careportal iob cob rawbg sage iage treatmentnotify boluscalc profile food" + "defaultValue": "basal bwp cage careportal iob cob rawbg sage iage treatmentnotify boluscalc profile food dbsize" }, "night_mode": { "type": "string", @@ -185,7 +185,7 @@ }, "show_plugins": { "type": "string", - "defaultValue": "careportal" + "defaultValue": "careportal dbsize" }, "show_rawbg": { "type": "string", diff --git a/bundle/bundle.reports.source.js b/bundle/bundle.reports.source.js index c07368543b4..27d67e9fb82 100644 --- a/bundle/bundle.reports.source.js +++ b/bundle/bundle.reports.source.js @@ -1,10 +1,11 @@ import './bundle.source'; window.Nightscout.report_plugins = require('../lib/report_plugins/')(); +window.Nightscout.predictions = require('../lib/report/predictions'); console.info('Nightscout report bundle ready'); // Needed for Hot Module Replacement if(typeof(module.hot) !== 'undefined') { - module.hot.accept() // eslint-disable-line no-undef + module.hot.accept() } diff --git a/bundle/bundle.source.js b/bundle/bundle.source.js index d554744e6e4..db61af947bf 100644 --- a/bundle/bundle.source.js +++ b/bundle/bundle.source.js @@ -32,5 +32,5 @@ console.info('Nightscout bundle ready'); // Needed for Hot Module Replacement if(typeof(module.hot) !== 'undefined') { - module.hot.accept() // eslint-disable-line no-undef + module.hot.accept() } diff --git a/ci.test.env b/ci.test.env index c57e5eeb0c4..f5e240f8381 100644 --- a/ci.test.env +++ b/ci.test.env @@ -4,4 +4,5 @@ HOSTNAME=localhost INSECURE_USE_HTTP=true PORT=1337 NODE_ENV=production -CI=true \ No newline at end of file +CI=true +CODACY_PROJECT_TOKEN=cff7ab3377d6434a9355fd051dbb4595 \ No newline at end of file diff --git a/docs/plugins/add-virtual-assistant-support-to-plugin.md b/docs/plugins/add-virtual-assistant-support-to-plugin.md index 60ac1d1957b..6c581013b9e 100644 --- a/docs/plugins/add-virtual-assistant-support-to-plugin.md +++ b/docs/plugins/add-virtual-assistant-support-to-plugin.md @@ -36,9 +36,8 @@ There are 2 types of handlers that you can supply: A plugin can expose multiple intent handlers (e.g. useful when it can supply multiple kinds of metrics). Each intent handler should be structured as follows: + `intent` - This is the intent this handler is built for. Right now, the templates used by both Alexa and Google Home use only the `"MetricNow"` intent (used for getting the present value of the requested metric) -+ `metrics` - An array of metric name(s) the handler will supply. e.g. "What is my `metric`" - iob, bg, cob, etc. Make sure to add the metric name and its synonyms to the list of metrics used by the virtual assistant(s). - - **IMPORTANT NOTE:** There is no protection against overlapping metric names, so PLEASE make sure your metric name is unique! - - Note: Although this value *is* an array, you really should only supply one (unique) value, and then add aliases or synonyms to that value in the list of metrics for the virtual assistant. We keep this value as an array for backwards compatibility. ++ `metrics` - An array of metric name(s) the handler will supply. e.g. "What is my `metric`" - iob, bg, cob, etc. Although this value *is* an array, you really should only supply one (unique) value, and then add aliases or synonyms to that value in the list of metrics for the virtual assistant. We keep this value as an array for backwards compatibility. + - **IMPORTANT NOTE:** There is no protection against overlapping metric names, so PLEASE make sure your metric name is unique! + `intenthandler` - This is a callback function that receives 3 arguments: - `callback` Call this at the end of your function. It requires 2 arguments: - `title` - Title of the handler. This is the value that will be displayed on the Alexa card (for devices with a screen). The Google Home response doesn't currently display a card, so it doesn't use this value. diff --git a/docs/plugins/alexa-plugin.md b/docs/plugins/alexa-plugin.md index 4e298df4b74..87117affd46 100644 --- a/docs/plugins/alexa-plugin.md +++ b/docs/plugins/alexa-plugin.md @@ -10,6 +10,7 @@ - [Create a new Alexa skill](#create-a-new-alexa-skill) - [Define the interaction model](#define-the-interaction-model) - [Point your skill at your site](#point-your-skill-at-your-site) + - [Do you use Authentication Roles?](#do-you-use-authentication-roles) - [Test your skill out with the test tool](#test-your-skill-out-with-the-test-tool) - [What questions can you ask it?](#what-questions-can-you-ask-it) - [Activate the skill on your Echo or other device](#activate-the-skill-on-your-echo-or-other-device) @@ -75,10 +76,20 @@ Now you need to point your skill at *your* Nightscout site. 1. In the left-hand menu for your skill, there's an option called "Endpoint". Click it. 1. Under "Service Endpoint Type", select "HTTPS". 1. You only need to set up the Default Region. In the box that says "Enter URI...", put in `https://{yourdomain}/api/v1/alexa`. (So if your Nightscout site is at `mynightscoutsite.herokuapp.com`, you'll enter `https://mynightscoutsite.herokuapp.com/api/v1/alexa` in the box.) + - If you use Authentication Roles, you'll need to add a bit to the end of your URL. See [the section](#do-you-use-authentication-roles) below. 1. In the dropdown under the previous box, select "My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority". 1. Click the "Save Endpoints" button at the top. 1. You should see a success message pop up when the save succeeds. +### Do you use Authentication Roles? ### + +If you use Authentication Roles, you will need to add a token to the end of your Nightscout URL when configuring your Endpoint. + +1. In your Nightscout Admin Tools, add a new subject and give it the "readable" role. + - If you **really** would like to be super specific, you could create a new role and set the permissions to `api:*:read`. +1. After the new subject is created, copy the "Access Token" value for the new row in your subject table (**don't** copy the link, just copy the text). +1. At the end of your Nighscout URL, add `?token={yourtoken}`, where `{yourtoken}` is the Access Token you just copied. Your new URL should look like `https://{yourdomain}/api/v1/googlehome?token={yourtoken}`. + ### Test your skill out with the test tool Click on the "Test" tab on the top menu. This will take you to the page where you can test your new skill. diff --git a/docs/plugins/alexa-templates/en-us.json b/docs/plugins/alexa-templates/en-us.json index 4cb10aa0643..20bf8c290d1 100644 --- a/docs/plugins/alexa-templates/en-us.json +++ b/docs/plugins/alexa-templates/en-us.json @@ -68,12 +68,30 @@ { "name": "AMAZON.StopIntent", "samples": [] + }, + { + "name": "AMAZON.CancelIntent", + "samples": [] + }, + { + "name": "AMAZON.HelpIntent", + "samples": [] } ], "types": [ { "name": "LIST_OF_METRICS", "values": [ + { + "name": { + "value": "delta", + "synonyms": [ + "blood glucose delta", + "blood sugar delta", + "bg delta" + ] + } + }, { "name": { "value": "uploader battery", @@ -162,6 +180,77 @@ "raw blood glucose" ] } + }, + { + "name": { + "value": "cgm noise" + } + }, + { + "name": { + "value": "cgm tx age", + "synonyms": [ + "tx age", + "transmitter age", + "cgm transmitter age" + ] + } + }, + { + "name": { + "value": "cgm tx status", + "synonyms": [ + "tx status", + "transmitter status", + "cgm transmitter status" + ] + } + }, + { + "name": { + "value": "cgm battery", + "synonyms": [ + "cgm battery level", + "cgm battery levels", + "cgm batteries", + "cgm transmitter battery", + "cgm transmitter battery level", + "cgm transmitter battery levels", + "cgm transmitter batteries", + "transmitter battery", + "transmitter battery level", + "transmitter battery levels", + "transmitter batteries" + ] + } + }, + { + "name": { + "value": "cgm session age", + "synonyms": [ + "session age" + ] + } + }, + { + "name": { + "value": "cgm status" + } + }, + { + "name": { + "value": "cgm mode" + } + }, + { + "name": { + "value": "db size", + "synonyms": [ + "database size", + "data size", + "file size" + ] + } } ] } diff --git a/docs/plugins/google-home-templates/en-us.zip b/docs/plugins/google-home-templates/en-us.zip index 6a8498b0b19..551e51307f0 100644 Binary files a/docs/plugins/google-home-templates/en-us.zip and b/docs/plugins/google-home-templates/en-us.zip differ diff --git a/docs/plugins/googlehome-plugin.md b/docs/plugins/googlehome-plugin.md index ccffb81f404..fc76117059e 100644 --- a/docs/plugins/googlehome-plugin.md +++ b/docs/plugins/googlehome-plugin.md @@ -6,7 +6,9 @@ - [Overview](#overview) - [Activate the Nightscout Google Home Plugin](#activate-the-nightscout-google-home-plugin) - [Create Your DialogFlow Agent](#create-your-dialogflow-agent) + - [Do you use Authentication Roles?](#do-you-use-authentication-roles) - [What questions can you ask it?](#what-questions-can-you-ask-it) + - [Using the Alpha Tester feature](#using-the-alpha-tester-feature) - [Updating your agent with new features](#updating-your-agent-with-new-features) - [Adding support for additional languages](#adding-support-for-additional-languages) - [Adding Google Home support to a plugin](#adding-google-home-support-to-a-plugin) @@ -30,6 +32,8 @@ To add Google Home support for your Nightscout site, here's what you need to do: ## Create Your DialogFlow Agent +**BEFORE YOU GET STARTED:** Please read [the section below on the **highly-recommended** use of the Alpha tester feature](#using-the-alpha-tester-feature). + 1. Download the agent template in your language for Google Home [here](google-home-templates/). - If you're language doesn't have a template, please consider starting with [the en-us template](google-home-templates/en-us.zip), then [modifying it to work with your language](#adding-support-for-additional-languages), and [making a pull request](/CONTRIBUTING.md) or [submitting an issue](https://github.com/nightscout/cgm-remote-monitor/issues) with your translated template to share it with others. 1. [Sign in to Google's Action Console](https://console.actions.google.com) @@ -37,7 +41,8 @@ To add Google Home support for your Nightscout site, here's what you need to do: 1. Click on the "New Project" button. 1. If prompted, agree to the Terms of Service. 1. Give your project a name (e.g. "Nightscout") and then click "Create project". -1. For the "development experience", select "Conversational" at the bottom of the list. +1. When asked what kind of Action you want to build, select "Custom" and then click the "Next" button. +1. When selecting how you want to build the project, scroll down to the bottom of the screen and click the link to build it using DialogFlow. 1. Click on the "Develop" tab at the top of the sreen. 1. Click on "Invocation" in the left navigation pane. 1. Set the display name (e.g. "Night Scout") of your Action and set your Google Assistant voice. @@ -56,6 +61,7 @@ To add Google Home support for your Nightscout site, here's what you need to do: 1. After the import finishes, click the "DONE" button followed by the "SAVE" button. 1. In the navigation pane on the left, click on "Fulfillment". 1. Enable the toggle for "Webhook" and then fill in the URL field with your Nightscout URL: `https://YOUR-NIGHTSCOUT-SITE/api/v1/googlehome` + - If you use Authentication Roles, you'll need to add a bit to the end of your URL. See [the section](#do-you-use-authentication-roles) below. 1. Scroll down to the bottom of the page and click the "SAVE" button. 1. Click on "Integrations" in the navigation pane. 1. Click on "INTEGRATION SETTINGS" for "Google Assistant". @@ -65,10 +71,35 @@ To add Google Home support for your Nightscout site, here's what you need to do: That's it! Now try asking Google "Hey Google, ask *your Action's name* how am I doing?" +### Do you use Authentication Roles? ### + +If you use Authentication Roles, you will need to add a token to the end of your Nightscout URL when configuring your Webhook. + +1. In your Nightscout Admin Tools, add a new subject and give it the "readable" role. + - If you **really** would like to be super specific, you could create a new role and set the permissions to `api:*:read`. +1. After the new subject is created, copy the "Access Token" value for the new row in your subject table (**don't** copy the link, just copy the text). +1. At the end of your Nighscout URL, add `?token=YOUR-TOKEN`, where `YOUR-TOKEN` is the Access Token you just copied. Your new URL should look like `https://YOUR-NIGHTSCOUT-SITE/api/v1/googlehome?token=YOUR-TOKEN`. + ### What questions can you ask it? See [Interacting with Virtual Assistants](interacting-with-virtual-assistants.md) for details on what you can do with Google Home. +### Using the Alpha Tester feature + +If you use your Google Action on the same account as the one you used to create it, you will find that Google disables Test Mode for the action after some period of time, and you have to log in to the Actions console, and open the testing tab to re-enable testing for you to continue to use it. To overcome this limitation, you can use the Alpa Testers feature of Google Actions. To do so, you need to follow a few extra steps: + +1. Figure out which Google account you use for your Google Assistant. +1. Use or create a different account to follow the instructions to create your Google Action and DialogFlow agent. +1. Once you verify your Action is working, navigate to the [Actions Console](https://console.actions.google.com/), and open your project. +1. Navigate to the "Deploy" tab, then open the "Release" page in the left navigation pane. +1. Expand the "Alpha" section, then click on the "Create a release" button, and then follow the directions to create a release. + - You may need to fill out some extra information, such as a Privacy Policy ([example](https://docs.google.com/document/d/1RP32ooEol97UyPiJ9vUskhLb6XC6PHhtVTwh0siUZV0/view)), descriptions (e.g. both could be "Tools and stuff to help my partner and I do things better"), and testing instructions (e.g. "Since this is built entirely for myself and my partner, don't expect too much out of this one."). Because this will be for personal use, it's recommended that you keep all of these as vague as possible. +1. Click the "Manage Alpha Testers" button. +1. Enter the email address of the account you use for your Google Assistant (found in step 1). Enter the emails of any other people you would like to have access to talk to your Action (e.g. a spouse). +1. Click the "Save" button. +1. Copy the "Opt-in link" and open it on a device logged in with your account from step 1. Repeat for any other emails you added two steps ago. If the link doesn't work right away, try again in a couple hours. +1. Follow any directions to setup the account as an Alpha Tester. + ## Updating your agent with new features As more work is done on Nightscout, new ways to interact with Nighscout via Google Home may be made available. To be able to use these new features, you first will need to [update your Nightscout site](https://github.com/nightscout/cgm-remote-monitor#updating-my-version), and then you can follow the steps below to update your DialogFlow agent. @@ -83,6 +114,7 @@ As more work is done on Nightscout, new ways to interact with Nighscout via Goog 1. Select the template file you downloaded earlier, then type "RESTORE" in the text box as requested, and click the "RESTORE" button. 1. After the import is completed, click the "DONE" button. 1. Make sure to follow any directions specific to the Nightscout update. If there are any, they will be noted in the [release notes](https://github.com/nightscout/cgm-remote-monitor/releases). +1. If you use the Alpha Testers feature (see [Using the Alpha Tester feature](#using-the-alpha-tester-feature) above), create a new release. 1. Enjoy the new features! ## Adding support for additional languages diff --git a/docs/plugins/interacting-with-virtual-assistants.md b/docs/plugins/interacting-with-virtual-assistants.md index 984a876f21c..3fe67bee2fb 100644 --- a/docs/plugins/interacting-with-virtual-assistants.md +++ b/docs/plugins/interacting-with-virtual-assistants.md @@ -43,6 +43,7 @@ This list is not meant to be comprehensive, nor does it include every way you ca - "Alexa, ask Nightscout what is my basal" - "Alexa, ask Nightscout what is my current basal" - "Alexa, ask Nightscout what is my cob" +- "Alexa, ask Nightscout what is my delta" - "Alexa, ask Nightscout what is Charlie's carbs on board" - "Alexa, ask Nightscout what is Sophie's carbohydrates on board" - "Alexa, ask Nightscout what is Harper's loop forecast" @@ -51,6 +52,15 @@ This list is not meant to be comprehensive, nor does it include every way you ca - "Alexa, ask Nightscout what is Arden's raw bg" - "Alexa, ask Nightscout what is Dana's raw blood glucose" +*CGM Info:* (when using the [`xdripjs` plugin](/README.md#xdripjs-xdrip-js)) + +- "Alexa, ask Nightscout what's my CGM status" +- "Alexa, ask Nightscout what's my CGM session age" +- "Alexa, ask Nightscout what's my CGM transmitter age" +- "Alexa, ask Nightscout what's my CGM mode" +- "Alexa, ask Nightscout what's my CGM noise" +- "Alexa, ask Nightscout what's my CGM battery" + *Insulin Remaining:* - "Alexa, ask Nightscout how much insulin do I have left" diff --git a/env.js b/env.js index 0d8d41409b0..275271bdf26 100644 --- a/env.js +++ b/env.js @@ -14,15 +14,19 @@ var env = { settings: require('./lib/settings')() }; +var shadowEnv; + // Module to constrain all config and environment parsing to one spot. -// See the +// See README.md for info about all the supported ENV VARs function config ( ) { - /* - * See README.md for info about all the supported ENV VARs - */ - env.DISPLAY_UNITS = readENV('DISPLAY_UNITS', 'mg/dl'); - console.log('Units set to', env.DISPLAY_UNITS ); + // Assume users will typo whitespaces into keys and values + + shadowEnv = {}; + + Object.keys(process.env).forEach((key, index) => { + shadowEnv[_trim(key)] = _trim(process.env[key]); + }); env.PORT = readENV('PORT', 1337); env.HOSTNAME = readENV('HOSTNAME', null); @@ -82,12 +86,6 @@ function setAPISecret() { var shasum = crypto.createHash('sha1'); shasum.update(readENV('API_SECRET')); env.api_secret = shasum.digest('hex'); - - if (!readENV('TREATMENTS_AUTH', true)) { - - } - - } } } @@ -125,13 +123,17 @@ function updateSettings() { UNITS: 'DISPLAY_UNITS' }; + var envDefaultOverrides = { + DISPLAY_UNITS: 'mg/dl' + }; + env.settings.eachSettingAsEnv(function settingFromEnv (name) { var envName = envNameOverrides[name] || name; - return readENV(envName); + return readENV(envName, envDefaultOverrides[envName]); }); //should always find extended settings last - env.extendedSettings = findExtendedSettings(process.env); + env.extendedSettings = findExtendedSettings(shadowEnv); if (!readENVTruthy('TREATMENTS_AUTH', true)) { env.settings.authDefaultRoles = env.settings.authDefaultRoles || ""; @@ -141,16 +143,16 @@ function updateSettings() { function readENV(varName, defaultValue) { //for some reason Azure uses this prefix, maybe there is a good reason - var value = process.env['CUSTOMCONNSTR_' + varName] - || process.env['CUSTOMCONNSTR_' + varName.toLowerCase()] - || process.env[varName] - || process.env[varName.toLowerCase()]; + var value = shadowEnv['CUSTOMCONNSTR_' + varName] + || shadowEnv['CUSTOMCONNSTR_' + varName.toLowerCase()] + || shadowEnv[varName] + || shadowEnv[varName.toLowerCase()]; - if (varName == 'DISPLAY_UNITS' && value) { - if (value.toLowerCase().includes('mmol')) { + if (varName == 'DISPLAY_UNITS') { + if (value && value.toLowerCase().includes('mmol')) { value = 'mmol'; } else { - value = 'mg/dl'; + value = defaultValue; } } @@ -170,6 +172,8 @@ function findExtendedSettings (envs) { extended.devicestatus = {}; extended.devicestatus.advanced = true; + extended.devicestatus.days = 1; + if(shadowEnv['DEVICESTATUS_DAYS'] && shadowEnv['DEVICESTATUS_DAYS'] == '2') extended.devicestatus.days = 1; function normalizeEnv (key) { return key.toUpperCase().replace('CUSTOMCONNSTR_', ''); diff --git a/lib/api/activity/index.js b/lib/api/activity/index.js index d88019ab936..c42e73570c6 100644 --- a/lib/api/activity/index.js +++ b/lib/api/activity/index.js @@ -43,17 +43,17 @@ function configure(app, wares, ctx) { var d2 = null; - if (t.hasOwnProperty('created_at')) { + if (Object.prototype.hasOwnProperty.call(t, 'created_at')) { d2 = new Date(t.created_at); } else { - if (t.hasOwnProperty('timestamp')) { + if (Object.prototype.hasOwnProperty.call(t, 'timestamp')) { d2 = new Date(t.timestamp); } } if (d2 == null) { return; } - if (d1 == null || d2.getTime() > d1.getTime()) { + if (d1 == null || d2.getTime() > d1.getTime()) { d1 = d2; } }); @@ -80,7 +80,7 @@ function configure(app, wares, ctx) { if (!_isArray(activity)) { activity = [activity]; - }; + } ctx.activity.create(activity, function(err, created) { if (err) { diff --git a/lib/api/alexa/index.js b/lib/api/alexa/index.js index 337ec00f732..3c31bf1ce00 100644 --- a/lib/api/alexa/index.js +++ b/lib/api/alexa/index.js @@ -1,10 +1,9 @@ 'use strict'; +var _ = require('lodash'); var moment = require('moment'); -var _each = require('lodash/each'); function configure (app, wares, ctx, env) { - var entries = ctx.entries; var express = require('express') , api = express.Router( ); var translate = ctx.language.translate; @@ -16,34 +15,11 @@ function configure (app, wares, ctx, env) { // json body types get handled as parsed json api.use(wares.bodyParser.json()); - ctx.plugins.eachEnabledPlugin(function each(plugin){ - if (plugin.virtAsst) { - if (plugin.virtAsst.intentHandlers) { - console.log('Alexa: Plugin ' + plugin.name + ' supports Virtual Assistants'); - _each(plugin.virtAsst.intentHandlers, function (route) { - if (route) { - ctx.alexa.configureIntentHandler(route.intent, route.intentHandler, route.metrics); - } - }); - } - if (plugin.virtAsst.rollupHandlers) { - console.log('Alexa: Plugin ' + plugin.name + ' supports rollups for Virtual Assistants'); - _each(plugin.virtAsst.rollupHandlers, function (route) { - console.log('Route'); - console.log(route); - if (route) { - ctx.alexa.addToRollup(route.rollupGroup, route.rollupHandler, route.rollupName); - } - }); - } - } else { - console.log('Alexa: Plugin ' + plugin.name + ' does not support Virtual Assistants'); - } - }); + ctx.virtAsstBase.setupVirtAsstHandlers(ctx.alexa); api.post('/alexa', ctx.authorization.isPermitted('api:*:read'), function (req, res, next) { console.log('Incoming request from Alexa'); - var locale = req.body.request.locale; + var locale = _.get(req, 'body.request.locale'); if(locale){ if(locale.length > 2) { locale = locale.substr(0, 2); @@ -53,77 +29,40 @@ function configure (app, wares, ctx, env) { } switch (req.body.request.type) { - case 'IntentRequest': - onIntent(req.body.request.intent, function (title, response) { - res.json(ctx.alexa.buildSpeechletResponse(title, response, '', 'true')); + case 'SessionEndedRequest': + onSessionEnded(function () { + res.json(''); next( ); }); break; case 'LaunchRequest': - onLaunch(req.body.request.intent, function (title, response) { - res.json(ctx.alexa.buildSpeechletResponse(title, response, '', 'true')); - next( ); - }); - break; - case 'SessionEndedRequest': - onSessionEnded(req.body.request.intent, function (alexaResponse) { - res.json(alexaResponse); + if (!req.body.request.intent) { + onLaunch(function () { + res.json(ctx.alexa.buildSpeechletResponse( + translate('virtAsstTitleLaunch'), + translate('virtAsstLaunch'), + translate('virtAsstLaunch'), + false + )); + next( ); + }); + break; + } + // if intent is set then fallback to IntentRequest + case 'IntentRequest': // eslint-disable-line no-fallthrough + onIntent(req.body.request.intent, function (title, response) { + res.json(ctx.alexa.buildSpeechletResponse(title, response, '', true)); next( ); }); break; } }); - ctx.alexa.addToRollup('Status', function bgRollupHandler(slots, sbx, callback) { - entries.list({count: 1}, function (err, records) { - var direction; - if (translate(records[0].direction)) { - direction = translate(records[0].direction); - } else { - direction = records[0].direction; - } - var status = translate('virtAsstStatus', { - params: [ - sbx.scaleMgdl(records[0].sgv), - direction, - moment(records[0].date).from(moment(sbx.time)) - ] - }); - - callback(null, {results: status, priority: -1}); - }); - }, 'BG Status'); - - ctx.alexa.configureIntentHandler('MetricNow', function (callback, slots, sbx, locale) { - entries.list({count: 1}, function(err, records) { - var direction; - if(translate(records[0].direction)){ - direction = translate(records[0].direction); - } else { - direction = records[0].direction; - } - var status = translate('virtAsstStatus', { - params: [ - sbx.scaleMgdl(records[0].sgv), - direction, - moment(records[0].date).from(moment(sbx.time))] - }); - - callback(translate('virtAsstTitleCurrentBG'), status); - }); - }, ['bg', 'blood glucose', 'number']); - - ctx.alexa.configureIntentHandler('NSStatus', function (callback, slots, sbx, locale) { - ctx.alexa.getRollup('Status', sbx, slots, locale, function (status) { - callback(translate('virtAsstTitleFullStatus'), status); - }); - }); - + ctx.virtAsstBase.setupMutualIntents(ctx.alexa); - function onLaunch(intent, next) { + function onLaunch(next) { console.log('Session launched'); - console.log(JSON.stringify(intent)); - handleIntent(intent.name, intent.slots, next); + next( ); } function onIntent(intent, next) { @@ -132,28 +71,21 @@ function configure (app, wares, ctx, env) { handleIntent(intent.name, intent.slots, next); } - function onSessionEnded() { + function onSessionEnded(next) { console.log('Session ended'); + next( ); } function handleIntent(intentName, slots, next) { var metric; if (slots) { - if (slots.metric - && slots.metric.resolutions - && slots.metric.resolutions.resolutionsPerAuthority - && slots.metric.resolutions.resolutionsPerAuthority.length - && slots.metric.resolutions.resolutionsPerAuthority[0].status - && slots.metric.resolutions.resolutionsPerAuthority[0].status.code - && slots.metric.resolutions.resolutionsPerAuthority[0].status.code == "ER_SUCCESS_MATCH" - && slots.metric.resolutions.resolutionsPerAuthority[0].values - && slots.metric.resolutions.resolutionsPerAuthority[0].values.length - && slots.metric.resolutions.resolutionsPerAuthority[0].values[0].value - && slots.metric.resolutions.resolutionsPerAuthority[0].values[0].value.name - ){ - metric = slots.metric.resolutions.resolutionsPerAuthority[0].values[0].value.name; + var slotStatus = _.get(slots, 'metric.resolutions.resolutionsPerAuthority[0].status.code'); + var slotName = _.get(slots, 'metric.resolutions.resolutionsPerAuthority[0].values[0].value.name'); + if (slotStatus == "ER_SUCCESS_MATCH" && slotName) { + metric = slotName; } else { next(translate('virtAsstUnknownIntentTitle'), translate('virtAsstUnknownIntentText')); + return; } } @@ -161,8 +93,10 @@ function configure (app, wares, ctx, env) { if (handler){ var sbx = initializeSandbox(); handler(next, slots, sbx); + return; } else { next(translate('virtAsstUnknownIntentTitle'), translate('virtAsstUnknownIntentText')); + return; } } @@ -176,4 +110,4 @@ function configure (app, wares, ctx, env) { return api; } -module.exports = configure; \ No newline at end of file +module.exports = configure; diff --git a/lib/api/devicestatus/index.js b/lib/api/devicestatus/index.js index 91702902fa3..94dfb1c9385 100644 --- a/lib/api/devicestatus/index.js +++ b/lib/api/devicestatus/index.js @@ -2,6 +2,9 @@ const consts = require('../../constants'); const moment = require('moment'); +const { query } = require('express'); +const _take = require('lodash/take'); +const _ = require('lodash'); function configure (app, wares, ctx, env) { var express = require('express') @@ -18,6 +21,25 @@ function configure (app, wares, ctx, env) { api.use(ctx.authorization.isPermitted('api:devicestatus:read')); + function processDates(results) { + // Support date de-normalization for older clients + + if (env.settings.deNormalizeDates) { + const r = []; + results.forEach(function(e) { + if (e.created_at && Object.prototype.hasOwnProperty.call(e, 'utcOffset')) { + const d = moment(e.created_at).utcOffset(e.utcOffset); + e.created_at = d.toISOString(true); + delete e.utcOffset; + } + r.push(e); + }); + return r; + } else { + return results; + } + } + // List settings available api.get('/devicestatus/', function(req, res) { var q = req.query; @@ -25,21 +47,19 @@ function configure (app, wares, ctx, env) { q.count = 10; } - ctx.devicestatus.list(q, function(err, results) { + const inMemoryData = ctx.cache.devicestatus ? ctx.cache.devicestatus : []; + const canServeFromMemory = inMemoryData.length >= q.count && Object.keys(q).length == 1 ? true : false; - // Support date de-normalization for older clients - if (env.settings.deNormalizeDates) { - results.forEach(function(e) { - // eslint-disable-next-line no-prototype-builtins - if (e.created_at && e.hasOwnProperty('utcOffset')) { - const d = moment(e.created_at).utcOffset(e.utcOffset); - e.created_at = d.toISOString(true); - delete e.utcOffset; - } - }); - } + if (canServeFromMemory) { + const sorted = _.sortBy(inMemoryData, function(item) { + return -item.mills; + }); - return res.json(results); + return res.json(processDates(_take(sorted, q.count))); + } + + ctx.devicestatus.list(q, function(err, results) { + return res.json(processDates(results)); }); }); @@ -106,7 +126,7 @@ function configure (app, wares, ctx, env) { api.delete('/devicestatus/', ctx.authorization.isPermitted('api:devicestatus:delete'), delete_records); } - if (app.enabled('api') || true /*TODO: auth disabled for quick UI testing...*/ ) { + if (app.enabled('api')) { config_authed(app, api, wares, ctx); } diff --git a/lib/api/entries/index.js b/lib/api/entries/index.js index faf922ff0e8..5075df6eded 100644 --- a/lib/api/entries/index.js +++ b/lib/api/entries/index.js @@ -4,6 +4,7 @@ const _last = require('lodash/last'); const _isNil = require('lodash/isNil'); const _first = require('lodash/first'); const _includes = require('lodash/includes'); +const _ = require('lodash'); const moment = require('moment'); const consts = require('../../constants'); @@ -14,8 +15,7 @@ const expand = braces.expand; const ID_PATTERN = /^[a-f\d]{24}$/; function isId (value) { - //TODO: why did we need tht length check? - return value && ID_PATTERN.test(value) && value.length === 24; + return ID_PATTERN.test(value); } /** @@ -69,13 +69,13 @@ function configure (app, wares, ctx, env) { // if element has no data type, but we know what the type should be if (!data.type && opts.type) { // bless absence with known type + // TODO: this doesn't work, it assigns the query rather tham the type data.type = opts.type; } // Support date de-normalization for older clients if (env.settings.deNormalizeDates) { - // eslint-disable-next-line no-prototype-builtins - if (data.dateString && data.hasOwnProperty('utcOffset')) { + if (data.dateString && Object.prototype.hasOwnProperty.call(data, 'utcOffset')) { const d = moment(data.dateString).utcOffset(data.utcOffset); data.dateString = d.toISOString(true); delete data.utcOffset; @@ -106,9 +106,9 @@ function configure (app, wares, ctx, env) { return next(); } - console.log('CGM Entry request with If-Modified-Since: ', ifModifiedSince); + // console.log('CGM Entry request with If-Modified-Since: ', ifModifiedSince); - if (lastEntryDate.getTime() <= Date.parse(ifModifiedSince)) { + if (lastEntryDate && lastEntryDate.getTime() <= Date.parse(ifModifiedSince)) { console.log('Sending Not Modified'); res.status(304).send({ status: 304 @@ -315,6 +315,7 @@ function configure (app, wares, ctx, env) { function prepReqModel (req, model) { var type = model || 'sgv'; if (!req.query.find) { + req.query.find = { type: type }; @@ -428,6 +429,8 @@ function configure (app, wares, ctx, env) { * db queries in a fairly regimented manner. * This middleware executes the query, assigning the payload to results on * `res.entries`. + * If the query can be served from data in the runtime ddata, use the cached + * data and don't query the database. */ function query_models (req, res, next) { var query = req.query; @@ -437,6 +440,45 @@ function configure (app, wares, ctx, env) { query.count = consts.ENTRIES_DEFAULT_COUNT; } + // Check if we can process the query using in-memory data only + let inMemoryPossible = true; + let typeQuery; + + if (query.find) { + Object.keys(query.find).forEach(function(key) { + if (key == 'type') { + typeQuery = query.find[key]["$eq"]; + if (!typeQuery) typeQuery = query.find.type; + } else { + inMemoryPossible = false; + } + }); + } + + let inMemoryCollection; + + if (typeQuery) { + inMemoryCollection= _.filter(ctx.cache.entries, function checkType (object) { + if (typeQuery == 'sgv') return 'sgv' in object; + if (typeQuery == 'mbg') return 'mbg' in object; + if (typeQuery == 'cal') return object.type === 'cal'; + return false; + }); + } else { + inMemoryCollection = ctx.cache.getData('entries'); + + inMemoryCollection = _.sortBy(inMemoryCollection, function(item) { + return item.mills; + }).reverse(); + } + + if (inMemoryPossible && query.count <= inMemoryCollection.length) { + res.entries = _.cloneDeep(_.take(inMemoryCollection,query.count)); + res.entries_err = null; + return next(); + } + + // If we get this far, query the database // bias to entries, but allow expressing a preference var storage = req.storage || ctx.entries; // perform the query diff --git a/lib/api/googlehome/index.js b/lib/api/googlehome/index.js index 2b2caa2a378..cd42aa0ff37 100644 --- a/lib/api/googlehome/index.js +++ b/lib/api/googlehome/index.js @@ -1,10 +1,9 @@ 'use strict'; +var _ = require('lodash'); var moment = require('moment'); -var _each = require('lodash/each'); function configure (app, wares, ctx, env) { - var entries = ctx.entries; var express = require('express') , api = express.Router( ); var translate = ctx.language.translate; @@ -16,34 +15,11 @@ function configure (app, wares, ctx, env) { // json body types get handled as parsed json api.use(wares.bodyParser.json()); - ctx.plugins.eachEnabledPlugin(function each(plugin){ - if (plugin.virtAsst) { - if (plugin.virtAsst.intentHandlers) { - console.log('Google Home: Plugin ' + plugin.name + ' supports Virtual Assistants'); - _each(plugin.virtAsst.intentHandlers, function (route) { - if (route) { - ctx.googleHome.configureIntentHandler(route.intent, route.intentHandler, route.metrics); - } - }); - } - if (plugin.virtAsst.rollupHandlers) { - console.log('Google Home: Plugin ' + plugin.name + ' supports rollups for Virtual Assistants'); - _each(plugin.virtAsst.rollupHandlers, function (route) { - console.log('Route'); - console.log(route); - if (route) { - ctx.googleHome.addToRollup(route.rollupGroup, route.rollupHandler, route.rollupName); - } - }); - } - } else { - console.log('Google Home: Plugin ' + plugin.name + ' does not support Virtual Assistants'); - } - }); + ctx.virtAsstBase.setupVirtAsstHandlers(ctx.googleHome); api.post('/googlehome', ctx.authorization.isPermitted('api:*:read'), function (req, res, next) { console.log('Incoming request from Google Home'); - var locale = req.body.queryResult.languageCode; + var locale = _.get(req, 'body.queryResult.languageCode'); if(locale){ if(locale.length > 2) { locale = locale.substr(0, 2); @@ -58,57 +34,16 @@ function configure (app, wares, ctx, env) { handler(function (title, response) { res.json(ctx.googleHome.buildSpeechletResponse(response, false)); next( ); + return; }, req.body.queryResult.parameters, sbx); } else { - res.json(ctx.googleHome.buildSpeechletResponse('I\'m sorry. I don\'t know what you\'re asking for. Could you say that again?', true)); + res.json(ctx.googleHome.buildSpeechletResponse(translate('virtAsstUnknownIntentText'), true)); next( ); + return; } }); - ctx.googleHome.addToRollup('Status', function bgRollupHandler(slots, sbx, callback) { - entries.list({count: 1}, function (err, records) { - var direction; - if (translate(records[0].direction)) { - direction = translate(records[0].direction); - } else { - direction = records[0].direction; - } - var status = translate('virtAsstStatus', { - params: [ - sbx.scaleMgdl(records[0].sgv), - direction, - moment(records[0].date).from(moment(sbx.time)) - ] - }); - - callback(null, {results: status, priority: -1}); - }); - }, 'BG Status'); - - ctx.googleHome.configureIntentHandler('MetricNow', function (callback, slots, sbx, locale) { - entries.list({count: 1}, function(err, records) { - var direction; - if(translate(records[0].direction)){ - direction = translate(records[0].direction); - } else { - direction = records[0].direction; - } - var status = translate('virtAsstStatus', { - params: [ - sbx.scaleMgdl(records[0].sgv), - direction, - moment(records[0].date).from(moment(sbx.time))] - }); - - callback(translate('virtAsstTitleCurrentBG'), status); - }); - }, ['bg', 'blood glucose', 'number']); - - ctx.googleHome.configureIntentHandler('NSStatus', function (callback, slots, sbx, locale) { - ctx.googleHome.getRollup('Status', sbx, slots, locale, function (status) { - callback(translate('virtAsstTitleFullStatus'), status); - }); - }); + ctx.virtAsstBase.setupMutualIntents(ctx.googleHome); function initializeSandbox() { var sbx = require('../../sandbox')(); @@ -120,4 +55,4 @@ function configure (app, wares, ctx, env) { return api; } -module.exports = configure; \ No newline at end of file +module.exports = configure; diff --git a/lib/api/profile/index.js b/lib/api/profile/index.js index 30f8fe240ca..d00122f16bd 100644 --- a/lib/api/profile/index.js +++ b/lib/api/profile/index.js @@ -16,11 +16,37 @@ function configure (app, wares, ctx) { api.use(wares.bodyParser.urlencoded({ extended: true })); api.use(ctx.authorization.isPermitted('api:profile:read')); + + + /** + * @function query_models + * Perform the standard query logic, translating API parameters into mongo + * db queries in a fairly regimented manner. + * This middleware executes the query, returning the results as JSON + */ + function query_models (req, res, next) { + var query = req.query; + + // If "?count=" is present, use that number to decide how many to return. + if (!query.count) { + query.count = consts.PROFILES_DEFAULT_COUNT; + } + + // perform the query + ctx.profile.list_query(query, function payload(err, profiles) { + return res.json(profiles); + }); + } + + // List profiles available + api.get('/profiles/', query_models); + // List profiles available api.get('/profile/', function(req, res) { + const limit = req.query && req.query.count ? Number(req.query.count) : consts.PROFILES_DEFAULT_COUNT; ctx.profile.list(function (err, attribute) { return res.json(attribute); - }); + }, limit); }); // List current active record (in current state LAST record is current active) diff --git a/lib/api/properties.js b/lib/api/properties.js index 981f3c31328..7e9fd88ebab 100644 --- a/lib/api/properties.js +++ b/lib/api/properties.js @@ -42,6 +42,8 @@ function create (env, ctx) { result = _pick(sbx.properties, selected); } + result = env.settings.filteredSettings(result); + if (req.query && req.query.pretty) { res.setHeader('Content-Type', 'application/json'); res.send(JSON.stringify(result, null, 2)); diff --git a/lib/api/status.js b/lib/api/status.js index a6ab2e82750..56196114a07 100644 --- a/lib/api/status.js +++ b/lib/api/status.js @@ -14,8 +14,11 @@ function configure (app, wares, env, ctx) { // Status badge/text/json api.get('/status', function (req, res) { + + let extended = env.settings.filteredSettings(app.extendedClientSettings); + let settings = env.settings.filteredSettings(env.settings); - var authToken = req.query.token || req.query.secret || ''; + var authToken = req.query.token || req.query.secret || ''; var date = new Date(); var info = { status: 'ok' @@ -26,9 +29,10 @@ function configure (app, wares, env, ctx) { , apiEnabled: app.enabled('api') , careportalEnabled: app.enabled('api') && env.settings.enable.indexOf('careportal') > -1 , boluscalcEnabled: app.enabled('api') && env.settings.enable.indexOf('boluscalc') > -1 - , settings: env.settings - , extendedSettings: app.extendedClientSettings + , settings: settings + , extendedSettings: extended , authorized: ctx.authorization.authorize(authToken) + , runtimeState: ctx.runtimeState }; var badge = 'http://img.shields.io/badge/Nightscout-OK-green'; diff --git a/lib/api/treatments/index.js b/lib/api/treatments/index.js index 5d527fce6ac..0e1d8a0ede8 100644 --- a/lib/api/treatments/index.js +++ b/lib/api/treatments/index.js @@ -1,11 +1,12 @@ 'use strict'; -var _forEach = require('lodash/forEach'); -var _isNil = require('lodash/isNil'); -var _isArray = require('lodash/isArray'); +const _forEach = require('lodash/forEach'); +const _isNil = require('lodash/isNil'); +const _isArray = require('lodash/isArray'); +const _take = require('lodash/take'); -var consts = require('../../constants'); -var moment = require('moment'); +const constants = require('../../constants'); +const moment = require('moment'); function configure (app, wares, ctx, env) { var express = require('express') @@ -33,55 +34,73 @@ function configure (app, wares, ctx, env) { api.use(ctx.authorization.isPermitted('api:treatments:read')); - // List treatments available - api.get('/treatments', function(req, res) { - var ifModifiedSince = req.get('If-Modified-Since'); - ctx.treatments.list(req.query, function(err, results) { - var d1 = null; + function serveTreatments(req,res, err, results) { - const deNormalizeDates = env.settings.deNormalizeDates; + var ifModifiedSince = req.get('If-Modified-Since'); - _forEach(results, function clean (t) { - t.carbs = Number(t.carbs); - t.insulin = Number(t.insulin); + var d1 = null; - // eslint-disable-next-line no-prototype-builtins - if (deNormalizeDates && t.hasOwnProperty('utcOffset')) { - const d = moment(t.created_at).utcOffset(t.utcOffset); - t.created_at = d.toISOString(true); - delete t.utcOffset; - } + const deNormalizeDates = env.settings.deNormalizeDates; - var d2 = null; + _forEach(results, function clean (t) { + t.carbs = Number(t.carbs); + t.insulin = Number(t.insulin); - if (t.hasOwnProperty('created_at')) { - d2 = new Date(t.created_at); - } else { - if (t.hasOwnProperty('timestamp')) { - d2 = new Date(t.timestamp); - } - } + if (deNormalizeDates && Object.prototype.hasOwnProperty.call(t, 'utcOffset')) { + const d = moment(t.created_at).utcOffset(t.utcOffset); + t.created_at = d.toISOString(true); + delete t.utcOffset; + } - if (d2 == null) { return; } + var d2 = null; - if (d1 == null || d2.getTime() > d1.getTime()) { - d1 = d2; + if (Object.prototype.hasOwnProperty.call(t, 'created_at')) { + d2 = new Date(t.created_at); + } else { + if (Object.prototype.hasOwnProperty.call(t, 'timestamp')) { + d2 = new Date(t.timestamp); } - }); + } - if (!_isNil(d1)) res.setHeader('Last-Modified', d1.toUTCString()); + if (d2 == null) { return; } - if (ifModifiedSince && d1.getTime() <= moment(ifModifiedSince).valueOf()) { - res.status(304).send({ - status: 304 - , message: 'Not modified' - , type: 'internal' - }); - return; - } else { - return res.json(results); + if (d1 == null || d2.getTime() > d1.getTime()) { + d1 = d2; } }); + + if (!_isNil(d1)) res.setHeader('Last-Modified', d1.toUTCString()); + + if (ifModifiedSince && d1.getTime() <= moment(ifModifiedSince).valueOf()) { + res.status(304).send({ + status: 304 + , message: 'Not modified' + , type: 'internal' + }); + return; + } else { + return res.json(results); + } + } + + // List treatments available + api.get('/treatments', function(req, res) { + var query = req.query; + if (!query.count) { + // If there's a date search involved, default to a higher number of objects + query.count = query.find ? 1000 : 100; + } + + const inMemoryData = ctx.cache.treatments; + const canServeFromMemory = inMemoryData && inMemoryData.length >= query.count && Object.keys(query).length == 1 ? true : false; + + if (canServeFromMemory) { + serveTreatments(req, res, null, _take(inMemoryData,query.count)); + } else { + ctx.treatments.list(query, function(err, results) { + serveTreatments(req,res,err,results); + }); + } }); function config_authed (app, api, wares, ctx) { @@ -91,14 +110,37 @@ function configure (app, wares, ctx, env) { if (!_isArray(treatments)) { treatments = [treatments]; - }; + } + + for (let i = 0; i < treatments.length; i++) { + const t = treatments[i]; + + if (!t.created_at) { + t.created_at = new Date().toISOString(); + } + + /* + if (!t.created_at) { + console.log('Trying to create treatment without created_at field', t); + res.sendJSONStatus(res, constants.HTTP_VALIDATION_ERROR, 'Treatments must contain created_at'); + return; + } + const d = moment(t.created_at); + if (!d.isValid()) { + console.log('Trying to insert date with invalid created_at', t); + res.sendJSONStatus(res, constants.HTTP_VALIDATION_ERROR, 'Treatments created_at must be an ISO-8601 date'); + return; + } + */ + + } ctx.treatments.create(treatments, function(err, created) { if (err) { console.log('Error adding treatment', err); - res.sendJSONStatus(res, consts.HTTP_INTERNAL_ERROR, 'Mongo Error', err); + res.sendJSONStatus(res, constants.HTTP_INTERNAL_ERROR, 'Mongo Error', err); } else { - console.log('Treatment created'); + console.log('REST API treatment created', created); res.json(created); } }); @@ -119,19 +161,16 @@ function configure (app, wares, ctx, env) { query.count = 10 } - console.log('Delete records with query: ', query); - // remove using the query ctx.treatments.remove(query, function(err, stat) { if (err) { console.log('treatments delete error: ', err); return next(err); } + // yield some information about success of operation res.json(stat); - console.log('treatments records deleted'); - return next(); }); } @@ -160,9 +199,8 @@ function configure (app, wares, ctx, env) { var data = req.body; ctx.treatments.save(data, function(err, created) { if (err) { - res.sendJSONStatus(res, consts.HTTP_INTERNAL_ERROR, 'Mongo Error', err); - console.log('Error saving treatment'); - console.log(err); + res.sendJSONStatus(res, constants.HTTP_INTERNAL_ERROR, 'Mongo Error', err); + console.log('Error saving treatment', err); } else { res.json(created); console.log('Treatment saved', data); diff --git a/lib/api3/const.json b/lib/api3/const.json index 1c3dfd873ee..fd874a1175a 100644 --- a/lib/api3/const.json +++ b/lib/api3/const.json @@ -15,6 +15,7 @@ "UNAUTHORIZED": 401, "FORBIDDEN": 403, "NOT_FOUND": 404, + "NOT_ACCEPTABLE": 406, "GONE": 410, "PRECONDITION_FAILED": 412, "UNPROCESSABLE_ENTITY": 422, @@ -40,6 +41,7 @@ "HTTP_401_MISSING_OR_BAD_TOKEN": "Missing or bad access token or JWT", "HTTP_403_MISSING_PERMISSION": "Missing permission {0}", "HTTP_403_NOT_USING_HTTPS": "Not using SSL/TLS", + "HTTP_406_UNSUPPORTED_FORMAT": "Unsupported output format requested", "HTTP_422_READONLY_MODIFICATION": "Trying to modify read-only document", "HTTP_500_INTERNAL_ERROR": "Internal Server Error", "STORAGE_ERROR": "Database error", diff --git a/lib/api3/doc/formats.md b/lib/api3/doc/formats.md new file mode 100644 index 00000000000..5a01a802f3e --- /dev/null +++ b/lib/api3/doc/formats.md @@ -0,0 +1,88 @@ +# APIv3: Output formats + +### Choosing output format +In APIv3, the standard content type is JSON for both HTTP request and HTTP response. +However, in HTTP response, the response content type can be changed to XML or CSV +for READ, SEARCH, and HISTORY operations. + +The response content type can be requested in one of the following ways: +- add a file type extension to the URL, eg. + `/api/v3/entries.csv?...` + or `/api/v3/treatments/95e1a6e3-1146-5d6a-a3f1-41567cae0895.xml?...` +- set `Accept` HTTP request header to `text/csv` or `application/xml` + +The server replies with `406 Not Acceptable` HTTP status in case of not supported content type. + + +### JSON + +Default content type is JSON, output can look like this: + +``` +[ + { + "type":"sgv", + "sgv":"171", + "dateString":"2014-07-19T02:44:15.000-07:00", + "date":1405763055000, + "device":"dexcom", + "direction":"Flat", + "identifier":"5c5a2404e0196f4d3d9a718a", + "srvModified":1405763055000, + "srvCreated":1405763055000 + }, + { + "type":"sgv", + "sgv":"176", + "dateString":"2014-07-19T03:09:15.000-07:00", + "date":1405764555000, + "device":"dexcom", + "direction":"Flat", + "identifier":"5c5a2404e0196f4d3d9a7187", + "srvModified":1405764555000, + "srvCreated":1405764555000 + } +] +``` + +### XML + +Sample output: + +``` + + + + sgv + 171 + 2014-07-19T02:44:15.000-07:00 + 1405763055000 + dexcom + Flat + 5c5a2404e0196f4d3d9a718a + 1405763055000 + 1405763055000 + + + sgv + 176 + 2014-07-19T03:09:15.000-07:00 + 1405764555000 + dexcom + Flat + 5c5a2404e0196f4d3d9a7187 + 1405764555000 + 1405764555000 + + +``` + +### CSV + +Sample output: + +``` +type,sgv,dateString,date,device,direction,identifier,srvModified,srvCreated +sgv,171,2014-07-19T02:44:15.000-07:00,1405763055000,dexcom,Flat,5c5a2404e0196f4d3d9a718a,1405763055000,1405763055000 +sgv,176,2014-07-19T03:09:15.000-07:00,1405764555000,dexcom,Flat,5c5a2404e0196f4d3d9a7187,1405764555000,1405764555000 +``` diff --git a/lib/api3/doc/tutorial.md b/lib/api3/doc/tutorial.md index 3d8c656dfbd..d69e95ef4a4 100644 --- a/lib/api3/doc/tutorial.md +++ b/lib/api3/doc/tutorial.md @@ -11,7 +11,7 @@ Each NS instance with API v3 contains self-included OpenAPI specification at [/a --- ### VERSION -[VERSION](https://nsapiv3.herokuapp.com/api/v3/swagger-ui-dist/#/other/get_version) operation gets you basic information about software packages versions. +[VERSION](https://nsapiv3.herokuapp.com/api3-docs/#/other/get_version) operation gets you basic information about software packages versions. It is public (there is no need to add authorization parameters/headers). Sample GET `/version` client code (to get actual versions): @@ -38,7 +38,7 @@ Sample result: --- ### STATUS -[STATUS](https://nsapiv3.herokuapp.com/api/v3/swagger-ui-dist/#/other/get_status) operation gets you basic information about software packages versions. +[STATUS](https://nsapiv3.herokuapp.com/api3-docs/#/other/get_status) operation gets you basic information about software packages versions. It is public (there is no need to add authorization parameters/headers). Sample GET `/status` client code (to get my actual permissions): @@ -75,7 +75,7 @@ Sample result: --- ### SEARCH -[SEARCH](https://nsapiv3insecure.herokuapp.com/api/v3/swagger-ui-dist/index.html#/generic/SEARCH) operation filters, sorts, paginates and projects documents from the collection. +[SEARCH](https://nsapiv3insecure.herokuapp.com/api3-docs/#/generic/SEARCH) operation filters, sorts, paginates and projects documents from the collection. Sample GET `/entries` client code (to retrieve last 3 BG values): ```javascript @@ -110,7 +110,7 @@ Sample result: --- ### CREATE -[CREATE](https://nsapiv3.herokuapp.com/api/v3/swagger-ui-dist/#/generic/post__collection_) operation inserts a new document into the collection. +[CREATE](https://nsapiv3.herokuapp.com/api3-docs/#/generic/post__collection_) operation inserts a new document into the collection. Sample POST `/treatments` client code: ```javascript @@ -140,7 +140,7 @@ Sample result: --- ### READ -[READ](https://nsapiv3.herokuapp.com/api/v3/swagger-ui-dist/#/generic/get__collection___identifier_) operation retrieves you a single document from the collection by its identifier. +[READ](https://nsapiv3.herokuapp.com/api3-docs/#/generic/get__collection___identifier_) operation retrieves you a single document from the collection by its identifier. Sample GET `/treatments/{identifier}` client code: ```javascript @@ -172,7 +172,7 @@ Sample result: --- ### LAST MODIFIED -[LAST MODIFIED](https://nsapiv3insecure.herokuapp.com/api/v3/swagger-ui-dist/index.html#/other/LAST-MODIFIED) operation finds the date of last modification for each collection. +[LAST MODIFIED](https://nsapiv3insecure.herokuapp.com/api3-docs/#/other/LAST-MODIFIED) operation finds the date of last modification for each collection. Sample GET `/lastModified` client code (to get latest modification dates): ```javascript @@ -199,7 +199,7 @@ Sample result: --- ### UPDATE -[UPDATE](https://nsapiv3insecure.herokuapp.com/api/v3/swagger-ui-dist/index.html#/generic/put__collection___identifier_) operation updates existing document in the collection. +[UPDATE](https://nsapiv3insecure.herokuapp.com/api3-docs/#/generic/put__collection___identifier_) operation updates existing document in the collection. Sample PUT `/treatments/{identifier}` client code (to update `insulin` from 0.3 to 0.4): ```javascript @@ -231,7 +231,7 @@ Sample result: --- ### PATCH -[PATCH](https://nsapiv3insecure.herokuapp.com/api/v3/swagger-ui-dist/index.html#/generic/patch__collection___identifier_) operation partially updates existing document in the collection. +[PATCH](https://nsapiv3insecure.herokuapp.com/api3-docs/#/generic/patch__collection___identifier_) operation partially updates existing document in the collection. Sample PATCH `/treatments/{identifier}` client code (to update `insulin` from 0.4 to 0.5): ```javascript @@ -259,7 +259,7 @@ Sample result: --- ### DELETE -[DELETE](https://nsapiv3insecure.herokuapp.com/api/v3/swagger-ui-dist/index.html#/generic/delete__collection___identifier_) operation deletes existing document from the collection. +[DELETE](https://nsapiv3insecure.herokuapp.com/api3-docs/#/generic/delete__collection___identifier_) operation deletes existing document from the collection. Sample DELETE `/treatments/{identifier}` client code (to update `insulin` from 0.4 to 0.5): ```javascript @@ -282,7 +282,7 @@ Sample result: --- ### HISTORY -[HISTORY](https://nsapiv3insecure.herokuapp.com/api/v3/swagger-ui-dist/index.html#/generic/HISTORY2) operation queries all changes since the timestamp. +[HISTORY](https://nsapiv3insecure.herokuapp.com/api3-docs/#/generic/HISTORY2) operation queries all changes since the timestamp. Sample HISTORY `/treatments/history/{lastModified}` client code: ```javascript @@ -326,4 +326,4 @@ Sample result: } ] ``` -Notice the `"isValid":false` field marking the deletion of the document. \ No newline at end of file +Notice the `"isValid":false` field marking the deletion of the document. diff --git a/lib/api3/generic/create/insert.js b/lib/api3/generic/create/insert.js index 4ac80a37e94..b643818569a 100644 --- a/lib/api3/generic/create/insert.js +++ b/lib/api3/generic/create/insert.js @@ -3,6 +3,7 @@ const apiConst = require('../../const.json') , security = require('../../security') , validate = require('./validate.js') + , path = require('path') ; /** @@ -33,7 +34,7 @@ async function insert (opCtx, doc) { throw new Error('empty identifier'); res.setHeader('Last-Modified', now.toUTCString()); - res.setHeader('Location', `${req.baseUrl}${req.path}/${identifier}`); + res.setHeader('Location', path.posix.join(req.baseUrl, req.path, identifier)); res.status(apiConst.HTTP.CREATED).send({ }); ctx.bus.emit('storage-socket-create', { colName: col.colName, doc }); diff --git a/lib/api3/generic/history/operation.js b/lib/api3/generic/history/operation.js index 0929a09cc4f..5151c8b2749 100644 --- a/lib/api3/generic/history/operation.js +++ b/lib/api3/generic/history/operation.js @@ -1,6 +1,7 @@ 'use strict'; const dateTools = require('../../shared/dateTools') + , renderer = require('../../shared/renderer') , apiConst = require('../../const.json') , security = require('../../security') , opTools = require('../../shared/operationTools') @@ -53,7 +54,8 @@ async function history (opCtx, fieldsProjector) { _.each(result, fieldsProjector.applyProjection); - res.status(apiConst.HTTP.OK).send(result); + res.status(apiConst.HTTP.OK); + renderer.render(res, result); } } diff --git a/lib/api3/generic/read/operation.js b/lib/api3/generic/read/operation.js index 04d6f03bc70..c2e65a4afcc 100644 --- a/lib/api3/generic/read/operation.js +++ b/lib/api3/generic/read/operation.js @@ -4,6 +4,7 @@ const apiConst = require('../../const.json') , security = require('../../security') , opTools = require('../../shared/operationTools') , dateTools = require('../../shared/dateTools') + , renderer = require('../../shared/renderer') , FieldsProjector = require('../../shared/fieldsProjector') ; @@ -48,7 +49,8 @@ async function read (opCtx) { fieldsProjector.applyProjection(doc); - res.status(apiConst.HTTP.OK).send(doc); + res.status(apiConst.HTTP.OK); + renderer.render(res, doc); } diff --git a/lib/api3/generic/search/operation.js b/lib/api3/generic/search/operation.js index 074f864d58a..c24f978dc27 100644 --- a/lib/api3/generic/search/operation.js +++ b/lib/api3/generic/search/operation.js @@ -3,6 +3,7 @@ const apiConst = require('../../const.json') , security = require('../../security') , opTools = require('../../shared/operationTools') + , renderer = require('../../shared/renderer') , input = require('./input') , _each = require('lodash/each') , FieldsProjector = require('../../shared/fieldsProjector') @@ -49,7 +50,8 @@ async function search (opCtx) { _each(result, fieldsProjector.applyProjection); - res.status(apiConst.HTTP.OK).send(result); + res.status(apiConst.HTTP.OK); + renderer.render(res, result); } } diff --git a/lib/api3/generic/update/replace.js b/lib/api3/generic/update/replace.js index ca490b31136..fdf803ed16f 100644 --- a/lib/api3/generic/update/replace.js +++ b/lib/api3/generic/update/replace.js @@ -3,6 +3,7 @@ const apiConst = require('../../const.json') , security = require('../../security') , validate = require('./validate.js') + , path = require('path') ; /** @@ -38,7 +39,7 @@ async function replace (opCtx, doc, storageDoc, options) { res.setHeader('Last-Modified', now.toUTCString()); if (storageDoc.identifier !== doc.identifier || isDeduplication) { - res.setHeader('Location', `${req.baseUrl}${req.path}/${doc.identifier}`); + res.setHeader('Location', path.posix.join(req.baseUrl, req.path, doc.identifier)); } res.status(apiConst.HTTP.NO_CONTENT).send({ }); diff --git a/lib/api3/index.js b/lib/api3/index.js index 5b1799c78fd..bff0899536f 100644 --- a/lib/api3/index.js +++ b/lib/api3/index.js @@ -2,11 +2,11 @@ const express = require('express') , bodyParser = require('body-parser') + , renderer = require('./shared/renderer') , StorageSocket = require('./storageSocket') , apiConst = require('./const.json') , security = require('./security') , genericSetup = require('./generic/setup') - , swaggerSetup = require('./swagger') ; function configure (env, ctx) { @@ -34,7 +34,7 @@ function configure (env, ctx) { self.setupApiEnvironment = function setupApiEnvironment () { - + app.use(bodyParser.json({ limit: 1048576 * 50 }), function errorHandler (err, req, res, next) { @@ -47,6 +47,8 @@ function configure (env, ctx) { } }); + app.use(renderer.extension2accept); + // we don't need these here app.set('etag', false); app.set('x-powered-by', false); // this seems to be unreliable @@ -74,7 +76,7 @@ function configure (env, ctx) { app.get('/version', require('./specific/version')(app, ctx, env)); - if (app.get('env') === 'development' || app.get('ci')) { // for development and testing purposes only + if (app.get('env') === 'development' || app.get('ci')) { // for development and testing purposes only app.get('/test', async function test (req, res) { try { @@ -97,7 +99,10 @@ function configure (env, ctx) { self.setupApiEnvironment(); genericSetup(ctx, env, app); self.setupApiRoutes(); - swaggerSetup(app); + + app.use('/swagger-ui-dist', (req, res) => { + res.redirect(307, '../../../api3-docs'); + }); ctx.storageSocket = new StorageSocket(app, env, ctx); diff --git a/lib/api3/shared/renderer.js b/lib/api3/shared/renderer.js new file mode 100644 index 00000000000..a3588819a72 --- /dev/null +++ b/lib/api3/shared/renderer.js @@ -0,0 +1,99 @@ +'use strict'; + +const apiConst = require('../const.json') + , mime = require('mime') + , url = require('url') + , opTools = require('./operationTools') + , EasyXml = require('easyxml') + , csvStringify = require('csv-stringify') + ; + + +/** + * Middleware that converts url's extension to Accept HTTP request header + * @param {Object} req + * @param {Object} res + * @param {Function} next + */ +function extension2accept (req, res, next) { + + const pathSplit = req.path.split('.'); + + if (pathSplit.length < 2) + return next(); + + const pathBase = pathSplit[0] + , extension = pathSplit.slice(1).join('.'); + + if (!extension) + return next(); + + const mimeType = mime.getType(extension); + if (!mimeType) + return opTools.sendJSONStatus(res, apiConst.HTTP.NOT_ACCEPTABLE, apiConst.MSG.HTTP_406_UNSUPPORTED_FORMAT); + + req.extToAccept = { + url: req.url, + accept: req.headers.accept + }; + + req.headers.accept = mimeType; + const parsed = url.parse(req.url); + parsed.pathname = pathBase; + req.url = url.format(parsed); + + next(); +} + + +/** + * Sends data to output using the client's desired format + * @param {Object} res + * @param {any} data + */ +function render (res, data) { + res.format({ + 'json': () => res.send(data), + 'csv': () => renderCsv(res, data), + 'xml': () => renderXml(res, data), + 'default': () => + opTools.sendJSONStatus(res, apiConst.HTTP.NOT_ACCEPTABLE, apiConst.MSG.HTTP_406_UNSUPPORTED_FORMAT) + }); +} + + +/** + * Format data to output as .csv + * @param {Object} res + * @param {any} data + */ +function renderCsv (res, data) { + const csvSource = Array.isArray(data) ? data : [data]; + csvStringify(csvSource, { + header: true + }, + function csvStringified (err, output) { + res.send(output); + }); +} + + +/** + * Format data to output as .xml + * @param {Object} res + * @param {any} data + */ +function renderXml (res, data) { + const serializer = new EasyXml({ + rootElement: 'item', + dateFormat: 'ISO', + manifest: true + }); + res.send(serializer.render(data)); +} + + +module.exports = { + extension2accept, + render +}; \ No newline at end of file diff --git a/lib/api3/swagger.js b/lib/api3/swagger.js deleted file mode 100644 index 2d434e97f53..00000000000 --- a/lib/api3/swagger.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -const express = require('express') - , fs = require('fs') - ; - - -function setupSwaggerUI (app) { - - const serveSwaggerDef = function serveSwaggerDef (req, res) { - res.sendFile(__dirname + '/swagger.yaml'); - }; - app.get('/swagger.yaml', serveSwaggerDef); - - const swaggerUiAssetPath = require('swagger-ui-dist').getAbsoluteFSPath(); - const swaggerFiles = express.static(swaggerUiAssetPath); - - const urlRegex = /url: "[^"]*",/; - - const patchIndex = function patchIndex (req, res) { - const indexContent = fs.readFileSync(`${swaggerUiAssetPath}/index.html`) - .toString() - .replace(urlRegex, 'url: "../swagger.yaml",'); - res.send(indexContent); - }; - - app.get('/swagger-ui-dist', function getSwaggerRoot (req, res) { - let targetUrl = req.originalUrl; - if (!targetUrl.endsWith('/')) { - targetUrl += '/'; - } - targetUrl += 'index.html'; - res.redirect(targetUrl); - }); - app.get('/swagger-ui-dist/index.html', patchIndex); - - app.use('/swagger-ui-dist', swaggerFiles); -} - - -module.exports = setupSwaggerUI; \ No newline at end of file diff --git a/lib/api3/swagger.json b/lib/api3/swagger.json new file mode 100644 index 00000000000..b20bb0e6761 --- /dev/null +++ b/lib/api3/swagger.json @@ -0,0 +1,2251 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Nightscout API", + "description": "Nightscout API v3 is a component of cgm-remote-monitor project. It aims to provide lightweight, secured and HTTP REST compliant interface for your T1D treatment data exchange.\n\nAPI v3 uses these environment variables, among other things:\n- Security switch (optional, default = `true`)
API3_SECURITY_ENABLE=true
You can turn the whole security mechanism off, e.g. for debugging or development purposes, but this should never be set to false in production.\n\n- Number of minutes of acceptable time skew between client's and server's clock (optional, default = 5)
API3_TIME_SKEW_TOLERANCE=5
This security parameter is used for preventing anti-replay attacks, specifically when checking the time from `Date` header.\n\n- Maximum limit count of documents retrieved from single query
API3_MAX_LIMIT=1000
\n\n- Autopruning of obsolete documents (optional, default is only `DEVICESTATUS`=60)
API3_AUTOPRUNE_DEVICESTATUS=60\nAPI3_AUTOPRUNE_ENTRIES=365\nAPI3_AUTOPRUNE_TREATMENTS=120 
You can specify for which collections autopruning will be activated and length of retention period in days, e.g. \"Hold 60 days of devicestatus, automatically delete older documents, hold 365 days of treatments and entries, automatically delete older documents.\"\n\n- Fallback deduplication switch (optional, default = true)
API3_DEDUP_FALLBACK_ENABLED=true
API3 uses the `identifier` field for document identification and mutual distinction within a single collection. There is automatic deduplication implemented matching the equal `identifier` field. E.g. `CREATE` operation for document having the same `identifier` as another one existing in the database is automatically transformed into `UPDATE` operation of the document found in the database.\nDocuments not created via API v3 usually does not have any `identifier` field, but we would like to have some form of deduplication for them, too. This fallback deduplication is turned on by having set `API3_DEDUP_FALLBACK_ENABLED` to `true`. When searching the collection in database, the document is found to be a duplicate only when either he has equal `identifier` or he has no `identifier` and meets:
`devicestatus` collection: equal combination of `created_at` and `device`\n`entries` collection:      equal combination of `date` and `type`\n`food` collection:         equal `created_at`\n`profile` collection:      equal `created_at`\n`treatments` collection:   equal combination of `created_at` and `eventType` 
\n\n- Fallback switch for adding `created_at` field along the `date` field (optional, default = true)
API3_CREATED_AT_FALLBACK_ENABLED=true
Standard APIv3 document model uses only `date` field for storing a timestamp of the event recorded by the document. But there is a fallback option to fill `created_at` field as well automatically on each insert/update, just to keep all older components working.", + "contact": { + "name": "NS development discussion channel", + "url": "https://gitter.im/nightscout/public" + }, + "license": { + "name": "AGPL 3", + "url": "https://www.gnu.org/licenses/agpl.txt" + }, + "version": "3.0.1" + }, + "servers": [ + { + "url": "/api/v3" + } + ], + "tags": [ + { + "name": "generic", + "description": "Generic operations with each database collection (devicestatus, entries, food, profile, settings, treatments)" + }, + { + "name": "other", + "description": "All other various operations" + } + ], + "paths": { + "/{collection}": { + "get": { + "tags": [ + "generic" + ], + "summary": "SEARCH: Search documents from the collection", + "description": "General search operation through documents of one collection, matching the specified filtering criteria. You can apply:\n\n1) filtering - combining any number of filtering parameters\n\n2) ordering - using `sort` or `sort$desc` parameter\n\n3) paging - using `limit` and `skip` parameters\n\nWhen there is no document matching the filtering criteria, HTTP status 204 is returned with empty response content. Otherwise HTTP 200 code is returned with JSON array of matching documents as a response content.\n\nThis operation requires `read` permission for the API and the collection (e.g. `*:*:read`, `api:*:read`, `*:treatments:read`, `api:treatments:read`).\n\nThe only exception is the `settings` collection which requires `admin` permission (`api:settings:admin`), because the settings of each application should be isolated and kept secret. You need to know the concrete identifier to access the app's settings.", + "operationId": "SEARCH", + "parameters": [ + { + "name": "collection", + "in": "path", + "description": "Collection to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramCollection" + } + }, + { + "name": "Date", + "in": "header", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory header serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `now` query parameter.\nExample:\n\n
Date: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + { + "name": "now", + "in": "query", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory parameter serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `Date` header.\n\nExample:\n\n
now=1525383610088
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "token", + "in": "query", + "description": "An alternative way of authorization - passing accessToken in a query parameter.\n\nExample:\n\n
token=testadmin-bf2591231bd2c042
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + { + "name": "filter_parameters", + "in": "query", + "description": "Any number of filtering operators.\n\nEach filtering operator has name like `$`, e.g. `carbs$gt=2` which represents filtering rule \"The field carbs must be present and greater than 2\".\n\nYou can choose from operators:\n\n`eq`=equals, `insulin$eq=1.5`\n\n`ne`=not equals, `insulin$ne=1.5`\n\n`gt`=greater than, `carbs$gt=30`\n\n`gte`=greater than or equal, `carbs$gte=30`\n\n`lt`=less than, `carbs$lt=30`\n\n`lte`=less than or equal, `carbs$lte=30`\n\n`in`=in specified set, `type$in=sgv|mbg|cal`\n\n`nin`=not in specified set, `eventType$nin=Temp%20Basal|Temporary%20Target`\n\n`re`=regex pattern, `eventType$re=Temp.%2A`\n\nWhen filtering by field `date`, `created_at`, `srvModified` or `srvCreated`, you can choose from three input formats\n- Unix epoch in milliseconds (1525383610088)\n- Unix epoch in seconds (1525383610)\n- ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00')\n\nThe date is always queried in a normalized form - UTC with zero offset and with the correct format (1525383610088 for `date`, '2018-05-03T21:40:10.088Z' for `created_at`).", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + { + "name": "sort", + "in": "query", + "description": "Field name by which the sorting of documents is performed. This parameter cannot be combined with `sort$desc` parameter.", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + { + "name": "sort$desc", + "in": "query", + "description": "Field name by which the descending (reverse) sorting of documents is performed. This parameter cannot be combined with `sort` parameter.", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of documents to get in result array", + "required": false, + "style": "form", + "explode": true, + "schema": { + "minimum": 1, + "type": "integer", + "example": 100 + } + }, + { + "name": "skip", + "in": "query", + "description": "Number of documents to skip from collection query before loading them into result array (used for pagination)", + "required": false, + "style": "form", + "explode": true, + "schema": { + "minimum": 0, + "type": "integer", + "example": 0, + "default": 0 + } + }, + { + "name": "fields", + "in": "query", + "description": "A chosen set of fields to return in response. Either you can enumerate specific fields of interest or use the predefined set. Sample parameter values:\n\n_all: All fields will be returned (default value)\n\ndate,insulin: Only fields `date` and `insulin` will be returned", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string", + "default": "_all" + }, + "examples": { + "all": { + "summary": "All fields will be returned (default behaviour)", + "value": "_all" + }, + "customSet": { + "summary": "Only fields date and insulin will be returned", + "value": "date,insulin" + } + } + } + ], + "responses": { + "200": { + "description": "Successful operation returning array of documents matching the filtering criteria", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + }, + "text/csv": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + } + } + }, + "204": { + "description": "Successful operation - no documents matching the filtering criteria" + }, + "400": { + "description": "The request is malformed. There may be some required parameters missing or there are unrecognized parameters present." + }, + "401": { + "description": "The request was not successfully authenticated using access token or JWT, or the request has missing `Date` header or it contains an expired timestamp, so that the request cannot continue due to the security policy." + }, + "403": { + "description": "Insecure HTTP scheme used or the request has been successfully authenticated, but the security subject is not authorized for the operation." + }, + "404": { + "description": "The collection or document specified was not found." + }, + "406": { + "description": "The requested content type (in `Accept` header) is not supported." + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + }, + "post": { + "tags": [ + "generic" + ], + "summary": "CREATE: Inserts a new document into the collection", + "description": "Using this operation you can insert new documents into collection. Normally the operation ends with 201 HTTP status code, `Last-Modified` and `Location` headers specified and with an empty response content. `identifier` can be parsed from the `Location` response header.\n\nWhen the document to post is marked as a duplicate (using rules described at `API3_DEDUP_FALLBACK_ENABLED` switch), the update operation takes place instead of inserting. In this case the original document in the collection is found and it gets updated by the actual operation POST body. Finally the operation ends with 204 HTTP status code along with `Last-Modified` and correct `Location` headers.\n\nThis operation provides autopruning of the collection (if autopruning is enabled).\n\nThis operation requires `create` (and/or `update` for deduplication) permission for the API and the collection (e.g. `api:treatments:create` and `api:treatments:update`)", + "parameters": [ + { + "name": "collection", + "in": "path", + "description": "Collection to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramCollection" + } + }, + { + "name": "Date", + "in": "header", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory header serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `now` query parameter.\nExample:\n\n
Date: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + { + "name": "now", + "in": "query", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory parameter serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `Date` header.\n\nExample:\n\n
now=1525383610088
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "token", + "in": "query", + "description": "An alternative way of authorization - passing accessToken in a query parameter.\n\nExample:\n\n
token=testadmin-bf2591231bd2c042
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "JSON with new document to insert", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentToPost" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Successfully created a new document in collection", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + }, + "Location": { + "$ref": "#/components/schemas/headerLocation" + } + } + }, + "204": { + "description": "Successfully finished operation", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + }, + "Location": { + "$ref": "#/components/schemas/headerLocation" + } + } + }, + "400": { + "description": "The request is malformed. There may be some required parameters missing or there are unrecognized parameters present." + }, + "401": { + "description": "The request was not successfully authenticated using access token or JWT, or the request has missing `Date` header or it contains an expired timestamp, so that the request cannot continue due to the security policy." + }, + "403": { + "description": "Insecure HTTP scheme used or the request has been successfully authenticated, but the security subject is not authorized for the operation." + }, + "404": { + "description": "The collection or document specified was not found." + }, + "422": { + "description": "The client request is well formed but a server validation error occured. Eg. when trying to modify or delete a read-only document (having `isReadOnly=true`)." + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + } + }, + "/{collection}/{identifier}": { + "get": { + "tags": [ + "generic" + ], + "summary": "READ: Retrieves a single document from the collection", + "description": "Basically this operation looks for a document matching the `identifier` field returning 200 or 404 HTTP status code.\n\nIf the document has been found in the collection but it had already been deleted, 410 HTTP status code with empty response content is to be returned.\n\nWhen `If-Modified-Since` header is used and its value is greater than the timestamp of the document in the collection, 304 HTTP status code with empty response content is returned. It means that the document has not been modified on server since the last retrieval to client side. With `If-Modified-Since` header and less or equal timestamp `srvModified` a normal 200 HTTP status with full response is returned.\n\nThis operation requires `read` permission for the API and the collection (e.g. `api:treatments:read`)", + "parameters": [ + { + "name": "collection", + "in": "path", + "description": "Collection to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramCollection" + } + }, + { + "name": "identifier", + "in": "path", + "description": "Identifier of the document to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramIdentifier" + } + }, + { + "name": "Date", + "in": "header", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory header serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `now` query parameter.\nExample:\n\n
Date: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + { + "name": "now", + "in": "query", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory parameter serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `Date` header.\n\nExample:\n\n
now=1525383610088
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "token", + "in": "query", + "description": "An alternative way of authorization - passing accessToken in a query parameter.\n\nExample:\n\n
token=testadmin-bf2591231bd2c042
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + { + "name": "If-Modified-Since", + "in": "header", + "description": "Timestamp (defined with respect to server's clock) of the last document modification formatted as:\n\n<day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT\n\nIf this header is present, the operation will compare its value with the srvModified timestamp of the document at first and the operation result then may differ. The srvModified timestamp was defined by server's clock.\n\nExample:\n\n
If-Modified-Since: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + { + "name": "fields", + "in": "query", + "description": "A chosen set of fields to return in response. Either you can enumerate specific fields of interest or use the predefined set. Sample parameter values:\n\n_all: All fields will be returned (default value)\n\ndate,insulin: Only fields `date` and `insulin` will be returned", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string", + "default": "_all" + }, + "examples": { + "all": { + "summary": "All fields will be returned (default behaviour)", + "value": "_all" + }, + "customSet": { + "summary": "Only fields date and insulin will be returned", + "value": "date,insulin" + } + } + } + ], + "responses": { + "200": { + "description": "The document has been succesfully found and its JSON form returned in the response content.", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Document" + } + }, + "text/csv": { + "schema": { + "$ref": "#/components/schemas/Document" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Document" + } + } + } + }, + "304": { + "description": "The document has not been modified on the server since timestamp specified in If-Modified-Since header", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + } + } + }, + "401": { + "description": "The request was not successfully authenticated using access token or JWT, or the request has missing `Date` header or it contains an expired timestamp, so that the request cannot continue due to the security policy." + }, + "403": { + "description": "Insecure HTTP scheme used or the request has been successfully authenticated, but the security subject is not authorized for the operation." + }, + "404": { + "description": "The collection or document specified was not found." + }, + "406": { + "description": "The requested content type (in `Accept` header) is not supported." + }, + "410": { + "description": "The requested document has already been deleted." + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + }, + "put": { + "tags": [ + "generic" + ], + "summary": "UPDATE: Updates a document in the collection", + "description": "Normally the document with the matching `identifier` will be replaced in the collection by the whole JSON request body and 204 HTTP status code will be returned with empty response body.\n\nIf the document has been found in the collection but it had already been deleted, 410 HTTP status code with empty response content is to be returned.\n\nWhen no document with `identifier` has been found in the collection, then an insert operation takes place instead of updating. Finally 201 HTTP status code is returned with only `Last-Modified` header (`identifier` is already known from the path parameter).\n\nYou can also specify `If-Unmodified-Since` request header including your timestamp of document's last modification. If the document has been modified by somebody else on the server afterwards (and you do not know about it), the 412 HTTP status code is returned cancelling the update operation. You can use this feature to prevent race condition problems.\n\nThis operation provides autopruning of the collection (if autopruning is enabled).\n\nThis operation requires `update` (and/or `create`) permission for the API and the collection (e.g. `api:treatments:update` and `api:treatments:create`)", + "parameters": [ + { + "name": "collection", + "in": "path", + "description": "Collection to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramCollection" + } + }, + { + "name": "identifier", + "in": "path", + "description": "Identifier of the document to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramIdentifier" + } + }, + { + "name": "Date", + "in": "header", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory header serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `now` query parameter.\nExample:\n\n
Date: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + { + "name": "now", + "in": "query", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory parameter serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `Date` header.\n\nExample:\n\n
now=1525383610088
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "token", + "in": "query", + "description": "An alternative way of authorization - passing accessToken in a query parameter.\n\nExample:\n\n
token=testadmin-bf2591231bd2c042
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + { + "name": "If-Unmodified-Since", + "in": "header", + "description": "Timestamp (defined with respect to server's clock) of the last document modification formatted as:\n\n<day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT\n\nIf this header is present, the operation will compare its value with the srvModified timestamp of the document at first and the operation result then may differ. The srvModified timestamp was defined by server's clock.\n\nExample:\n\n
If-Unmodified-Since: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "JSON of new version of document (`identifier` in JSON is ignored if present)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentToPost" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Successfully created a new document in collection", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + } + } + }, + "204": { + "description": "Successfully finished operation", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + }, + "Location": { + "$ref": "#/components/schemas/headerLocation" + } + } + }, + "400": { + "description": "The request is malformed. There may be some required parameters missing or there are unrecognized parameters present." + }, + "401": { + "description": "The request was not successfully authenticated using access token or JWT, or the request has missing `Date` header or it contains an expired timestamp, so that the request cannot continue due to the security policy." + }, + "403": { + "description": "Insecure HTTP scheme used or the request has been successfully authenticated, but the security subject is not authorized for the operation." + }, + "404": { + "description": "The collection or document specified was not found." + }, + "410": { + "description": "The requested document has already been deleted." + }, + "412": { + "description": "The document has already been modified on the server since specified timestamp (in If-Unmodified-Since header)." + }, + "422": { + "description": "The client request is well formed but a server validation error occured. Eg. when trying to modify or delete a read-only document (having `isReadOnly=true`)." + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + }, + "delete": { + "tags": [ + "generic" + ], + "summary": "DELETE: Deletes a document from the collection", + "description": "If the document has already been deleted, the operation will succeed anyway. Normally, documents are not really deleted from the collection but they are only marked as deleted. For special cases the deletion can be irreversible using `permanent` parameter.\n\nThis operation provides autopruning of the collection (if autopruning is enabled).\n\nThis operation requires `delete` permission for the API and the collection (e.g. `api:treatments:delete`)", + "parameters": [ + { + "name": "collection", + "in": "path", + "description": "Collection to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramCollection" + } + }, + { + "name": "identifier", + "in": "path", + "description": "Identifier of the document to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramIdentifier" + } + }, + { + "name": "Date", + "in": "header", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory header serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `now` query parameter.\nExample:\n\n
Date: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + { + "name": "now", + "in": "query", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory parameter serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `Date` header.\n\nExample:\n\n
now=1525383610088
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "token", + "in": "query", + "description": "An alternative way of authorization - passing accessToken in a query parameter.\n\nExample:\n\n
token=testadmin-bf2591231bd2c042
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + { + "name": "permanent", + "in": "query", + "description": "If true, the deletion will be irreversible and it will not appear in `HISTORY` operation. Normally there is no reason for setting this flag.", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "204": { + "description": "Successful operation - empty response" + }, + "401": { + "description": "The request was not successfully authenticated using access token or JWT, or the request has missing `Date` header or it contains an expired timestamp, so that the request cannot continue due to the security policy." + }, + "403": { + "description": "Insecure HTTP scheme used or the request has been successfully authenticated, but the security subject is not authorized for the operation." + }, + "404": { + "description": "The collection or document specified was not found." + }, + "422": { + "description": "The client request is well formed but a server validation error occured. Eg. when trying to modify or delete a read-only document (having `isReadOnly=true`)." + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + }, + "patch": { + "tags": [ + "generic" + ], + "summary": "PATCH: Partially updates document in the collection", + "description": "Normally the document with the matching `identifier` will be retrieved from the collection and it will be patched by all specified fields from the JSON request body. Finally 204 HTTP status code will be returned with empty response body.\n\nIf the document has been found in the collection but it had already been deleted, 410 HTTP status code with empty response content is to be returned.\n\nWhen no document with `identifier` has been found in the collection, then the operation ends with 404 HTTP status code.\n\nYou can also specify `If-Unmodified-Since` request header including your timestamp of document's last modification. If the document has been modified by somebody else on the server afterwards (and you do not know about it), the 412 HTTP status code is returned cancelling the update operation. You can use this feature to prevent race condition problems.\n\n`PATCH` operation can save some bandwidth for incremental document updates in comparison with `GET` - `UPDATE` operation sequence.\n\nWhile patching the document, the field `modifiedBy` is automatically set to the authorized subject's name.\n\nThis operation provides autopruning of the collection (if autopruning is enabled).\n\nThis operation requires `update` permission for the API and the collection (e.g. `api:treatments:update`)", + "parameters": [ + { + "name": "collection", + "in": "path", + "description": "Collection to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramCollection" + } + }, + { + "name": "identifier", + "in": "path", + "description": "Identifier of the document to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramIdentifier" + } + }, + { + "name": "Date", + "in": "header", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory header serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `now` query parameter.\nExample:\n\n
Date: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + { + "name": "now", + "in": "query", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory parameter serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `Date` header.\n\nExample:\n\n
now=1525383610088
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "token", + "in": "query", + "description": "An alternative way of authorization - passing accessToken in a query parameter.\n\nExample:\n\n
token=testadmin-bf2591231bd2c042
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + { + "name": "If-Unmodified-Since", + "in": "header", + "description": "Timestamp (defined with respect to server's clock) of the last document modification formatted as:\n\n<day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT\n\nIf this header is present, the operation will compare its value with the srvModified timestamp of the document at first and the operation result then may differ. The srvModified timestamp was defined by server's clock.\n\nExample:\n\n
If-Unmodified-Since: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "JSON of new version of document (`identifier` in JSON is ignored if present)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentToPost" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Successfully finished operation", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + }, + "Location": { + "$ref": "#/components/schemas/headerLocation" + } + } + }, + "400": { + "description": "The request is malformed. There may be some required parameters missing or there are unrecognized parameters present." + }, + "401": { + "description": "The request was not successfully authenticated using access token or JWT, or the request has missing `Date` header or it contains an expired timestamp, so that the request cannot continue due to the security policy." + }, + "403": { + "description": "Insecure HTTP scheme used or the request has been successfully authenticated, but the security subject is not authorized for the operation." + }, + "404": { + "description": "The collection or document specified was not found." + }, + "410": { + "description": "The requested document has already been deleted." + }, + "412": { + "description": "The document has already been modified on the server since specified timestamp (in If-Unmodified-Since header)." + }, + "422": { + "description": "The client request is well formed but a server validation error occured. Eg. when trying to modify or delete a read-only document (having `isReadOnly=true`)." + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + } + }, + "/{collection}/history": { + "get": { + "tags": [ + "generic" + ], + "summary": "HISTORY: Retrieves incremental changes since timestamp", + "description": "HISTORY operation is intended for continuous data synchronization with other systems.\nEvery insertion, update and deletion will be included in the resulting JSON array of documents (since timestamp in `Last-Modified` request header value). All changes are listed chronologically in response with 200 HTTP status code. The maximum listed `srvModified` timestamp is also stored in `Last-Modified` and `ETag` response headers that you can use for future, directly following synchronization. You can also limit the array's length using `limit` parameter.\n\nDeleted documents will appear with `isValid` = `false` field.\n\nWhen there is no change detected since the timestamp the operation ends with 204 HTTP status code and empty response content.\n\nHISTORY operation has a fallback mechanism in place for documents, which were not created by API v3. For such documents `srvModified` is virtually assigned from the `date` field (for `entries` collection) or from the `created_at` field (for other collections).\n\nThis operation requires `read` permission for the API and the collection (e.g. `api:treatments:read`)\n\nThe only exception is the `settings` collection which requires `admin` permission (`api:settings:admin`), because the settings of each application should be isolated and kept secret. You need to know the concrete identifier to access the app's settings.", + "operationId": "HISTORY", + "parameters": [ + { + "name": "collection", + "in": "path", + "description": "Collection to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramCollection" + } + }, + { + "name": "Date", + "in": "header", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory header serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `now` query parameter.\nExample:\n\n
Date: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + { + "name": "now", + "in": "query", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory parameter serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `Date` header.\n\nExample:\n\n
now=1525383610088
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "token", + "in": "query", + "description": "An alternative way of authorization - passing accessToken in a query parameter.\n\nExample:\n\n
token=testadmin-bf2591231bd2c042
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + { + "name": "Last-Modified", + "in": "header", + "description": "Starting timestamp (defined with respect to server's clock) since which the changes in documents are to be listed, formatted as:\n\n<day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT\n\nExample:\n\n
Last-Modified: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of documents to get in result array", + "required": false, + "style": "form", + "explode": true, + "schema": { + "minimum": 1, + "type": "integer", + "example": 100 + } + }, + { + "name": "fields", + "in": "query", + "description": "A chosen set of fields to return in response. Either you can enumerate specific fields of interest or use the predefined set. Sample parameter values:\n\n_all: All fields will be returned (default value)\n\ndate,insulin: Only fields `date` and `insulin` will be returned", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string", + "default": "_all" + }, + "examples": { + "all": { + "summary": "All fields will be returned (default behaviour)", + "value": "_all" + }, + "customSet": { + "summary": "Only fields date and insulin will be returned", + "value": "date,insulin" + } + } + } + ], + "responses": { + "200": { + "description": "Changed documents since specified timestamp", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModifiedMaximum" + }, + "ETag": { + "$ref": "#/components/schemas/headerEtagLastModifiedMaximum" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + }, + "text/csv": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + } + } + }, + "204": { + "description": "No changes detected" + }, + "400": { + "description": "The request is malformed. There may be some required parameters missing or there are unrecognized parameters present." + }, + "401": { + "description": "The request was not successfully authenticated using access token or JWT, or the request has missing `Date` header or it contains an expired timestamp, so that the request cannot continue due to the security policy." + }, + "403": { + "description": "Insecure HTTP scheme used or the request has been successfully authenticated, but the security subject is not authorized for the operation." + }, + "404": { + "description": "The collection or document specified was not found." + }, + "406": { + "description": "The requested content type (in `Accept` header) is not supported." + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + } + }, + "/{collection}/history/{lastModified}": { + "get": { + "tags": [ + "generic" + ], + "summary": "HISTORY: Retrieves incremental changes since timestamp", + "description": "This HISTORY operation variant is more precise than the previous one with `Last-Modified` request HTTP header), because it does not loose milliseconds precision.\n\nSince this variant queries for changed documents by timestamp precisely and exclusively, the last modified document does not repeat itself in following calls. That is the reason why is this variant more suitable for continuous synchronization with other systems.\n\nThis variant behaves quite the same as the previous one in all other aspects.", + "operationId": "HISTORY2", + "parameters": [ + { + "name": "collection", + "in": "path", + "description": "Collection to which the operation is targeted", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "$ref": "#/components/schemas/paramCollection" + } + }, + { + "name": "lastModified", + "in": "path", + "description": "Starting timestamp (in UNIX epoch format, defined with respect to server's clock) since which the changes in documents are to be listed. Query for modified documents is made using \"greater than\" operator (not including equal timestamps).", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "Date", + "in": "header", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory header serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `now` query parameter.\nExample:\n\n
Date: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + { + "name": "now", + "in": "query", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory parameter serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `Date` header.\n\nExample:\n\n
now=1525383610088
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "token", + "in": "query", + "description": "An alternative way of authorization - passing accessToken in a query parameter.\n\nExample:\n\n
token=testadmin-bf2591231bd2c042
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of documents to get in result array", + "required": false, + "style": "form", + "explode": true, + "schema": { + "minimum": 1, + "type": "integer", + "example": 100 + } + }, + { + "name": "fields", + "in": "query", + "description": "A chosen set of fields to return in response. Either you can enumerate specific fields of interest or use the predefined set. Sample parameter values:\n\n_all: All fields will be returned (default value)\n\ndate,insulin: Only fields `date` and `insulin` will be returned", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string", + "default": "_all" + }, + "examples": { + "all": { + "summary": "All fields will be returned (default behaviour)", + "value": "_all" + }, + "customSet": { + "summary": "Only fields date and insulin will be returned", + "value": "date,insulin" + } + } + } + ], + "responses": { + "200": { + "description": "Changed documents since specified timestamp", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModifiedMaximum" + }, + "ETag": { + "$ref": "#/components/schemas/headerEtagLastModifiedMaximum" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + }, + "text/csv": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + } + } + }, + "204": { + "description": "No changes detected" + }, + "400": { + "description": "The request is malformed. There may be some required parameters missing or there are unrecognized parameters present." + }, + "401": { + "description": "The request was not successfully authenticated using access token or JWT, or the request has missing `Date` header or it contains an expired timestamp, so that the request cannot continue due to the security policy." + }, + "403": { + "description": "Insecure HTTP scheme used or the request has been successfully authenticated, but the security subject is not authorized for the operation." + }, + "404": { + "description": "The collection or document specified was not found." + }, + "406": { + "description": "The requested content type (in `Accept` header) is not supported." + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + } + }, + "/version": { + "get": { + "tags": [ + "other" + ], + "summary": "VERSION: Returns actual version information", + "description": "No authentication is needed for this commnad (it is public)", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Version" + } + } + } + } + } + } + }, + "/status": { + "get": { + "tags": [ + "other" + ], + "summary": "STATUS: Returns actual version information and all permissions granted for API", + "description": "This operation requires authorization in contrast with VERSION operation.", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Status" + } + } + } + }, + "401": { + "description": "The request was not successfully authenticated using access token or JWT, or the request has missing `Date` header or it contains an expired timestamp, so that the request cannot continue due to the security policy." + }, + "403": { + "description": "Insecure HTTP scheme used or the request has been successfully authenticated, but the security subject is not authorized for the operation." + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + } + }, + "/lastModified": { + "get": { + "tags": [ + "other" + ], + "summary": "LAST MODIFIED: Retrieves timestamp of the last modification of every collection", + "description": "LAST MODIFIED operation inspects collections separately (in parallel) and for each of them it finds the date of any last modification (insertion, update, deletion).\nNot only `srvModified`, but also `date` and `created_at` fields are inspected (as a fallback to previous API).\n\nThis operation requires `read` permission for the API and the collections (e.g. `api:treatments:read`). For each collection the permission is checked separately, you will get timestamps only for those collections that you have access to.", + "operationId": "LAST-MODIFIED", + "parameters": [ + { + "name": "Date", + "in": "header", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory header serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `now` query parameter.\nExample:\n\n
Date: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + { + "name": "now", + "in": "query", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory parameter serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `Date` header.\n\nExample:\n\n
now=1525383610088
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "token", + "in": "query", + "description": "An alternative way of authorization - passing accessToken in a query parameter.\n\nExample:\n\n
token=testadmin-bf2591231bd2c042
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful operation returning the timestamps", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LastModifiedResult" + } + } + } + }, + "401": { + "description": "The request was not successfully authenticated using access token or JWT, or the request has missing `Date` header or it contains an expired timestamp, so that the request cannot continue due to the security policy." + }, + "403": { + "description": "Insecure HTTP scheme used or the request has been successfully authenticated, but the security subject is not authorized for the operation." + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + } + } + }, + "components": { + "schemas": { + "headerLocation": { + "type": "string", + "description": "Location of document - the relative part of URL. This can be used to parse the identifier of just created document.\nExample=/api/v3/treatments/53409478-105f-11e9-ab14-d663bd873d93" + }, + "headerLastModified": { + "type": "string", + "description": "Timestamp of the last document modification on the server, formatted as\n', :: GMT'.\nThis field is relevant only for documents which were somehow modified by API v3 (inserted, updated or deleted) and it was generated using server's clock.\nExample='Wed, 17 Oct 2018 05:13:00 GMT'" + }, + "headerLastModifiedMaximum": { + "type": "string", + "description": "The latest (maximum) `srvModified` field of all returning documents, formatted as\n', :: GMT'.\nExample='Wed, 17 Oct 2018 05:13:00 GMT'" + }, + "headerEtagLastModifiedMaximum": { + "type": "string", + "description": "The latest (maximum) `srvModified` field of all returning documents. This header does not loose milliseconds from the date (unlike the `Last-Modified` header).\nExample='W/\"1525383610088\"'" + }, + "paramCollection": { + "type": "string", + "example": "treatments", + "enum": [ + "devicestatus", + "entries", + "food", + "profile", + "settings", + "treatments" + ] + }, + "paramIdentifier": { + "type": "string", + "example": "53409478-105f-11e9-ab14-d663bd873d93" + }, + "DocumentBase": { + "required": [ + "app", + "date" + ], + "properties": { + "identifier": { + "type": "string", + "description": "Main addressing, required field that identifies document in the collection.\n\nThe client should not create the identifier, the server automatically assigns it when the document is inserted.\n\nThe server calculates the identifier in such a way that duplicate records are automatically merged (deduplicating is made by `date`, `device` and `eventType` fields).\n\nThe best practise for all applications is not to loose identifiers from received documents, but save them carefully for other consumer applications/systems.\n\nAPI v3 has a fallback mechanism in place, for documents without `identifier` field the `identifier` is set to internal `_id`, when reading or addressing these documents.\n\nNote: this field is immutable by the client (it cannot be updated or patched)", + "example": "53409478-105f-11e9-ab14-d663bd873d93" + }, + "date": { + "type": "integer", + "description": "Required timestamp when the record or event occured, you can choose from three input formats\n- Unix epoch in milliseconds (1525383610088)\n- Unix epoch in seconds (1525383610)\n- ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00')\n\nThe date is always stored in a normalized form - UTC with zero offset. If UTC offset was present, it is going to be set in the `utcOffset` field.\n\nNote: this field is immutable by the client (it cannot be updated or patched)", + "format": "int64", + "example": 1525383610088 + }, + "utcOffset": { + "type": "integer", + "description": "Local UTC offset (timezone) of the event in minutes. This field can be set either directly by the client (in the incoming document) or it is automatically parsed from the `date` field.\n\nNote: this field is immutable by the client (it cannot be updated or patched)", + "example": 120 + }, + "app": { + "type": "string", + "description": "Application or system in which the record was entered by human or device for the first time.\n\nNote: this field is immutable by the client (it cannot be updated or patched)", + "example": "xdrip" + }, + "device": { + "type": "string", + "description": "The device from which the data originated (including serial number of the device, if it is relevant and safe).\n\nNote: this field is immutable by the client (it cannot be updated or patched)", + "example": "dexcom G5" + }, + "_id": { + "type": "string", + "description": "Internally assigned database id. This field is for internal server purposes only, clients communicate with API by using identifier field.", + "example": "58e9dfbc166d88cc18683aac" + }, + "srvCreated": { + "type": "integer", + "description": "The server's timestamp of document insertion into the database (Unix epoch in ms). This field appears only for documents which were inserted by API v3.\n\nNote: this field is immutable by the client (it cannot be updated or patched)", + "format": "int64", + "example": 1525383610088 + }, + "subject": { + "type": "string", + "description": "Name of the security subject (within Nightscout scope) which has created the document. This field is automatically set by the server from the passed token or JWT.\n\nNote: this field is immutable by the client (it cannot be updated or patched)", + "example": "uploader" + }, + "srvModified": { + "type": "integer", + "description": "The server's timestamp of the last document modification in the database (Unix epoch in ms). This field appears only for documents which were somehow modified by API v3 (inserted, updated or deleted).\n\nNote: this field is immutable by the client (it cannot be updated or patched)", + "format": "int64", + "example": 1525383610088 + }, + "modifiedBy": { + "type": "string", + "description": "Name of the security subject (within Nightscout scope) which has patched or deleted the document for the last time. This field is automatically set by the server.\n\nNote: this field is immutable by the client (it cannot be updated or patched)", + "example": "admin" + }, + "isValid": { + "type": "boolean", + "description": "A flag set by the server only for deleted documents. This field appears only within history operation and for documents which were deleted by API v3 (and they always have a false value)\n\nNote: this field is immutable by the client (it cannot be updated or patched)", + "example": false + }, + "isReadOnly": { + "type": "boolean", + "description": "A flag set by client that locks the document from any changes. Every document marked with `isReadOnly=true` is forever immutable and cannot even be deleted.\n\nAny attempt to modify the read-only document will end with status 422 UNPROCESSABLE ENTITY.", + "example": true + } + }, + "description": "Shared base for all documents" + }, + "DeviceStatus": { + "description": "State of physical device, which is a technical part of the whole T1D compensation system", + "allOf": [ + { + "$ref": "#/components/schemas/DocumentBase" + }, + { + "type": "object", + "properties": { + "some_property": { + "type": "string", + "description": "..." + } + } + } + ] + }, + "Entry": { + "description": "Blood glucose measurements and CGM calibrations", + "allOf": [ + { + "$ref": "#/components/schemas/DocumentBase" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "sgv, mbg, cal, etc" + }, + "sgv": { + "type": "number", + "description": "The glucose reading. (only available for sgv types)" + }, + "direction": { + "type": "string", + "description": "Direction of glucose trend reported by CGM. (only available for sgv types)", + "example": "\"DoubleDown\", \"SingleDown\", \"FortyFiveDown\", \"Flat\", \"FortyFiveUp\", \"SingleUp\", \"DoubleUp\", \"NOT COMPUTABLE\", \"RATE OUT OF RANGE\" for xdrip" + }, + "noise": { + "type": "number", + "description": "Noise level at time of reading. (only available for sgv types)" + }, + "filtered": { + "type": "number", + "description": "The raw filtered value directly from CGM transmitter. (only available for sgv types)" + }, + "unfiltered": { + "type": "number", + "description": "The raw unfiltered value directly from CGM transmitter. (only available for sgv types)" + }, + "rssi": { + "type": "number", + "description": "The signal strength from CGM transmitter. (only available for sgv types)" + }, + "units": { + "type": "string", + "description": "The units for the glucose value, mg/dl or mmol/l. It is strongly recommended to fill in this field.", + "example": "\"mg\", \"mmol\"" + } + } + } + ] + }, + "Food": { + "description": "Nutritional values of food", + "allOf": [ + { + "$ref": "#/components/schemas/DocumentBase" + }, + { + "type": "object", + "properties": { + "food": { + "type": "string", + "description": "food, quickpick" + }, + "category": { + "type": "string", + "description": "Name for a group of related records" + }, + "subcategory": { + "type": "string", + "description": "Name for a second level of groupping" + }, + "name": { + "type": "string", + "description": "Name of the food described" + }, + "portion": { + "type": "number", + "description": "Number of units (e.g. grams) of the whole portion described" + }, + "unit": { + "type": "string", + "description": "Unit for the portion", + "example": "\"g\", \"ml\", \"oz\"" + }, + "carbs": { + "type": "number", + "description": "Amount of carbs in the portion in grams" + }, + "fat": { + "type": "number", + "description": "Amount of fat in the portion in grams" + }, + "protein": { + "type": "number", + "description": "Amount of proteins in the portion in grams" + }, + "energy": { + "type": "number", + "description": "Amount of energy in the portion in kJ" + }, + "gi": { + "type": "number", + "description": "Glycemic index (1=low, 2=medium, 3=high)" + }, + "hideafteruse": { + "type": "boolean", + "description": "Flag used for quickpick" + }, + "hidden": { + "type": "boolean", + "description": "Flag used for quickpick" + }, + "position": { + "type": "number", + "description": "Ordering field for quickpick" + }, + "portions": { + "type": "number", + "description": "component multiplier if defined inside quickpick compound" + }, + "foods": { + "type": "array", + "description": "Neighbour documents (from food collection) that together make a quickpick compound", + "items": { + "$ref": "#/components/schemas/Food" + } + } + } + } + ] + }, + "Profile": { + "description": "Parameters describing body functioning relative to T1D + compensation parameters", + "allOf": [ + { + "$ref": "#/components/schemas/DocumentBase" + }, + { + "type": "object", + "properties": { + "some_property": { + "type": "string", + "description": "..." + } + } + } + ] + }, + "Settings": { + "description": "A document representing persisted settings of some application or system (it could by Nightscout itself as well). This pack of options serves as a backup or as a shared centralized storage for multiple client instances. It is a probably good idea to `PATCH` the document instead of `UPDATE` operation, e.g. when changing one settings option in a client application.\n\n`identifier` represents a client application name here, e.g. `xdrip` or `aaps`.\n\n`Settings` collection has a more specific authorization required. For the `SEARCH` operation within this collection, you need an `admin` permission, such as `api:settings:admin`. The goal is to isolate individual client application settings.", + "allOf": [ + { + "$ref": "#/components/schemas/DocumentBase" + }, + { + "type": "object", + "properties": { + "some_property": { + "type": "string", + "description": "..." + } + } + } + ] + }, + "Treatment": { + "description": "T1D compensation action", + "allOf": [ + { + "$ref": "#/components/schemas/DocumentBase" + }, + { + "type": "object", + "properties": { + "eventType": { + "type": "string", + "description": "The type of treatment event.\n\nNote: this field is immutable by the client (it cannot be updated or patched)", + "example": "\"BG Check\", \"Snack Bolus\", \"Meal Bolus\", \"Correction Bolus\", \"Carb Correction\", \"Combo Bolus\", \"Announcement\", \"Note\", \"Question\", \"Exercise\", \"Site Change\", \"Sensor Start\", \"Sensor Change\", \"Pump Battery Change\", \"Insulin Change\", \"Temp Basal\", \"Profile Switch\", \"D.A.D. Alert\", \"Temporary Target\", \"OpenAPS Offline\", \"Bolus Wizard\"" + }, + "glucose": { + "type": "string", + "description": "Current glucose." + }, + "glucoseType": { + "type": "string", + "description": "Method used to obtain glucose, Finger or Sensor.", + "example": "\"Sensor\", \"Finger\", \"Manual\"" + }, + "units": { + "type": "string", + "description": "The units for the glucose value, mg/dl or mmol/l. It is strongly recommended to fill in this field when `glucose` is entered.", + "example": "\"mg/dl\", \"mmol/l\"" + }, + "carbs": { + "type": "number", + "description": "Amount of carbs given." + }, + "protein": { + "type": "number", + "description": "Amount of protein given." + }, + "fat": { + "type": "number", + "description": "Amount of fat given." + }, + "insulin": { + "type": "number", + "description": "Amount of insulin, if any." + }, + "duration": { + "type": "number", + "description": "Duration in minutes." + }, + "preBolus": { + "type": "number", + "description": "How many minutes the bolus was given before the meal started." + }, + "splitNow": { + "type": "number", + "description": "Immediate part of combo bolus (in percent)." + }, + "splitExt": { + "type": "number", + "description": "Extended part of combo bolus (in percent)." + }, + "percent": { + "type": "number", + "description": "Eventual basal change in percent." + }, + "absolute": { + "type": "number", + "description": "Eventual basal change in absolute value (insulin units per hour)." + }, + "targetTop": { + "type": "number", + "description": "Top limit of temporary target." + }, + "targetBottom": { + "type": "number", + "description": "Bottom limit of temporary target." + }, + "profile": { + "type": "string", + "description": "Name of the profile to which the pump has been switched." + }, + "reason": { + "type": "string", + "description": "For example the reason why the profile has been switched or why the temporary target has been set." + }, + "notes": { + "type": "string", + "description": "Description/notes of treatment." + }, + "enteredBy": { + "type": "string", + "description": "Who entered the treatment." + } + } + } + ] + }, + "DocumentToPost": { + "type": "object", + "description": "Single document", + "example": { + "identifier": "53409478-105f-11e9-ab14-d663bd873d93", + "date": 1532936118000, + "utcOffset": 120, + "carbs": 10, + "insulin": 1, + "eventType": "Snack Bolus", + "app": "xdrip", + "subject": "uploader" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/DeviceStatus" + }, + { + "$ref": "#/components/schemas/Entry" + }, + { + "$ref": "#/components/schemas/Food" + }, + { + "$ref": "#/components/schemas/Profile" + }, + { + "$ref": "#/components/schemas/Settings" + }, + { + "$ref": "#/components/schemas/Treatment" + } + ] + }, + "Document": { + "type": "object", + "description": "Single document", + "example": { + "identifier": "53409478-105f-11e9-ab14-d663bd873d93", + "date": 1532936118000, + "utcOffset": 120, + "carbs": 10, + "insulin": 1, + "eventType": "Snack Bolus", + "srvCreated": 1532936218000, + "srvModified": 1532936218000, + "app": "xdrip", + "subject": "uploader", + "modifiedBy": "admin" + }, + "xml": { + "name": "item" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/DeviceStatus" + }, + { + "$ref": "#/components/schemas/Entry" + }, + { + "$ref": "#/components/schemas/Food" + }, + { + "$ref": "#/components/schemas/Profile" + }, + { + "$ref": "#/components/schemas/Settings" + }, + { + "$ref": "#/components/schemas/Treatment" + } + ] + }, + "DeviceStatusArray": { + "type": "array", + "description": "Array of documents", + "items": { + "$ref": "#/components/schemas/DeviceStatus" + } + }, + "EntryArray": { + "type": "array", + "description": "Array of documents", + "items": { + "$ref": "#/components/schemas/Entry" + } + }, + "FoodArray": { + "type": "array", + "description": "Array of documents", + "items": { + "$ref": "#/components/schemas/Food" + } + }, + "ProfileArray": { + "type": "array", + "description": "Array of documents", + "items": { + "$ref": "#/components/schemas/Profile" + } + }, + "SettingsArray": { + "type": "array", + "description": "Array of settings", + "items": { + "$ref": "#/components/schemas/Settings" + } + }, + "TreatmentArray": { + "type": "array", + "description": "Array of documents", + "items": { + "$ref": "#/components/schemas/Treatment" + } + }, + "DocumentArray": { + "type": "object", + "xml": { + "name": "items" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/DeviceStatusArray" + }, + { + "$ref": "#/components/schemas/EntryArray" + }, + { + "$ref": "#/components/schemas/FoodArray" + }, + { + "$ref": "#/components/schemas/ProfileArray" + }, + { + "$ref": "#/components/schemas/SettingsArray" + }, + { + "$ref": "#/components/schemas/TreatmentArray" + } + ] + }, + "Version": { + "type": "object", + "properties": { + "version": { + "type": "string", + "description": "The whole Nightscout instance version", + "example": "0.10.2-release-20171201" + }, + "apiVersion": { + "type": "string", + "description": "API v3 subsystem version", + "example": "3.0.0" + }, + "srvDate": { + "type": "number", + "description": "Actual server date and time in UNIX epoch format", + "example": 1532936118000 + }, + "storage": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Type of storage engine used", + "example": "mongodb" + }, + "version": { + "type": "string", + "description": "Version of the storage engine", + "example": "4.0.6" + } + } + } + }, + "description": "Information about versions" + }, + "Status": { + "description": "Information about versions and API permissions", + "allOf": [ + { + "$ref": "#/components/schemas/Version" + }, + { + "type": "object", + "properties": { + "apiPermissions": { + "type": "object", + "properties": { + "devicestatus": { + "type": "string", + "example": "crud" + }, + "entries": { + "type": "string", + "example": "r" + }, + "food": { + "type": "string", + "example": "crud" + }, + "profile": { + "type": "string", + "example": "r" + }, + "treatments": { + "type": "string", + "example": "crud" + } + } + } + } + } + ] + }, + "LastModifiedResult": { + "properties": { + "srvDate": { + "type": "integer", + "description": "Actual storage server date (Unix epoch in ms).", + "format": "int64", + "example": 1556260878776 + }, + "collections": { + "type": "object", + "properties": { + "devicestatus": { + "type": "integer", + "description": "Timestamp of the last modification (Unix epoch in ms), `null` when there is no timestamp found.", + "format": "int64", + "example": 1556260760974 + }, + "treatments": { + "type": "integer", + "description": "Timestamp of the last modification (Unix epoch in ms), `null` when there is no timestamp found.", + "format": "int64", + "example": 1553374184169 + }, + "entries": { + "type": "integer", + "description": "Timestamp of the last modification (Unix epoch in ms), `null` when there is no timestamp found.", + "format": "int64", + "example": 1556260758768 + }, + "profile": { + "type": "integer", + "description": "Timestamp of the last modification (Unix epoch in ms), `null` when there is no timestamp found.", + "format": "int64", + "example": 1548524042744 + } + }, + "description": "Collections which the user have read access to." + } + }, + "description": "Result of LAST MODIFIED operation" + } + }, + "responses": { + "201Created": { + "description": "Successfully created a new document in collection", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + } + } + }, + "201CreatedLocation": { + "description": "Successfully created a new document in collection", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + }, + "Location": { + "$ref": "#/components/schemas/headerLocation" + } + } + }, + "204NoContent": { + "description": "Successfully finished operation", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + } + } + }, + "204NoContentLocation": { + "description": "Successfully finished operation", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + }, + "Location": { + "$ref": "#/components/schemas/headerLocation" + } + } + }, + "304NotModified": { + "description": "The document has not been modified on the server since timestamp specified in If-Modified-Since header", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + } + } + }, + "400BadRequest": { + "description": "The request is malformed. There may be some required parameters missing or there are unrecognized parameters present." + }, + "401Unauthorized": { + "description": "The request was not successfully authenticated using access token or JWT, or the request has missing `Date` header or it contains an expired timestamp, so that the request cannot continue due to the security policy." + }, + "403Forbidden": { + "description": "Insecure HTTP scheme used or the request has been successfully authenticated, but the security subject is not authorized for the operation." + }, + "404NotFound": { + "description": "The collection or document specified was not found." + }, + "406NotAcceptable": { + "description": "The requested content type (in `Accept` header) is not supported." + }, + "412PreconditionFailed": { + "description": "The document has already been modified on the server since specified timestamp (in If-Unmodified-Since header)." + }, + "410Gone": { + "description": "The requested document has already been deleted." + }, + "422UnprocessableEntity": { + "description": "The client request is well formed but a server validation error occured. Eg. when trying to modify or delete a read-only document (having `isReadOnly=true`)." + }, + "search200": { + "description": "Successful operation returning array of documents matching the filtering criteria", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + }, + "text/csv": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + } + } + }, + "search204": { + "description": "Successful operation - no documents matching the filtering criteria" + }, + "read200": { + "description": "The document has been succesfully found and its JSON form returned in the response content.", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModified" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Document" + } + }, + "text/csv": { + "schema": { + "$ref": "#/components/schemas/Document" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Document" + } + } + } + }, + "history200": { + "description": "Changed documents since specified timestamp", + "headers": { + "Last-Modified": { + "$ref": "#/components/schemas/headerLastModifiedMaximum" + }, + "ETag": { + "$ref": "#/components/schemas/headerEtagLastModifiedMaximum" + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + }, + "text/csv": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/DocumentArray" + } + } + } + }, + "history204": { + "description": "No changes detected" + }, + "lastModified200": { + "description": "Successful operation returning the timestamps", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LastModifiedResult" + } + } + } + } + }, + "parameters": { + "dateHeader": { + "name": "Date", + "in": "header", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory header serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `now` query parameter.\nExample:\n\n
Date: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + "nowParam": { + "name": "now", + "in": "query", + "description": "Timestamp (defined by client's clock) when the HTTP request was constructed on client. This mandatory parameter serves as an anti-replay precaution. After a period of time (specified by `API3_TIME_SKEW_TOLERANCE`) the message won't be valid any more and it will be denied with HTTP 401 Unauthorized code. This can be set alternatively in `Date` header.\n\nExample:\n\n
now=1525383610088
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + "tokenParam": { + "name": "token", + "in": "query", + "description": "An alternative way of authorization - passing accessToken in a query parameter.\n\nExample:\n\n
token=testadmin-bf2591231bd2c042
", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + "limitParam": { + "name": "limit", + "in": "query", + "description": "Maximum number of documents to get in result array", + "required": false, + "style": "form", + "explode": true, + "schema": { + "minimum": 1, + "type": "integer", + "example": 100 + } + }, + "skipParam": { + "name": "skip", + "in": "query", + "description": "Number of documents to skip from collection query before loading them into result array (used for pagination)", + "required": false, + "style": "form", + "explode": true, + "schema": { + "minimum": 0, + "type": "integer", + "example": 0, + "default": 0 + } + }, + "sortParam": { + "name": "sort", + "in": "query", + "description": "Field name by which the sorting of documents is performed. This parameter cannot be combined with `sort$desc` parameter.", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + "sortDescParam": { + "name": "sort$desc", + "in": "query", + "description": "Field name by which the descending (reverse) sorting of documents is performed. This parameter cannot be combined with `sort` parameter.", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + "permanentParam": { + "name": "permanent", + "in": "query", + "description": "If true, the deletion will be irreversible and it will not appear in `HISTORY` operation. Normally there is no reason for setting this flag.", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "boolean" + } + }, + "fieldsParam": { + "name": "fields", + "in": "query", + "description": "A chosen set of fields to return in response. Either you can enumerate specific fields of interest or use the predefined set. Sample parameter values:\n\n_all: All fields will be returned (default value)\n\ndate,insulin: Only fields `date` and `insulin` will be returned", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string", + "default": "_all" + }, + "examples": { + "all": { + "summary": "All fields will be returned (default behaviour)", + "value": "_all" + }, + "customSet": { + "summary": "Only fields date and insulin will be returned", + "value": "date,insulin" + } + } + }, + "filterParams": { + "name": "filter_parameters", + "in": "query", + "description": "Any number of filtering operators.\n\nEach filtering operator has name like `$`, e.g. `carbs$gt=2` which represents filtering rule \"The field carbs must be present and greater than 2\".\n\nYou can choose from operators:\n\n`eq`=equals, `insulin$eq=1.5`\n\n`ne`=not equals, `insulin$ne=1.5`\n\n`gt`=greater than, `carbs$gt=30`\n\n`gte`=greater than or equal, `carbs$gte=30`\n\n`lt`=less than, `carbs$lt=30`\n\n`lte`=less than or equal, `carbs$lte=30`\n\n`in`=in specified set, `type$in=sgv|mbg|cal`\n\n`nin`=not in specified set, `eventType$nin=Temp%20Basal|Temporary%20Target`\n\n`re`=regex pattern, `eventType$re=Temp.%2A`\n\nWhen filtering by field `date`, `created_at`, `srvModified` or `srvCreated`, you can choose from three input formats\n- Unix epoch in milliseconds (1525383610088)\n- Unix epoch in seconds (1525383610)\n- ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00')\n\nThe date is always queried in a normalized form - UTC with zero offset and with the correct format (1525383610088 for `date`, '2018-05-03T21:40:10.088Z' for `created_at`).", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + "lastModifiedRequiredHeader": { + "name": "Last-Modified", + "in": "header", + "description": "Starting timestamp (defined with respect to server's clock) since which the changes in documents are to be listed, formatted as:\n\n<day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT\n\nExample:\n\n
Last-Modified: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": true, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + "ifModifiedSinceHeader": { + "name": "If-Modified-Since", + "in": "header", + "description": "Timestamp (defined with respect to server's clock) of the last document modification formatted as:\n\n<day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT\n\nIf this header is present, the operation will compare its value with the srvModified timestamp of the document at first and the operation result then may differ. The srvModified timestamp was defined by server's clock.\n\nExample:\n\n
If-Modified-Since: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + }, + "ifUnmodifiedSinceHeader": { + "name": "If-Unmodified-Since", + "in": "header", + "description": "Timestamp (defined with respect to server's clock) of the last document modification formatted as:\n\n<day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT\n\nIf this header is present, the operation will compare its value with the srvModified timestamp of the document at first and the operation result then may differ. The srvModified timestamp was defined by server's clock.\n\nExample:\n\n
If-Unmodified-Since: Wed, 17 Oct 2018 05:13:00 GMT
", + "required": false, + "style": "simple", + "explode": false, + "schema": { + "type": "string" + } + } + }, + "securitySchemes": { + "accessToken": { + "type": "apiKey", + "description": "Add token as query item in the URL or as HTTP header. You can manage access token in `/admin`.\nEach operation requires a specific permission that has to be granted (via security role) to the security subject, which was authenticated by `token` parameter/header or `JWT`. E.g. for creating new `devicestatus` document via API you need `api:devicestatus:create` permission.", + "name": "token", + "in": "query" + }, + "jwtoken": { + "type": "http", + "description": "Use this if you know the temporary json webtoken.", + "scheme": "bearer", + "bearerFormat": "JWT" + } + } + } +} diff --git a/lib/api3/swagger.yaml b/lib/api3/swagger.yaml index 17db893e0ef..5cbb2a05544 100644 --- a/lib/api3/swagger.yaml +++ b/lib/api3/swagger.yaml @@ -2,7 +2,7 @@ openapi: 3.0.0 servers: - url: '/api/v3' info: - version: '3.0.1' + version: "3.0.1" title: Nightscout API contact: name: NS development discussion channel @@ -135,6 +135,8 @@ paths: $ref: '#/components/responses/403Forbidden' 404: $ref: '#/components/responses/404NotFound' + 406: + $ref: '#/components/responses/406NotAcceptable' ###################################################################################### @@ -240,6 +242,8 @@ paths: $ref: '#/components/responses/403Forbidden' 404: $ref: '#/components/responses/404NotFound' + 406: + $ref: '#/components/responses/406NotAcceptable' 410: $ref: '#/components/responses/410Gone' @@ -459,6 +463,8 @@ paths: $ref: '#/components/responses/403Forbidden' 404: $ref: '#/components/responses/404NotFound' + 406: + $ref: '#/components/responses/406NotAcceptable' ###################################################################################### @@ -518,6 +524,8 @@ paths: $ref: '#/components/responses/403Forbidden' 404: $ref: '#/components/responses/404NotFound' + 406: + $ref: '#/components/responses/406NotAcceptable' ###################################################################################### @@ -888,6 +896,9 @@ components: 404NotFound: description: The collection or document specified was not found. + 406NotAcceptable: + description: The requested content type (in `Accept` header) is not supported. + 412PreconditionFailed: description: The document has already been modified on the server since specified timestamp (in If-Unmodified-Since header). @@ -903,6 +914,12 @@ components: application/json: schema: $ref: '#/components/schemas/DocumentArray' + text/csv: + schema: + $ref: '#/components/schemas/DocumentArray' + application/xml: + schema: + $ref: '#/components/schemas/DocumentArray' search204: description: Successful operation - no documents matching the filtering criteria @@ -913,6 +930,12 @@ components: application/json: schema: $ref: '#/components/schemas/Document' + text/csv: + schema: + $ref: '#/components/schemas/Document' + application/xml: + schema: + $ref: '#/components/schemas/Document' headers: 'Last-Modified': $ref: '#/components/schemas/headerLastModified' @@ -924,6 +947,12 @@ components: application/json: schema: $ref: '#/components/schemas/DocumentArray' + text/csv: + schema: + $ref: '#/components/schemas/DocumentArray' + application/xml: + schema: + $ref: '#/components/schemas/DocumentArray' headers: 'Last-Modified': $ref: '#/components/schemas/headerLastModifiedMaximum' @@ -1417,6 +1446,8 @@ components: Document: description: Single document + xml: + name: 'item' type: object oneOf: - $ref: '#/components/schemas/DeviceStatus' @@ -1483,6 +1514,8 @@ components: DocumentArray: type: object + xml: + name: 'items' oneOf: - $ref: '#/components/schemas/DeviceStatusArray' - $ref: '#/components/schemas/EntryArray' diff --git a/lib/authorization/index.js b/lib/authorization/index.js index feaed739b42..b81578e0dca 100644 --- a/lib/authorization/index.js +++ b/lib/authorization/index.js @@ -186,7 +186,7 @@ function init (env, ctx) { authorization.isPermitted = function isPermitted (permission, opts) { - opts = mkopts(opts); + mkopts(opts); authorization.seenPermissions = _.chain(authorization.seenPermissions) .push(permission) .sort() diff --git a/lib/authorization/storage.js b/lib/authorization/storage.js index 3a4c4490876..d602470add6 100644 --- a/lib/authorization/storage.js +++ b/lib/authorization/storage.js @@ -24,7 +24,7 @@ function init (env, ctx) { function create (collection) { function doCreate(obj, fn) { - if (!obj.hasOwnProperty('created_at')) { + if (!Object.prototype.hasOwnProperty.call(obj, 'created_at')) { obj.created_at = (new Date()).toISOString(); } collection.insert(obj, function (err, doc) { @@ -210,16 +210,28 @@ function init (env, ctx) { if (!accessToken) return null; - var split_token = accessToken.split('-'); - var prefix = split_token ? _.last(split_token) : ''; - if (prefix.length < 16) { - return null; - } + function checkToken(accessToken) { + var split_token = accessToken.split('-'); + var prefix = split_token ? _.last(split_token) : ''; - return _.find(storage.subjects, function matches (subject) { - return subject.accessTokenDigest.indexOf(accessToken) === 0 || subject.digest.indexOf(prefix) === 0; - }); + if (prefix.length < 16) { + return null; + } + + return _.find(storage.subjects, function matches (subject) { + return subject.accessTokenDigest.indexOf(accessToken) === 0 || subject.digest.indexOf(prefix) === 0; + }); + } + + if (!Array.isArray(accessToken)) accessToken = [accessToken]; + + for (let i=0; i < accessToken.length; i++) { + const subject = checkToken(accessToken[i]); + if (subject) return subject; + } + + return null; }; storage.doesAccessTokenExist = function doesAccessTokenExist(accessToken) { diff --git a/lib/bus.js b/lib/bus.js index 5828130fa92..65faeea21a6 100644 --- a/lib/bus.js +++ b/lib/bus.js @@ -1,11 +1,11 @@ 'use strict'; - var Stream = require('stream'); function init (settings) { var beats = 0; var started = new Date( ); var interval = settings.heartbeat * 1000; + let busInterval; var stream = new Stream; @@ -24,9 +24,15 @@ function init (settings) { stream.emit('tick', ictus( )); } + stream.teardown = function ( ) { + console.log('Initiating server teardown'); + clearInterval(busInterval); + stream.emit('teardown'); + }; + stream.readable = true; stream.uptime = repeat; - setInterval(repeat, interval); + busInterval = setInterval(repeat, interval); return stream; } module.exports = init; diff --git a/lib/client/browser-settings.js b/lib/client/browser-settings.js index 2119b39da40..0a8e1469a11 100644 --- a/lib/client/browser-settings.js +++ b/lib/client/browser-settings.js @@ -71,6 +71,8 @@ function init (client, serverSettings, $) { $('#basalrender').val(settings.extendedSettings.basal ? settings.extendedSettings.basal.render : 'none'); + $('#bolusrender').val(settings.extendedSettings.bolus ? settings.extendedSettings.bolus.render : 'all'); + if (settings.timeFormat === 24) { $('#24-browser').prop('checked', true); } else { @@ -161,6 +163,7 @@ function init (client, serverSettings, $) { storage.remove(name); }); storage.remove('basalrender'); + storage.remove('bolusrender'); event.preventDefault(); client.browserUtils.reload(); }); @@ -213,6 +216,7 @@ function init (client, serverSettings, $) { , language: $('#language').val() , scaleY: $('#scaleY').val() , basalrender: $('#basalrender').val() + , bolusrender: $('#bolusrender').val() , showPlugins: checkedPluginNames() , storageVersion: STORAGE_VERSION }); @@ -256,6 +260,7 @@ function init (client, serverSettings, $) { settings.thresholds = serverSettings.settings.thresholds; } + if (serverSettings.settings.enable) { settings.enable = serverSettings.settings.enable; } @@ -268,8 +273,15 @@ function init (client, serverSettings, $) { settings.extendedSettings.basal = {}; } - var stored = storage.get('basalrender'); - settings.extendedSettings.basal.render = stored !== null ? stored : settings.extendedSettings.basal.render; + var basalStored = storage.get('basalrender'); + settings.extendedSettings.basal.render = basalStored !== null ? basalStored : settings.extendedSettings.basal.render; + + if (!settings.extendedSettings.bolus) { + settings.extendedSettings.bolus = {}; + } + + var bolusStored = storage.get('bolusrender'); + settings.extendedSettings.bolus.render = bolusStored !== null ? bolusStored : settings.extendedSettings.bolus.render; } catch (err) { console.error(err); diff --git a/lib/client/browser-utils.js b/lib/client/browser-utils.js index 4f920588f80..634afb2ab40 100644 --- a/lib/client/browser-utils.js +++ b/lib/client/browser-utils.js @@ -51,7 +51,7 @@ function init ($) { function queryParms () { var params = {}; - if (location.search) { + if ((typeof location !== 'undefined') && location.search) { location.search.substr(1).split('&').forEach(function(item) { // eslint-disable-next-line no-useless-escape params[item.split('=')[0]] = item.split('=')[1].replace(/[_\+]/g, ' '); diff --git a/lib/client/careportal.js b/lib/client/careportal.js index a5c86232d8e..a6edfe3ec22 100644 --- a/lib/client/careportal.js +++ b/lib/client/careportal.js @@ -52,7 +52,7 @@ function init (client, $) { submitHooks = {}; _.forEach(careportal.allEventTypes, function each (event) { - inputMatrix[event.val] = _.pick(event, ['bg', 'insulin', 'carbs', 'protein', 'fat', 'prebolus', 'duration', 'percent', 'absolute', 'profile', 'split', 'reasons', 'targets']); + inputMatrix[event.val] = _.pick(event, ['otp','remoteCarbs', 'remoteAbsorption', 'remoteBolus', 'bg', 'insulin', 'carbs', 'protein', 'fat', 'prebolus', 'duration', 'percent', 'absolute', 'profile', 'split', 'reasons', 'targets']); submitHooks[event.val] = event.submitHook; }); } @@ -80,11 +80,18 @@ function init (client, $) { $('#reasonLabel').css('display', displayType(reasons && reasons.length > 0)); $('#targets').css('display', displayType(inputMatrix[eventType]['targets'])); + $('#otpLabel').css('display', displayType(inputMatrix[eventType]['otp'])); + $('#remoteCarbsLabel').css('display', displayType(inputMatrix[eventType]['remoteCarbs'])); + $('#remoteAbsorptionLabel').css('display', displayType(inputMatrix[eventType]['remoteAbsorption'])); + $('#remoteBolusLabel').css('display', displayType(inputMatrix[eventType]['remoteBolus'])); + $('#bg').css('display', displayType(inputMatrix[eventType]['bg'])); $('#insulinGivenLabel').css('display', displayType(inputMatrix[eventType]['insulin'])); + $('#carbsGivenLabel').css('display', displayType(inputMatrix[eventType]['carbs'])); $('#proteinGivenLabel').css('display', displayType(inputMatrix[eventType]['protein'])); $('#fatGivenLabel').css('display', displayType(inputMatrix[eventType]['fat'])); + $('#durationLabel').css('display', displayType(inputMatrix[eventType]['duration'])); $('#percentLabel').css('display', displayType(inputMatrix[eventType]['percent'] && $('#absolute').val() === '')); $('#absoluteLabel').css('display', displayType(inputMatrix[eventType]['absolute'] && $('#percent').val() === '')); @@ -99,6 +106,11 @@ function init (client, $) { careportal.reasonable(); + resetIfHidden(inputMatrix[eventType]['otp'], '#otp'); + resetIfHidden(inputMatrix[eventType]['remoteCarbs'], '#remoteCarbs'); + resetIfHidden(inputMatrix[eventType]['remoteAbsorption'], '#remoteAbsorption'); + resetIfHidden(inputMatrix[eventType]['remoteBolus'], '#remoteBolus'); + resetIfHidden(inputMatrix[eventType]['insulin'], '#insulinGiven'); resetIfHidden(inputMatrix[eventType]['carbs'], '#carbsGiven'); resetIfHidden(inputMatrix[eventType]['protein'], '#proteinGiven'); @@ -192,6 +204,12 @@ function init (client, $) { $('#eventType').val(''); $('#glucoseValue').val('').attr('placeholder', translate('Value in') + ' ' + client.settings.units); $('#meter').prop('checked', true); + + $('#otp').val(''); + $('#remoteCarbs').val(''); + $('#remoteAbsorption').val(''); + $('#remoteBolus').val(''); + $('#carbsGiven').val(''); $('#proteinGiven').val(''); $('#fatGiven').val(''); @@ -214,6 +232,10 @@ function init (client, $) { var data = { enteredBy: $('#enteredBy').val() , eventType: eventType + , otp: $('#otp').val() + , remoteCarbs: $('#remoteCarbs').val() + , remoteAbsorption: $('#remoteAbsorption').val() + , remoteBolus: $('#remoteBolus').val() , glucose: $('#glucoseValue').val().replace(',', '.') , reason: selectedReason , targetTop: $('#targetTop').val().replace(',', '.') @@ -226,11 +248,17 @@ function init (client, $) { , duration: times.msecs(parse_duration($('#duration').val())).mins < 1 ? $('#duration').val() : times.msecs(parse_duration($('#duration').val())).mins , percent: $('#percent').val() , profile: $('#profile').val() - , preBolus: parseInt($('#preBolus').val()) + , preBolus: $('#preBolus').val() , notes: $('#notes').val() , units: client.settings.units }; + data.preBolus = parseInt(data.preBolus); + + if (isNaN(data.preBolus)) { + delete data.preBolus; + } + var reasons = inputMatrix[eventType]['reasons']; var reason = _.find(reasons, function matches (r) { return r.name === selectedReason; @@ -255,6 +283,8 @@ function init (client, $) { data.eventTime = mergeDateAndTime().toDate(); } + data.created_at = data.eventTime ? data.eventTime.toISOString() : new Date().toISOString(); + if (!inputMatrix[data.eventType].profile) { delete data.profile; } @@ -266,6 +296,8 @@ function init (client, $) { if (data.eventType.indexOf('Temporary Target Cancel') > -1) { data.duration = 0; data.eventType = 'Temporary Target'; + data.targetBottom = ""; + data.targetTop = ""; } if (data.eventType.indexOf('Combo Bolus') > -1) { @@ -273,7 +305,14 @@ function init (client, $) { data.splitExt = parseInt($('#insulinSplitExt').val()) || 0; } - return data; + let d = {}; + Object.keys(data).forEach(function(key) { + if (data[key] !== "" && data[key] !== null) { + d[key] = data[key] + } + }); + + return d; } careportal.save = function save (event) { @@ -327,6 +366,8 @@ function init (client, $) { } } + // TODO: add check for remote (Bolus, Carbs, Absorption) + return { allOk , messages @@ -350,6 +391,11 @@ function init (client, $) { text[text.length - 1] += ' ' + translate('Cancel'); } + pushIf(data.remoteCarbs, translate('Remote Carbs') + ': ' + data.remoteCarbs); + pushIf(data.remoteAbsorption, translate('Remote Absorption') + ': ' + data.remoteAbsorption); + pushIf(data.remoteBolus, translate('Remote Bolus') + ': ' + data.remoteBolus); + pushIf(data.otp, translate('One Time Pascode') + ': ' + data.otp); + pushIf(data.glucose, translate('Blood Glucose') + ': ' + data.glucose); pushIf(data.glucose, translate('Measurement Method') + ': ' + translate(data.glucoseType)); diff --git a/lib/client/chart.js b/lib/client/chart.js index a5db09f416a..d84dd0998b5 100644 --- a/lib/client/chart.js +++ b/lib/client/chart.js @@ -84,9 +84,13 @@ function init (client, d3, $) { function brushEnded () { // update the opacity of the context data points to brush extent + var selectedRange = chart.createAdjustedRange(); + var from = selectedRange[0].getTime(); + var to = selectedRange[1].getTime(); + chart.context.selectAll('circle') .data(client.entries) - .style('opacity', function(d) { return renderer.highlightBrushPoints(d) }); + .style('opacity', function(d) { return renderer.highlightBrushPoints(d, from, to) }); } var extent = client.dataExtent(); @@ -251,6 +255,7 @@ function init (client, d3, $) { chart.createBrushedRange = function() { var brushedRange = chart.theBrush && d3.brushSelection(chart.theBrush.node()) || null; + var range = brushedRange && brushedRange.map(chart.xScale2.invert); var dataExtent = client.dataExtent(); @@ -267,13 +272,15 @@ function init (client, d3, $) { range[1] = new Date(end); range[0] = new Date(end - client.focusRangeMS); + // console.log('createBrushedRange: ', brushedRange, range); + return range; } chart.createAdjustedRange = function() { var adjustedRange = chart.createBrushedRange(); - adjustedRange[1] = new Date(adjustedRange[1].getTime() + client.forecastTime); + adjustedRange[1] = new Date(Math.max(adjustedRange[1].getTime(), client.forecastTime)); return adjustedRange; } @@ -375,7 +382,8 @@ function init (client, d3, $) { chart.theBrush.selectAll('rect') .attr('y', 0) - .attr('height', contextHeight); + .attr('height', contextHeight) + .attr('width', '100%'); // disable resizing of brush chart.context.select('.x.brush').select('.overlay').style('cursor', 'move'); @@ -507,7 +515,7 @@ function init (client, d3, $) { .attr('y', 0) .attr('height', contextHeight); - // console.log('Redrawing old brush with new dimensions: ', currentBrushExtent); + // console.log('chart.update(): Redrawing old brush with new dimensions: ', currentBrushExtent); // redraw old brush with new dimensions chart.theBrush.call(chart.brush.move, currentBrushExtent.map(chart.xScale2)); @@ -578,7 +586,7 @@ function init (client, d3, $) { chart.xScaleBasals.domain(dataRange); - // console.log('Redrawing brush due to update: ', currentBrushExtent); + // console.log('chart.update(): Redrawing brush due to update: ', currentBrushExtent); chart.theBrush.call(chart.brush.move, currentBrushExtent.map(chart.xScale2)); }; @@ -602,13 +610,13 @@ function init (client, d3, $) { }; function scrollUpdate () { - scrolling = false; - var nowDate = scrollNow; var currentBrushExtent = scrollBrushExtent; var currentRange = scrollRange; + chart.setForecastTime(); + chart.xScale.domain(currentRange); focusYDomain = dynamicDomainOrElse(focusYDomain); @@ -663,6 +671,11 @@ function init (client, d3, $) { renderer.addTreatmentProfiles(client); renderer.drawTreatments(client); + // console.log('scrollUpdate(): Redrawing brush due to update: ', currentBrushExtent); + + chart.theBrush.call(chart.brush.move, currentBrushExtent.map(chart.xScale2)); + + scrolling = false; } chart.scroll = function scroll (nowDate) { @@ -704,21 +717,28 @@ function init (client, d3, $) { if (client.sbx.pluginBase.forecastPoints) { var shownForecastPoints = chart.getForecastData(); - var focusHoursAheadMills = chart.getMaxForecastMills(); + // Get maximum time we will allow projected forward in time + // based on the number of hours the user has selected to show. + var maxForecastMills = chart.getMaxForecastMills(); var selectedRange = chart.createBrushedRange(); var to = selectedRange[1].getTime(); - var maxForecastMills = to + times.mins(30).msecs; + // Default min forecast projection times to the default amount of time to forecast + var minForecastMills = to + client.defaultForecastTime; + var availForecastMills = 0; + + // Determine what the maximum forecast time is that is available in the forecast data if (shownForecastPoints.length > 0) { - maxForecastMills = _.max(_.map(shownForecastPoints, function(point) { return point.mills })); + availForecastMills = _.max(_.map(shownForecastPoints, function(point) { return point.mills })); } - maxForecastMills = Math.min(focusHoursAheadMills, maxForecastMills); - - var lastSGVMills = client.sbx.lastSGVMills(); + // Limit the amount shown to the maximum time allowed to be projected forward based + // on the number of hours the user has selected to show + var forecastMills = Math.min(availForecastMills, maxForecastMills); - client.forecastTime = ((maxForecastMills > 0) && lastSGVMills) ? maxForecastMills - lastSGVMills : client.defaultForecastTime; + // Don't allow the forecast time to go below the minimum forecast time + client.forecastTime = Math.max(forecastMills, minForecastMills); } }; diff --git a/lib/client/clock-client.js b/lib/client/clock-client.js index 324a5168693..73ac9c3baca 100644 --- a/lib/client/clock-client.js +++ b/lib/client/clock-client.js @@ -1,156 +1,128 @@ 'use strict'; -const browserSettings = require('./browser-settings'); - +var browserSettings = require('./browser-settings'); var client = {}; +var latestProperties = {}; client.settings = browserSettings(client, window.serverSettings, $); -// console.log('settings', client.settings); -// client.settings now contains all settings - client.query = function query () { - console.log('query'); var parts = (location.search || '?').substring(1).split('&'); var token = ''; - parts.forEach(function (val) { + parts.forEach(function(val) { if (val.startsWith('token=')) { token = val.substring('token='.length); } }); var secret = localStorage.getItem('apisecrethash'); - var src = '/api/v1/entries.json?count=3&t=' + new Date().getTime(); + var src = '/api/v2/properties'; // Use precalculated data from the backend if (secret) { - src += '&secret=' + secret; + var s = '?secret=' + secret; + src += s; } else if (token) { - src += '&token=' + token; + var s2 = '?token=' + token; + src += s2; } $.ajax(src, { - success: client.render + error: function gotError (err) { + console.error(err); + } + , success: function gotData (data) { + latestProperties = data; + client.render(); + } }); }; -client.render = function render (xhr) { - console.log('got data', xhr); +client.render = function render () { + + if (!latestProperties.bgnow && !latestProperties.bgnow.sgvs) { + console.error('BG data not available'); + return; + } - let rec; - let delta; + let rec = latestProperties.bgnow.sgvs[0]; + let deltaDisplayValue; - xhr.forEach(element => { - if (element.sgv && !rec) { - rec = element; - } - else if (element.sgv && rec && delta==null) { - delta = (rec.sgv - element.sgv)/((rec.date - element.date)/(5*60*1000)); - } - }); + if (latestProperties.delta) { + deltaDisplayValue = latestProperties.delta.display; + } let $errorMessage = $('#errorMessage'); + let $inner = $('#inner'); // If no one measured value found => show "-?-" if (!rec) { if (!$errorMessage.length) { - $('#arrowDiv').append('
-?-
'); - $('#arrow').hide(); + $inner.after('
-?-
') } else { $errorMessage.show(); } + $inner.hide(); return; } else { $errorMessage.length && $errorMessage.hide(); - $('#arrow').show(); - } - - let last = new Date(rec.date); - let now = new Date(); - - // Convert BG to mmol/L if necessary. - if (window.serverSettings.settings.units === 'mmol') { - var displayValue = window.Nightscout.units.mgdlToMMOL(rec.sgv); - var deltaDisplayValue = window.Nightscout.units.mgdlToMMOL(delta); - } else { - displayValue = rec.sgv; - deltaDisplayValue = Math.round(delta); + $inner.show(); } - if (deltaDisplayValue > 0) { - deltaDisplayValue = '+' + deltaDisplayValue; + //Parse face parameters + let face = $inner.data('face').toLowerCase(); + + // Backward compatible + if (face === 'clock-color') { + face = 'c' + (window.serverSettings.settings.showClockLastTime ? 'y' : 'n') + '13-sg35-' + (window.serverSettings.settings.showClockDelta ? 'dt14-' : '') + 'nl-ar25-nl-ag6'; + } else if (face === 'clock') { + face = 'bn0-sg40'; + } else if (face === 'bgclock') { + face = 'b' + (window.serverSettings.settings.showClockLastTime ? 'y' : 'n') + '13-sg35-' + (window.serverSettings.settings.showClockDelta ? 'dt14-' : '') + 'nl-ar25-nl-ag6'; + } else if (face === 'config') { + face = $inner.attr('data-face-config'); + $inner.empty(); } - // Insert the BG value text. - $('#bgnow').html(displayValue); - - // Insert the trend arrow. - $('#arrow').attr('src', '/images/' + (!rec.direction || rec.direction === 'NOT COMPUTABLE' ? 'NONE' : rec.direction) + '.svg'); - - // Time before data considered stale. + let faceParams = face.split('-'); + let bgColor = false; let staleMinutes = 13; - let threshold = 1000 * 60 * staleMinutes; - - // Toggle stale if necessary. - $('#bgnow').toggleClass('stale', (now - last > threshold)); - - // Generate and insert the clock. - let timeDivisor = parseInt(client.settings.timeFormat ? client.settings.timeFormat : 12, 10); - let today = new Date() - , h = today.getHours() % timeDivisor; - if (timeDivisor === 12) { - h = (h === 0) ? 12 : h; // In the case of 00:xx, change to 12:xx for 12h time - } - if (timeDivisor === 24) { - h = (h < 10) ? ("0" + h) : h; // Pad the hours with a 0 in 24h time + let alwaysShowTime = false; + + let clockCreated = ($inner.children().length > 0); + + for (let param in faceParams) { + if (param === '0') { + bgColor = (faceParams[param].substr(0, 1) === 'c'); // do we want colorful background? + alwaysShowTime = (faceParams[param].substr(1, 1) === 'y'); // always show "stale time" text? + staleMinutes = (faceParams[param].substr(2, 2) - 0 >= 0) ? faceParams[param].substr(2, 2) : 13; // threshold value (0=never) + } else if (!clockCreated) { + let div = '
0) ? ' style="' + ((faceParams[param].substr(0, 2) === 'ar') ? 'height' : 'font-size') + ':' + faceParams[param].substr(2, 2) + 'vmin"' : '') + '>
'; + $inner.append(div); + } } - let m = today.getMinutes(); - if (m < 10) m = "0" + m; - $('#clock').text(h + ":" + m); - // defined in the template this is loaded into - // eslint-disable-next-line no-undef - if (clockFace === 'clock-color') { + // Convert BG to mmol/L if necessary. + let displayValue = rec.scaled; - var bgHigh = window.serverSettings.settings.thresholds.bgHigh; - var bgLow = window.serverSettings.settings.thresholds.bgLow; - var bgTargetBottom = window.serverSettings.settings.thresholds.bgTargetBottom; - var bgTargetTop = window.serverSettings.settings.thresholds.bgTargetTop; + // Insert the delta value text. + $('.dt').html(deltaDisplayValue); - var bgNum = parseFloat(rec.sgv); + // Color background + if (bgColor) { // These are the particular shades of red, yellow, green, and blue. - var red = 'rgba(213,9,21,1)'; - var yellow = 'rgba(234,168,0,1)'; - var green = 'rgba(134,207,70,1)'; - var blue = 'rgba(78,143,207,1)'; + let red = 'rgba(213,9,21,1)'; + let yellow = 'rgba(234,168,0,1)'; + let green = 'rgba(134,207,70,1)'; + let blue = 'rgba(78,143,207,1)'; - var elapsedMins = Math.round(((now - last) / 1000) / 60); + // Threshold values + let bgHigh = client.settings.thresholds.bgHigh; + let bgLow = client.settings.thresholds.bgLow; + let bgTargetBottom = client.settings.thresholds.bgTargetBottom; + let bgTargetTop = client.settings.thresholds.bgTargetTop; - // Insert the BG stale time text. - let staleTimeText; - if (elapsedMins == 0) { - staleTimeText = 'Just now'; - } - else if (elapsedMins == 1) { - staleTimeText = '1 minute ago'; - } - else { - staleTimeText = elapsedMins + ' minutes ago'; - } - $('#staleTime').text(staleTimeText); - - // Force NS to always show 'x minutes ago' - if (window.serverSettings.settings.showClockLastTime) { - $('#staleTime').css('display', 'block'); - } - - // Insert the delta value text. - $('#delta').html(deltaDisplayValue); - - // Show delta - if (window.serverSettings.settings.showClockDelta) { - $('#delta').css('display', 'inline-block'); - } + let bgNum = parseFloat(rec.mgdl); // Threshold background coloring. if (bgNum < bgLow) { @@ -169,32 +141,73 @@ client.render = function render (xhr) { $('body').css('background-color', red); } - // Restyle body bg, and make the "x minutes ago" visible too. - if (now - last > threshold) { - $('body').css('background-color', 'grey'); - $('body').css('color', 'black'); - $('#arrow').css('filter', 'brightness(0%)'); + } else { + $('body').css('background-color', 'black'); + } - if (!window.serverSettings.settings.showClockLastTime) { - $('#staleTime').css('display', 'block'); - } + // Time before data considered stale. + let threshold = 1000 * 60 * staleMinutes; - } else { - $('body').css('color', 'white'); - $('#arrow').css('filter', 'brightness(100%)'); + var elapsedms = Date.now() - rec.mills; + let elapsedMins = Math.floor((elapsedms / 1000) / 60); + let thresholdReached = (elapsedms > threshold) && threshold > 0; - if (!window.serverSettings.settings.showClockLastTime) { - $('#staleTime').css('display', 'none'); - } + // Insert the BG value text, toggle stale if necessary. + $('.sg').toggleClass('stale', thresholdReached).html(displayValue); + if (thresholdReached || alwaysShowTime) { + let staleTimeText; + if (elapsedMins === 0) { + staleTimeText = 'Just now'; + } else if (elapsedMins === 1) { + staleTimeText = '1 minute ago'; + } else { + staleTimeText = elapsedMins + ' minutes ago'; } + + $('.ag').html(staleTimeText); + } else { + $('.ag').html(''); } + + // Insert the trend arrow. + let arrow = $('arrow').attr('src', '/images/' + (!rec.direction || rec.direction === 'NOT COMPUTABLE' ? 'NONE' : rec.direction) + '.svg'); + + // Restyle body bg + if (thresholdReached) { + $('body').css('background-color', 'grey').css('color', 'black'); + $('.ar').css('filter', 'brightness(0%)').html(arrow); + } else { + $('body').css('color', bgColor ? 'white' : 'grey'); + $('.ar').css('filter', bgColor ? 'brightness(100%)' : 'brightness(50%)').html(arrow); + } + + updateClock(); + }; +function updateClock () { + let timeDivisor = parseInt(client.settings.timeFormat ? client.settings.timeFormat : 12, 10); + let today = new Date() + , h = today.getHours() % timeDivisor; + if (timeDivisor === 12) { + h = (h === 0) ? 12 : h; // In the case of 00:xx, change to 12:xx for 12h time + } + if (timeDivisor === 24) { + h = (h < 10) ? ("0" + h) : h; // Pad the hours with a 0 in 24h time + } + let m = today.getMinutes(); + if (m < 10) m = "0" + m; + $('.tm').html(h + ":" + m); +} + client.init = function init () { - console.log('init'); + console.log('Initializing clock'); client.query(); - setInterval(client.query, 1 * 60 * 1000); + setInterval(client.query, 20 * 1000); // update every 20 seconds + + // time update + setInterval(updateClock, 1000); }; module.exports = client; diff --git a/lib/client/d3locales.js b/lib/client/d3locales.js index afb04cbad5c..1af15ba3fb6 100644 --- a/lib/client/d3locales.js +++ b/lib/client/d3locales.js @@ -142,6 +142,21 @@ d3locales.it_IT = { shortMonths: ['Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic'] }; +d3locales.pl_PL = { + decimal: '.', + thousands: ',', + grouping: [3], + currency: ['', 'zł'], + dateTime: '%a %b %e %X %Y', + date: '%d.%m.%Y', + time: '%H:%M:%S', + periods: ['AM', 'PM'], // unused + days: ['Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'], + shortDays: ['Nie', 'Pn', 'Wt', 'Śr', 'Czw', 'Pt', 'So'], + months: ['Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpień', 'Wrzesień', 'Październik', 'Listopad', 'Grudzień'], + shortMonths: ['Sty', 'Lu', 'Mar', 'Kw', 'Maj', 'Cze', 'Lip', 'Sie', 'Wrz', 'Pa', 'Lis', 'Gru'] +}; + d3locales.pt_BR = { decimal: ',', thousands: '.', @@ -212,6 +227,7 @@ d3locales.locale = function locale (language) { , fr: 'fr_FR' , he: 'he_IL' , it: 'it_IT' + , pl: 'pl_PL' , pt: 'pt_BR' , ro: 'ro_RO' , ru: 'ru_RU' diff --git a/lib/client/index.js b/lib/client/index.js index 469009a9a94..53515e3b943 100644 --- a/lib/client/index.js +++ b/lib/client/index.js @@ -15,6 +15,8 @@ var levels = require('../levels'); var times = require('../times'); var receiveDData = require('./receiveddata'); +var brushing = false; + var client = {}; $('#loadingMessageText').html('Connecting to server'); @@ -60,18 +62,23 @@ client.init = function init (callback) { , url: src , headers: client.headers() }).done(function success (serverSettings) { + if (serverSettings.runtimeState !== 'loaded') { + console.log('Server is still loading data'); + $('#loadingMessageText').html('Server is starting and still loading data, retrying load in 5 seconds'); + window.setTimeout(window.Nightscout.client.init(), 5000); + return; + } client.settingsFailed = false; console.log('Application appears to be online'); $('#centerMessagePanel').hide(); client.load(serverSettings, callback); - // eslint-disable-next-line no-unused-vars - }).fail(function fail (jqXHR, textStatus, errorThrown) { + }).fail(function fail (jqXHR) { // check if we couldn't reach the server at all, show offline message if (!jqXHR.readyState) { console.log('Application appears to be OFFLINE'); - $('#loadingMessageText').html('Connecting to Nightscout server failed, retrying every 2 seconds'); - window.setTimeout(window.Nightscout.client.init(), 2000); + $('#loadingMessageText').html('Connecting to Nightscout server failed, retrying every 5 seconds'); + window.setTimeout(window.Nightscout.client.init(), 5000); return; } @@ -136,7 +143,8 @@ client.load = function load (serverSettings, callback) { client.now = Date.now(); client.ddata = require('../data/ddata')(); - client.forecastTime = client.defaultForecastTime = times.mins(30).msecs; + client.defaultForecastTime = times.mins(30).msecs; + client.forecastTime = client.now + client.defaultForecastTime; client.entries = []; client.ticks = require('./ticks'); @@ -390,15 +398,23 @@ client.load = function load (serverSettings, callback) { brushExtent[0] = new Date(brushExtent[1].getTime() - client.focusRangeMS); - // console.log('Resetting brush in updateBrushToNow: ', brushExtent); + // console.log('updateBrushToNow(): Resetting brush: ', brushExtent); - chart.theBrush && chart.theBrush.call(chart.brush.move, brushExtent.map(chart.xScale2)); + if (chart.theBrush) { + chart.theBrush.call(chart.brush) + chart.theBrush.call(chart.brush.move, brushExtent.map(chart.xScale2)); + } if (!skipBrushing) { brushed(); } } + function updateBolusRenderOver () { + var bolusRenderOver = (client.settings.bolusRenderOver || 1) + ' U and Over'; + $('#bolusRenderOver').text(bolusRenderOver); + } + function alarmingNow () { return container.hasClass('alarming'); } @@ -409,22 +425,29 @@ client.load = function load (serverSettings, callback) { function brushed () { // Brush not initialized - console.log("brushed"); if (!chart.theBrush) { return; } + if (brushing) { + return; + } + + brushing = true; + // default to most recent focus period var brushExtent = client.dataExtent(); brushExtent[0] = new Date(brushExtent[1].getTime() - client.focusRangeMS); var brushedRange = d3.brushSelection(chart.theBrush.node()); + // console.log("brushed(): coordinates: ", brushedRange); + if (brushedRange) { brushExtent = brushedRange.map(chart.xScale2.invert); } - // console.log('Brushed to: ', brushExtent); + // console.log('brushed(): Brushed to: ', brushExtent); if (!brushedRange || (brushExtent[1].getTime() - brushExtent[0].getTime() !== client.focusRangeMS)) { // ensure that brush updating is with the time range @@ -434,7 +457,7 @@ client.load = function load (serverSettings, callback) { brushExtent[1] = new Date(brushExtent[0].getTime() + client.focusRangeMS); } - // console.log('Updating brushed to: ', brushExtent); + // console.log('brushed(): updating to: ', brushExtent); chart.theBrush.call(chart.brush.move, brushExtent.map(chart.xScale2)); } @@ -596,6 +619,8 @@ client.load = function load (serverSettings, callback) { var top = (client.bottomOfPills() + 5); $('#chartContainer').css({ top: top + 'px', height: $(window).height() - top - 10 }); container.removeClass('loading'); + + brushing = false; } function sgvToColor (sgv) { @@ -774,7 +799,8 @@ client.load = function load (serverSettings, callback) { function updateClock () { updateClockDisplay(); - var interval = (60 - (new Date()).getSeconds()) * 1000 + 5; + // Update at least every 15 seconds + var interval = Math.min(15 * 1000, (60 - (new Date()).getSeconds()) * 1000 + 5); setTimeout(updateClock, interval); updateTimeAgo(); @@ -959,7 +985,7 @@ client.load = function load (serverSettings, callback) { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Client-side code to connect to server and handle incoming data //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // eslint-disable-next-line no-undef + /* global io */ client.socket = socket = io.connect(); socket.on('dataUpdate', dataUpdate); @@ -1239,6 +1265,7 @@ client.load = function load (serverSettings, callback) { prepareEntries(); updateTitle(); + updateBolusRenderOver(); // Don't invoke D3 in headless mode diff --git a/lib/client/receiveddata.js b/lib/client/receiveddata.js index e0adf13fb3b..6f542b89b03 100644 --- a/lib/client/receiveddata.js +++ b/lib/client/receiveddata.js @@ -128,6 +128,9 @@ function receiveDData (received, ddata, settings) { } } + if (received.dbstats && received.dbstats.dataSize) { + ddata.dbstats = received.dbstats; + } } //expose for tests diff --git a/lib/client/renderer.js b/lib/client/renderer.js index f058d3de860..a3841695060 100644 --- a/lib/client/renderer.js +++ b/lib/client/renderer.js @@ -58,11 +58,7 @@ function init (client, d3) { } // get the desired opacity for context chart based on the brush extent - renderer.highlightBrushPoints = function highlightBrushPoints (data) { - var selectedRange = chart().createAdjustedRange(); - var from = selectedRange[0].getTime(); - var to = selectedRange[1].getTime(); - + renderer.highlightBrushPoints = function highlightBrushPoints (data, from, to) { if (client.latestSGV && data.mills >= from && data.mills <= to) { return chart().futureOpacity(data.mills - client.latestSGV.mills); } else { @@ -531,7 +527,7 @@ function init (client, d3) { }; } - function prepareArc (treatment, radius) { + function prepareArc (treatment, radius, renderBasal) { var arc_data = [ // white carb half-circle on top { 'element': '', 'color': 'white', 'start': -1.5708, 'end': 1.5708, 'inner': 0, 'outer': radius.R1 } @@ -542,39 +538,39 @@ function init (client, d3) { // these used to be semicircles from 1.5708 to 4.7124, but that made the tooltip target too big { 'element': '', 'color': 'transparent', 'start': 3.1400, 'end': 3.1432, 'inner': radius.R2, 'outer': radius.R3 } , { 'element': '', 'color': 'transparent', 'start': 3.1400, 'end': 3.1432, 'inner': radius.R2, 'outer': radius.R4 } - ]; + ] + , arc_data_1_elements = []; arc_data[0].outlineOnly = !treatment.carbs; arc_data[2].outlineOnly = !treatment.insulin; if (treatment.carbs > 0) { - arc_data[1].element = Math.round(treatment.carbs) + ' g'; + arc_data_1_elements.push(Math.round(treatment.carbs) + ' g'); } if (treatment.protein > 0) { - arc_data[1].element = arc_data[1].element + " / " + Math.round(treatment.protein) + ' g'; + arc_data_1_elements.push(Math.round(treatment.protein) + ' g'); } if (treatment.fat > 0) { - arc_data[1].element = arc_data[1].element + " / " + Math.round(treatment.fat) + ' g'; + arc_data_1_elements.push(Math.round(treatment.fat) + ' g'); } + arc_data[1].element = arc_data_1_elements.join(' / '); + if (treatment.foodType) { arc_data[1].element = arc_data[1].element + " " + treatment.foodType; } if (treatment.insulin > 0) { var dosage_units = '' + Math.round(treatment.insulin * 100) / 100; - - var unit_of_measurement = ' U'; // One international unit of insulin (1 IU) is shown as '1 U' - var enteredBy = '' + treatment.enteredBy; - - if ((treatment.insulin < 1 && !treatment.carbs && enteredBy.indexOf('openaps') > -1) || treatment.isSMB) { // don't show the unit of measurement for insulin boluses < 1 without carbs (e.g. oref0 SMB's). Otherwise lot's of small insulin only dosages are often unreadable - unit_of_measurement = ''; - // remove leading zeros to avoid overlap with adjacent boluses + + if (renderBasal === 'all-remove-zero-u') { dosage_units = (dosage_units + "").replace(/^0/, ""); } + var unit_of_measurement = (renderBasal === 'all-remove-zero-u' ? '' : ' U'); // One international unit of insulin (1 IU) is shown as '1 U' + arc_data[3].element = dosage_units + unit_of_measurement; } @@ -968,11 +964,15 @@ function init (client, d3) { .attr('id', 'label') .style('fill', 'white'); - // reduce the treatment label font size to make it readable with SMB - var fontBaseSize = (opts.treatments >= 30) ? 40 : 50 - Math.floor((25 - opts.treatments) / 30 * 10); - label.append('text') - .style('font-size', fontBaseSize / opts.scale) + .style('font-size', function(d) { + var fontSize = ( (opts.treatments >= 30) ? 40 : 50 - Math.floor((25 - opts.treatments) / 30 * 10) ) / opts.scale; + var elementValue = parseFloat(d.element); + if (!isNaN(elementValue) && elementValue < 1) { + fontSize = (25 + Math.floor(elementValue * 10)) / opts.scale; + } + return fontSize; + }) .style('text-shadow', '0px 0px 10px rgba(0, 0, 0, 1)') .attr('text-anchor', 'middle') .attr('dy', '.35em') @@ -990,6 +990,7 @@ function init (client, d3) { renderer.drawTreatments = function drawTreatments (client) { var treatmentCount = 0; + var renderBasal = client.settings.extendedSettings.bolus.render; chart().focus.selectAll('.draggable-treatment').remove(); _.forEach(client.ddata.treatments, function eachTreatment (d) { @@ -998,16 +999,18 @@ function init (client, d3) { // add treatment bubbles _.forEach(client.ddata.treatments, function eachTreatment (d) { + var showLabels = ( !d.carbs && ( ( renderBasal == 'none') || ( renderBasal === 'over' && d.insulin < client.settings.bolusRenderOver) ) ) ? false : true; renderer.drawTreatment(d, { scale: renderer.bubbleScale() - , showLabels: true + , showLabels: showLabels , treatments: treatmentCount - }, client.sbx.data.profile.getCarbRatio(new Date())); + }, client.sbx.data.profile.getCarbRatio(new Date()), + renderBasal); }); }; - renderer.drawTreatment = function drawTreatment (treatment, opts, carbratio) { - if (!treatment.carbs && !treatment.insulin) { + renderer.drawTreatment = function drawTreatment (treatment, opts, carbratio, renderBasal) { + if (!treatment.carbs && !treatment.protein && !treatment.fat && !treatment.insulin) { return; } @@ -1024,13 +1027,16 @@ function init (client, d3) { return; } - var arc = prepareArc(treatment, radius); + var arc = prepareArc(treatment, radius, renderBasal); var treatmentDots = appendTreatments(treatment, arc); appendLabels(treatmentDots, arc, opts); }; renderer.addBasals = function addBasals (client) { + if (!client.settings.isEnabled('basal')) { + return; + } var mode = client.settings.extendedSettings.basal.render; var profile = client.sbx.data.profile; var linedata = []; diff --git a/lib/constants.json b/lib/constants.json index c2736f7e6e9..38e36040d42 100644 --- a/lib/constants.json +++ b/lib/constants.json @@ -4,6 +4,16 @@ "HTTP_UNAUTHORIZED" : 401, "HTTP_VALIDATION_ERROR" : 422, "HTTP_INTERNAL_ERROR" : 500, + "HTTP_BAD_REQUEST": 400, "ENTRIES_DEFAULT_COUNT" : 10, - "MMOL_TO_MGDL": 18 + "PROFILES_DEFAULT_COUNT" : 10, + "MMOL_TO_MGDL": 18, + "ONE_DAY" : 86400000, + "TWO_DAYS" : 172800000, + "FIFTEEN_MINUTES": 900000, + "THIRTY_MINUTES": 1800000, + "ONE_HOUR": 3600000, + "THREE_HOURS": 10800000, + "FOUR_HOURS": 14400000, + "SIX_HOURS": 21600000 } diff --git a/lib/data/calcdelta.js b/lib/data/calcdelta.js index e3e0fde7052..c991bd8d602 100644 --- a/lib/data/calcdelta.js +++ b/lib/data/calcdelta.js @@ -75,7 +75,7 @@ module.exports = function calcDelta (oldData, newData) { var result = []; l = newArray.length; for (var j = 0; j < l; j++) { - if (!seen.hasOwnProperty(newArray[j].mills)) { + if (!Object.prototype.hasOwnProperty.call(seen, newArray[j].mills)) { result.push(newArray[j]); } } @@ -94,12 +94,12 @@ module.exports = function calcDelta (oldData, newData) { var changesFound = false; for (var array in compressibleArrays) { - if (compressibleArrays.hasOwnProperty(array)) { + if (Object.prototype.hasOwnProperty.call(compressibleArrays, array)) { var a = compressibleArrays[array]; - if (newData.hasOwnProperty(a)) { + if (Object.prototype.hasOwnProperty.call(newData, a)) { // if previous data doesn't have the property (first time delta?), just assign data over - if (!oldData.hasOwnProperty(a)) { + if (!Object.prototype.hasOwnProperty.call(oldData, a)) { delta[a] = newData[a]; changesFound = true; continue; @@ -125,9 +125,9 @@ module.exports = function calcDelta (oldData, newData) { var changesFound = false; for (var object in skippableObjects) { - if (skippableObjects.hasOwnProperty(object)) { + if (Object.prototype.hasOwnProperty.call(skippableObjects, object)) { var o = skippableObjects[object]; - if (newData.hasOwnProperty(o)) { + if (Object.prototype.hasOwnProperty.call(newData, o)) { if (JSON.stringify(newData[o]) !== JSON.stringify(oldData[o])) { //console.log('delta changes found on', o); changesFound = true; diff --git a/lib/data/dataloader.js b/lib/data/dataloader.js index cc4426aa6ab..985ea259de5 100644 --- a/lib/data/dataloader.js +++ b/lib/data/dataloader.js @@ -1,29 +1,82 @@ 'use strict'; -var _ = require('lodash'); -var async = require('async'); -var times = require('../times'); -var fitTreatmentsToBGCurve = require('./treatmenttocurve'); +const _ = require('lodash'); +const async = require('async'); +const fitTreatmentsToBGCurve = require('./treatmenttocurve'); +const constants = require('../constants'); -var ONE_DAY = 86400000, - TWO_DAYS = 172800000; - -function uniq(a) { +function uniqBasedOnMills(a) { var seen = {}; return a.filter(function(item) { - // eslint-disable-next-line no-prototype-builtins - return seen.hasOwnProperty(item.mills) ? false : (seen[item.mills] = true); + return Object.prototype.hasOwnProperty.call(seen, item.mills) ? false : (seen[item.mills] = true); + }); +} + +const processForRuntime = (obj) => { + Object.keys(obj).forEach(key => { + if (typeof obj[key] === 'object' && obj[key]) { + if (obj[key].hasOwnProperty('_id')) { + obj[key]._id = obj[key]._id.toString(); + } + if (obj[key].hasOwnProperty('created_at') && !obj[key].hasOwnProperty('mills')) { + obj[key].mills = new Date(obj[key].created_at).getTime(); + } + } }); } +const findLatestMills = (data) => { + if (!data) return; + let max = data[0].mills; + for (let i = 0, len = data.length; i < len; i++) { + let o = data[i]; + max = o.mills > max ? o.mills : max; + } + return max; +} + +function mergeProcessSort(oldData, newData, ageLimit) { + + processForRuntime(newData); + + var filtered = _.filter(newData, function hasId(object) { + const hasId = !_.isEmpty(object._id); + const isFresh = (ageLimit && object.mills >= ageLimit) || (!ageLimit); + return isFresh && hasId; + }); + + // Merge old and new data, preferring the new objects + + let merged = []; + if (oldData && filtered) { + merged = filtered; // Start with the new / updated data + for (let i = 0; i < oldData.length; i++) { + const oldElement = oldData[i]; + let found = false; + for (let j = 0; j < filtered.length; j++) { + if (oldElement._id == filtered[j]._id) { + found = true; + break; + } + } + if (!found) merged.push(oldElement); // Merge old object in, if it wasn't found in the new data + } + } else { + merged = filtered; + } + + return _.sortBy(merged, function(item) { + return item.mills; + }); + +} + function init(env, ctx) { var dataloader = {}; dataloader.update = function update(ddata, opts, done) { - //console.log("Database is connected: " + ctx.store.client.isConnected()); - if (opts && done == null && opts.call) { done = opts; opts = { @@ -40,16 +93,38 @@ function init(env, ctx) { }; } ddata.lastUpdated = opts.lastUpdated; - // console.log('LOOKING SINCE', (new Date(ddata.lastUpdated))); + + const normalizeTreatments = (obj) => { + Object.keys(obj).forEach(key => { + if (typeof obj[key] === 'object' && obj[key]) { + const element = obj[key]; + if (element.hasOwnProperty('_id')) { + element._id = element._id.toString(); + } + if (element.hasOwnProperty('amount') && !element.hasOwnProperty('absolute')) { + element.absolute = Number(element.amount); + } + normalizeTreatments(obj[key]); + } + }); + } function loadComplete(err, result) { + + // convert all IDs to strings, as these are not used after load + + normalizeTreatments(ddata); + ddata.treatments = _.uniq(ddata.treatments, false, function(item) { - return item._id.toString(); + return item._id; }); + //sort treatments so the last is the most recent + ddata.treatments = _.sortBy(ddata.treatments, function(item) { return item.mills; }); + fitTreatmentsToBGCurve(ddata, env, ctx); if (err) { console.error(err); @@ -68,8 +143,13 @@ function init(env, ctx) { done(err, result); } - // clear treatments, we're going to merge from more queries + // clear data we'll get from the cache + ddata.treatments = []; + ddata.devicestatus = []; + ddata.entries = []; + + ddata.dbstats = {}; async.parallel([ loadEntries.bind(null, ddata, ctx) @@ -80,6 +160,7 @@ function init(env, ctx) { , loadFood.bind(null, ddata, ctx) , loadDeviceStatus.bind(null, ddata, env, ctx) , loadActivity.bind(null, ddata, ctx) + , loadDatabaseStats.bind(null, ddata, ctx) ], loadComplete); }; @@ -89,10 +170,15 @@ function init(env, ctx) { } function loadEntries(ddata, ctx, callback) { + + const withFrame = ddata.page && ddata.page.frame; + const longLoad = Math.round(constants.TWO_DAYS); + const loadTime = ctx.cache.isEmpty('entries') || withFrame ? longLoad : constants.FIFTEEN_MINUTES; + var dateRange = { - $gte: ddata.lastUpdated - TWO_DAYS + $gte: ddata.lastUpdated - loadTime }; - if (ddata.page && ddata.page.frame) { + if (withFrame) { dateRange['$lte'] = ddata.lastUpdated; } var q = { @@ -111,19 +197,28 @@ function loadEntries(ddata, ctx, callback) { } if (!err && results) { - var mbgs = []; - var sgvs = []; - var cals = []; - results.forEach(function(element) { + + const r = ctx.ddata.processRawDataForRuntime(results); + const currentData = ctx.cache.insertData('entries', r).reverse(); + + const mbgs = []; + const sgvs = []; + const cals = []; + + currentData.forEach(function(element) { if (element) { + if (!element.mills) element.mills = element.date; if (element.mbg) { mbgs.push({ + _id: element._id, mgdl: Number(element.mbg), mills: element.date, - device: element.device + device: element.device, + type: 'mbg' }); } else if (element.sgv) { sgvs.push({ + _id: element._id, mgdl: Number(element.sgv), mills: element.date, device: element.device, @@ -131,54 +226,34 @@ function loadEntries(ddata, ctx, callback) { filtered: element.filtered, unfiltered: element.unfiltered, noise: element.noise, - rssi: element.rssi + rssi: element.rssi, + type: 'sgv' }); } else if (element.type === 'cal') { cals.push({ + _id: element._id, mills: element.date, scale: element.scale, intercept: element.intercept, - slope: element.slope + slope: element.slope, + type: 'cal' }); } } }); - //stop using uniq for SGVs since we use buckets, also enables more detailed monitoring + const ageLimit = ddata.lastUpdated - constants.TWO_DAYS; ddata.sgvs = sgvs; - - ddata.mbgs = uniq(mbgs); - ddata.cals = uniq(cals); + ddata.mbgs = mbgs; + ddata.cals = cals; } callback(); }); } -function mergeToTreatments(ddata, results) { - var filtered = _.filter(results, function hasId(treatment) { - return !_.isEmpty(treatment._id); - }); - - var treatments = _.map(filtered, function update(treatment) { - treatment.mills = new Date(treatment.created_at).getTime(); - return treatment; - }); - - //filter out temps older than a day and an hour ago since we don't display them - var oldestAgo = ddata.lastUpdated - TWO_DAYS - times.hour().msecs; - treatments = _.filter(treatments, function noOldTemps(treatment) { - return !treatment.eventType || treatment.eventType.indexOf('Temp Basal') === -1 || treatment.mills > oldestAgo; - }); - - ddata.treatments = _.unionWith(ddata.treatments, treatments, function(a, b) { - return a._id.toString() == b._id.toString(); - }); -} - - function loadActivity(ddata, ctx, callback) { var dateRange = { - $gte: new Date(ddata.lastUpdated - (ONE_DAY * 2)).toISOString() + $gte: new Date(ddata.lastUpdated - (constants.ONE_DAY * 2)).toISOString() }; if (ddata.page && ddata.page.frame) { dateRange['$lte'] = new Date(ddata.lastUpdated).toISOString(); @@ -193,7 +268,6 @@ function loadActivity(ddata, ctx, callback) { } }; - var activity = []; ctx.activity.list(q, function(err, results) { if (err) { @@ -216,7 +290,7 @@ function loadActivity(ddata, ctx, callback) { } }); - ddata.activity = uniq(activity); + ddata.activity = uniqBasedOnMills(activity); } callback(); }); @@ -224,11 +298,18 @@ function loadActivity(ddata, ctx, callback) { function loadTreatments(ddata, ctx, callback) { - // Load 2.5 days to cover last 48 hours including overlapping temp boluses or temp targets + const withFrame = ddata.page && ddata.page.frame; + const longLoad = Math.round(constants.ONE_DAY * 2.5); //ONE_DAY * 2.5; + + // Load 2.5 days to cover last 48 hours including overlapping temp boluses or temp targets for first load + // Subsequently load at least 15 minutes of data + + const loadTime = ctx.cache.isEmpty('treatments') || withFrame ? longLoad : constants.FIFTEEN_MINUTES; + var dateRange = { - $gte: new Date(ddata.lastUpdated - (ONE_DAY * 2.5)).toISOString() + $gte: new Date(ddata.lastUpdated - loadTime).toISOString() }; - if (ddata.page && ddata.page.frame) { + if (withFrame) { dateRange['$lte'] = new Date(ddata.lastUpdated).toISOString(); } var tq = { @@ -242,7 +323,11 @@ function loadTreatments(ddata, ctx, callback) { ctx.treatments.list(tq, function(err, results) { if (!err && results) { - mergeToTreatments(ddata, results); + + // update cache and apply to runtime data + const r = ctx.ddata.processRawDataForRuntime(results); + const currentData = ctx.cache.insertData('treatments', r); + ddata.treatments = ctx.ddata.idMergePreferNew(ddata.treatments, currentData); } callback(); @@ -251,7 +336,7 @@ function loadTreatments(ddata, ctx, callback) { function loadProfileSwitchTreatments(ddata, ctx, callback) { var dateRange = { - $gte: new Date(ddata.lastUpdated - (ONE_DAY * 31 * 12)).toISOString() + $gte: new Date(ddata.lastUpdated - (constants.ONE_DAY * 31 * 12)).toISOString() }; if (ddata.page && ddata.page.frame) { @@ -273,7 +358,7 @@ function loadProfileSwitchTreatments(ddata, ctx, callback) { ctx.treatments.list(tq, function(err, results) { if (!err && results) { - mergeToTreatments(ddata, results); + ddata.treatments = mergeProcessSort(ddata.treatments, results); } // Store last profile switch @@ -307,7 +392,7 @@ function loadSensorAndInsulinTreatments(ddata, ctx, callback) { function loadLatestSingle(ddata, ctx, dataType, callback) { var dateRange = { - $gte: new Date(ddata.lastUpdated - (ONE_DAY * 32)).toISOString() + $gte: new Date(ddata.lastUpdated - (constants.ONE_DAY * 62)).toISOString() }; if (ddata.page && ddata.page.frame) { @@ -329,9 +414,8 @@ function loadLatestSingle(ddata, ctx, dataType, callback) { ctx.treatments.list(tq, function(err, results) { if (!err && results) { - mergeToTreatments(ddata, results); + ddata.treatments = mergeProcessSort(ddata.treatments, results); } - callback(); }); } @@ -361,12 +445,19 @@ function loadFood(ddata, ctx, callback) { } function loadDeviceStatus(ddata, env, ctx, callback) { + + const withFrame = ddata.page && ddata.page.frame; + const longLoad = env.extendedSettings.devicestatus && env.extendedSettings.devicestatus.days && env.extendedSettings.devicestatus.days == 2 ? constants.TWO_DAYS : constants.ONE_DAY; + const loadTime = ctx.cache.isEmpty('devicestatus') || withFrame ? longLoad : constants.FIFTEEN_MINUTES; + var dateRange = { - $gte: new Date(ddata.lastUpdated - ONE_DAY).toISOString() + $gte: new Date( ddata.lastUpdated - loadTime ).toISOString() }; - if (ddata.page && ddata.page.frame) { + + if (withFrame) { dateRange['$lte'] = new Date(ddata.lastUpdated).toISOString(); } + var opts = { find: { created_at: dateRange @@ -376,16 +467,14 @@ function loadDeviceStatus(ddata, env, ctx, callback) { } }; - if (env.extendedSettings.devicestatus && env.extendedSettings.devicestatus.advanced) { - //not adding count: 1 restriction - } else { - opts.count = 1; - } - ctx.devicestatus.list(opts, function(err, results) { if (!err && results) { - ddata.devicestatus = _.map(results, function eachStatus(result) { - result.mills = new Date(result.created_at).getTime(); + + // update cache and apply to runtime data + const r = ctx.ddata.processRawDataForRuntime(results); + const currentData = ctx.cache.insertData('devicestatus', r); + + const res2 = _.map(currentData, function eachStatus(result) { if ('uploaderBattery' in result) { result.uploader = { battery: result.uploaderBattery @@ -393,7 +482,9 @@ function loadDeviceStatus(ddata, env, ctx, callback) { delete result.uploaderBattery; } return result; - }).reverse(); + }); + + ddata.devicestatus = mergeProcessSort(ddata.devicestatus, res2); } else { ddata.devicestatus = []; } @@ -401,5 +492,20 @@ function loadDeviceStatus(ddata, env, ctx, callback) { }); } +function loadDatabaseStats(ddata, ctx, callback) { + ctx.store.db.stats(function mongoDone (err, result) { + if (err) { + console.log("Problem loading database stats"); + } + if (!err && result) { + ddata.dbstats = { + dataSize: result.dataSize + , indexSize: result.indexSize + }; + } + callback(); + }); +} + module.exports = init; diff --git a/lib/data/ddata.js b/lib/data/ddata.js index 9fa470e3f16..9389f10d360 100644 --- a/lib/data/ddata.js +++ b/lib/data/ddata.js @@ -17,9 +17,65 @@ function init () { , devicestatus: [] , food: [] , activity: [] + , dbstats: {} , lastUpdated: 0 }; + /** + * Convert Mongo ids to strings and ensure all objects have the mills property for + * significantly faster processing than constant date parsing, plus simplified + * logic + */ + ddata.processRawDataForRuntime = (data) => { + + let obj = _.cloneDeep(data); + + Object.keys(obj).forEach(key => { + if (typeof obj[key] === 'object' && obj[key]) { + if (Object.prototype.hasOwnProperty.call(obj[key], '_id')) { + obj[key]._id = obj[key]._id.toString(); + } + if (Object.prototype.hasOwnProperty.call(obj[key], 'created_at') + && !Object.prototype.hasOwnProperty.call(obj[key], 'mills')) { + obj[key].mills = new Date(obj[key].created_at).getTime(); + } + if (Object.prototype.hasOwnProperty.call(obj[key], 'sysTime') + && !Object.prototype.hasOwnProperty.call(obj[key], 'mills')) { + obj[key].mills = new Date(obj[key].sysTime).getTime(); + } + } + }); + + return obj; + }; + + /** + * Merge two arrays based on _id string, preferring new objects when a collision is found + * @param {array} oldData + * @param {array} newData + */ + ddata.idMergePreferNew = (oldData, newData) => { + + if (!newData && oldData) return oldData; + if (!oldData && newData) return newData; + + const merged = _.cloneDeep(newData); + + for (let i = 0; i < oldData.length; i++) { + const oldElement = oldData[i]; + let found = false; + for (let j = 0; j < newData.length; j++) { + if (oldElement._id == newData[j]._id) { + found = true; + break; + } + } + if (!found) merged.push(oldElement); // Merge old object in, if it wasn't found in the new data + } + + return merged; + }; + ddata.clone = function clone () { return _.clone(ddata, function(value) { //special handling of mongo ObjectID's @@ -33,14 +89,14 @@ function init () { }); }; - ddata.dataWithRecentStatuses = function dataWithRecentStatuses() { + ddata.dataWithRecentStatuses = function dataWithRecentStatuses () { var results = {}; results.devicestatus = ddata.recentDeviceStatus(Date.now()); results.sgvs = ddata.sgvs; results.cals = ddata.cals; var profiles = _.cloneDeep(ddata.profiles); - if (profiles && profiles[0]) { + if (profiles && profiles[0] && profiles[0].store) { Object.keys(profiles[0].store).forEach(k => { if (k.indexOf('@@@@@') > 0) { delete profiles[0].store[k]; @@ -51,9 +107,9 @@ function init () { results.mbgs = ddata.mbgs; results.food = ddata.food; results.treatments = ddata.treatments; + results.dbstats = ddata.dbstats; return results; - } ddata.recentDeviceStatus = function recentDeviceStatus (time) { diff --git a/lib/data/treatmenttocurve.js b/lib/data/treatmenttocurve.js index afa17b397ec..714fb9049e6 100644 --- a/lib/data/treatmenttocurve.js +++ b/lib/data/treatmenttocurve.js @@ -41,7 +41,7 @@ module.exports = function fitTreatmentsToBGCurve (ddata, env, ctx) { calcedBG = mgdlAfter; } - return calcedBG || 180; + return Math.round(calcedBG) || 180; } function mgdlValue (entry) { diff --git a/lib/language.js b/lib/language.js index 87fb871e1d1..5246208ff1c 100644 --- a/lib/language.js +++ b/lib/language.js @@ -23,6 +23,7 @@ function init() { , { code: 'fr', language: 'Français', speechCode: 'fr-FR' } , { code: 'he', language: 'עברית', speechCode: 'he-IL' } , { code: 'hr', language: 'Hrvatski', speechCode: 'hr-HR' } + , { code: 'hu', language: 'Magyar', speechCode: 'hu-HU' } , { code: 'it', language: 'Italiano', speechCode: 'it-IT' } , { code: 'ja', language: '日本語', speechCode: 'ja-JP' } , { code: 'ko', language: '한국어', speechCode: 'ko-KR' } @@ -65,6 +66,7 @@ function init() { ,ko: '포트에서 수신' ,tr: 'Port dinleniyor' ,zh_cn: '正在监听端口' + ,hu: 'Port figyelése' } // Client ,'Mo' : { @@ -91,6 +93,7 @@ function init() { ,ko: '월' ,tr: 'Pzt' ,zh_cn: '一' + ,hu: 'Hé' } ,'Tu' : { cs: 'Út' @@ -116,6 +119,7 @@ function init() { ,ko: '화' ,tr: 'Sal' ,zh_cn: '二' + ,hu: 'Ke' } ,'We' : { cs: 'St' @@ -141,6 +145,7 @@ function init() { ,ko: '수' ,tr: 'Çar' ,zh_cn: '三' + ,hu: 'Sze' } ,'Th' : { cs: 'Čt' @@ -166,6 +171,7 @@ function init() { ,ko: '목' ,tr: 'Per' ,zh_cn: '四' + ,hu: 'Csü' } ,'Fr' : { cs: 'Pá' @@ -191,6 +197,7 @@ function init() { ,ko: '금' ,tr: 'Cum' ,zh_cn: '五' + ,hu: 'Pé' } ,'Sa' : { cs: 'So' @@ -216,6 +223,7 @@ function init() { ,ko: '토' ,tr: 'Cmt' ,zh_cn: '六' + ,hu: 'Szo' } ,'Su' : { cs: 'Ne' @@ -241,6 +249,7 @@ function init() { ,ko: '일' ,tr: 'Paz' ,zh_cn: '日' + ,hu: 'Vas' } ,'Monday' : { cs: 'Pondělí' @@ -266,6 +275,7 @@ function init() { ,ko: '월요일' ,tr: 'Pazartesi' ,zh_cn: '星期一' + ,hu: 'Hétfő' } ,'Tuesday' : { cs: 'Úterý' @@ -291,6 +301,7 @@ function init() { ,ko: '화요일' ,tr: 'Salı' ,zh_cn: '星期二' + ,hu: 'Kedd' } ,'Wednesday' : { cs: 'Středa' @@ -316,6 +327,7 @@ function init() { ,ko: '수요일' ,tr: 'Çarşamba' ,zh_cn: '星期三' + ,hu: 'Szerda' } ,'Thursday' : { cs: 'Čtvrtek' @@ -341,6 +353,7 @@ function init() { ,ko: '목요일' ,tr: 'Perşembe' ,zh_cn: '星期四' + ,hu: 'Csütörtök' } ,'Friday' : { cs: 'Pátek' @@ -366,6 +379,7 @@ function init() { ,ko: '금요일' ,tr: 'Cuma' ,zh_cn: '星期五' + ,hu: 'Péntek' } ,'Saturday' : { cs: 'Sobota' @@ -391,6 +405,7 @@ function init() { ,ko: '토요일' ,tr: 'Cumartesi' ,zh_cn: '星期六' + ,hu: 'Szombat' } ,'Sunday' : { cs: 'Neděle' @@ -416,6 +431,7 @@ function init() { ,ko: '일요일' ,tr: 'Pazar' ,zh_cn: '星期日' + ,hu: 'Vasárnap' } ,'Category' : { cs: 'Kategorie' @@ -441,6 +457,7 @@ function init() { ,ko: '분류' ,tr: 'Kategori' ,zh_cn: '类别' + ,hu: 'Kategória' } ,'Subcategory' : { cs: 'Podkategorie' @@ -466,6 +483,7 @@ function init() { ,ko: '세부 분류' ,tr: 'Altkategori' ,zh_cn: '子类别' + ,hu: 'Alkategória' } ,'Name' : { cs: 'Jméno' @@ -491,6 +509,7 @@ function init() { ,ko: '프로파일 명' ,tr: 'İsim' ,zh_cn: '名称' + ,hu: 'Név' } ,'Today' : { cs: 'Dnes' @@ -516,6 +535,7 @@ function init() { ,ko: '오늘' ,tr: 'Bugün' ,zh_cn: '今天' + ,hu: 'Ma' } ,'Last 2 days' : { cs: 'Poslední 2 dny' @@ -535,12 +555,13 @@ function init() { ,nb: 'Siste 2 dager' ,he: 'יומיים אחרונים' ,pl: 'Ostatnie 2 dni' - ,ru: 'Последние 2 дня' + ,ru: 'Прошедшие 2 дня' ,sk: 'Posledné 2 dni' ,nl: 'Afgelopen 2 dagen' ,ko: '지난 2일' ,tr: 'Son 2 gün' ,zh_cn: '过去2天' + ,hu: 'Utolsó 2 nap' } ,'Last 3 days' : { cs: 'Poslední 3 dny' @@ -560,12 +581,13 @@ function init() { ,nb: 'Siste 3 dager' ,he: 'שלושה ימים אחרונים' ,pl: 'Ostatnie 3 dni' - ,ru: 'Последние 3 дня' + ,ru: 'Прошедшие 3 дня' ,sk: 'Posledné 3 dni' ,nl: 'Afgelopen 3 dagen' ,ko: '지난 3일' ,tr: 'Son 3 gün' ,zh_cn: '过去3天' + ,hu: 'Utolsó 3 nap' } ,'Last week' : { cs: 'Poslední týden' @@ -585,12 +607,13 @@ function init() { ,nb: 'Siste uke' ,he: 'שבוע אחרון' ,pl: 'Ostatni tydzień' - ,ru: 'Последняя неделя' + ,ru: 'Прошедшая неделя' ,sk: 'Posledný týždeň' ,nl: 'Afgelopen week' ,ko: '지난주' ,tr: 'Geçen Hafta' ,zh_cn: '上周' + ,hu: 'Előző hét' } ,'Last 2 weeks' : { cs: 'Poslední 2 týdny' @@ -610,12 +633,13 @@ function init() { ,nb: 'Siste 2 uker' ,he: 'שבועיים אחרונים' ,pl: 'Ostatnie 2 tygodnie' - ,ru: 'Последние 2 недели' + ,ru: 'Прошедшие 2 недели' ,sk: 'Posledné 2 týždne' ,nl: 'Afgelopen 2 weken' ,ko: '지난 2주' ,tr: 'Son 2 hafta' ,zh_cn: '过去2周' + ,hu: 'Előző 2 hét' } ,'Last month' : { cs: 'Poslední měsíc' @@ -635,12 +659,13 @@ function init() { ,nb: 'Siste måned' ,he: 'חודש אחרון' ,pl: 'Ostatni miesiąc' - ,ru: 'Последний месяц' + ,ru: 'Прошедший месяц' ,sk: 'Posledný mesiac' ,nl: 'Afgelopen maand' ,ko: '지난달' ,tr: 'Geçen Ay' ,zh_cn: '上个月' + ,hu: 'Előző hónap' } ,'Last 3 months' : { cs: 'Poslední 3 měsíce' @@ -660,12 +685,13 @@ function init() { ,nb: 'Siste 3 måneder' ,he: 'שלושה חודשים אחרונים' ,pl: 'Ostatnie 3 miesiące' - ,ru: 'Последние 3 месяца' + ,ru: 'Прошедшие 3 месяца' ,sk: 'Posledné 3 mesiace' ,nl: 'Afgelopen 3 maanden' ,ko: '지난 3달' ,tr: 'Son 3 ay' ,zh_cn: '过去3个月' + ,hu: 'Előző 3 hónap' } , 'between': { cs: 'between' @@ -685,12 +711,13 @@ function init() { ,nb: 'between' ,he: 'between' ,pl: 'between' - ,ru: 'between' + ,ru: 'между' ,sk: 'between' - ,nl: 'between' + ,nl: 'tussen' ,ko: 'between' ,tr: 'between' ,zh_cn: 'between' + ,hu: 'között' } , 'around': { cs: 'around' @@ -710,12 +737,13 @@ function init() { ,nb: 'around' ,he: 'around' ,pl: 'around' - ,ru: 'around' + ,ru: 'около' ,sk: 'around' - ,nl: 'around' + ,nl: 'rond' ,ko: 'around' ,tr: 'around' ,zh_cn: 'around' + ,hu: 'körülbelül' } , 'and': { cs: 'and' @@ -735,12 +763,13 @@ function init() { ,nb: 'and' ,he: 'and' ,pl: 'and' - ,ru: 'and' + ,ru: 'и' ,sk: 'and' - ,nl: 'and' + ,nl: 'en' ,ko: 'and' ,tr: 'and' ,zh_cn: 'and' + ,hu: 'és' } ,'From' : { cs: 'Od' @@ -766,6 +795,7 @@ function init() { ,ko: '시작일' ,tr: 'Başlangıç' ,zh_cn: '从' + ,hu: 'Tól' } ,'To' : { cs: 'Do' @@ -791,6 +821,7 @@ function init() { ,ko: '종료일' ,tr: 'Bitiş' ,zh_cn: '到' + ,hu: 'Ig' } ,'Notes' : { cs: 'Poznámky' @@ -816,6 +847,7 @@ function init() { ,ko: '메모' ,tr: 'Not' ,zh_cn: '记录' + ,hu: 'Jegyzetek' } ,'Food' : { cs: 'Jídlo' @@ -841,6 +873,7 @@ function init() { ,ko: '음식' ,tr: 'Gıda' ,zh_cn: '食物' + ,hu: 'Étel' } ,'Insulin' : { cs: 'Inzulín' @@ -866,6 +899,7 @@ function init() { ,ko: '인슐린' ,tr: 'İnsülin' ,zh_cn: '胰岛素' + ,hu: 'Inzulin' } ,'Carbs' : { cs: 'Sacharidy' @@ -891,10 +925,11 @@ function init() { ,ko: '탄수화물' ,tr: 'Karbonhidrat' ,zh_cn: '碳水化合物' + ,hu: 'Szénhidrát' } ,'Notes contain' : { cs: 'Poznámky obsahují' - ,de: 'Erläuterungen' + ,de: 'Notizen enthalten' ,he: 'ההערות מכילות' ,es: 'Contenido de las notas' ,fr: 'Notes contiennent' @@ -916,8 +951,9 @@ function init() { ,ko: '메모 포함' ,tr: 'Notlar içerir' ,zh_cn: '记录包括' + ,hu: 'Jegyzet tartalmazza' } - ,'Target bg range bottom' : { + ,'Target BG range bottom' : { cs: 'Cílová glykémie spodní' ,de: 'Vorgabe unteres BG-Ziel' ,es: 'Objetivo inferior de glucemia' @@ -941,6 +977,7 @@ function init() { ,ko: '최저 목표 혈당 범위' ,tr: 'Hedef KŞ aralığı düşük' ,zh_cn: '目标血糖范围 下限' + ,hu: 'Alsó cukorszint határ' } ,'top' : { cs: 'horní' @@ -966,6 +1003,7 @@ function init() { ,ko: '최고치' ,tr: 'Üstü' ,zh_cn: '上限' + ,hu: 'Felső' } ,'Show' : { cs: 'Zobraz' @@ -991,10 +1029,11 @@ function init() { ,ko: '확인' ,tr: 'Göster' ,zh_cn: '生成' + ,hu: 'Mutasd' } ,'Display' : { cs: 'Zobraz' - ,de: 'Darstellen' + ,de: 'Anzeigen' ,es: 'Visualizar' ,fr: 'Afficher' ,el: 'Εμφάνιση' @@ -1016,6 +1055,7 @@ function init() { ,ko: '출력' ,tr: 'Görüntüle' ,zh_cn: '显示' + ,hu: 'Ábrázol' } ,'Loading' : { cs: 'Nahrávám' @@ -1041,6 +1081,7 @@ function init() { ,ko: '로딩' ,tr: 'Yükleniyor' ,zh_cn: '载入中' + ,hu: 'Betöltés' } ,'Loading profile' : { cs: 'Nahrávám profil' @@ -1066,6 +1107,7 @@ function init() { ,ko: '프로파일 로딩' ,tr: 'Profil yükleniyor' ,zh_cn: '载入配置文件' + ,hu: 'Profil betöltése' } ,'Loading status' : { cs: 'Nahrávám status' @@ -1091,6 +1133,7 @@ function init() { ,ko: '상태 로딩' ,tr: 'Durum Yükleniyor' ,zh_cn: '载入状态' + ,hu: 'Állapot betöltése' } ,'Loading food database' : { cs: 'Nahrávám databázi jídel' @@ -1116,6 +1159,7 @@ function init() { ,ko: '음식 데이터 베이스 로딩' ,tr: 'Gıda veritabanı yükleniyor' ,zh_cn: '载入食物数据库' + ,hu: 'Étel adatbázis betöltése' } ,'not displayed' : { cs: 'není zobrazeno' @@ -1135,12 +1179,13 @@ function init() { ,nb: 'Vises ikke' ,he: 'לא מוצג' ,pl: 'Nie jest wyświetlany' - ,ru: 'Не отражено' + ,ru: 'Не показано' ,sk: 'Nie je zobrazené' ,nl: 'Niet weergegeven' ,ko: '출력되지 않음' ,tr: 'görüntülenmedi' ,zh_cn: '未显示' + ,hu: 'nincs megjelenítve' } ,'Loading CGM data of' : { cs: 'Nahrávám CGM data' @@ -1166,6 +1211,7 @@ function init() { ,ko: 'CGM 데이터 로딩' ,tr: 'den CGM veriler yükleniyor' ,zh_cn: '载入CGM(连续血糖监测)数据从' + ,hu: 'CGM adatok betöltése' } ,'Loading treatments data of' : { cs: 'Nahrávám data ošetření' @@ -1191,6 +1237,7 @@ function init() { ,ko: '처리 데이터 로딩' ,tr: 'dan Tedavi verilerini yükle' ,zh_cn: '载入操作数据从' + ,hu: 'Kezelés adatainak betöltése' } ,'Processing data of' : { cs: 'Zpracovávám data' @@ -1216,10 +1263,11 @@ function init() { ,ko: '데이터 처리 중' ,tr: 'dan Veri işleme' ,zh_cn: '处理数据从' + ,hu: 'Adatok feldolgozása' } ,'Portion' : { cs: 'Porce' - ,de: 'Portion' + ,de: 'Abschnitt' ,es: 'Porción' ,fr: 'Portion' ,el: 'Μερίδα' @@ -1241,6 +1289,7 @@ function init() { ,ko: '부분' ,tr: 'Porsiyon' ,zh_cn: '部分' + ,hu: 'Porció' } ,'Size' : { cs: 'Rozměr' @@ -1260,12 +1309,13 @@ function init() { ,nb: 'Størrelse' ,he: 'גודל' ,pl: 'Rozmiar' - ,ru: 'Размер' + ,ru: 'Объем' ,sk: 'Veľkosť' ,nl: 'Grootte' ,ko: '크기' ,tr: 'Boyut' ,zh_cn: '大小' + ,hu: 'Méret' } ,'(none)' : { cs: '(Žádný)' @@ -1292,6 +1342,7 @@ function init() { ,tr: '(hiç)' ,zh_cn: '(无)' ,zh_tw: '(無)' + ,hu: '(semmilyen)' } ,'None' : { cs: 'Žádný' @@ -1318,6 +1369,7 @@ function init() { ,tr: 'Hiç' ,zh_cn: '无' ,zh_tw: '無' + ,hu: 'Semmilyen' } ,'' : { cs: '<Žádný>' @@ -1343,6 +1395,7 @@ function init() { ,ko: '<없음>' ,tr: '' ,zh_cn: '<无>' + ,hu: '' } ,'Result is empty' : { cs: 'Prázdný výsledek' @@ -1368,6 +1421,7 @@ function init() { ,ko: '결과 없음' ,tr: 'Sonuç boş' ,zh_cn: '结果为空' + ,hu: 'Az eredmény üres' } ,'Day to day' : { cs: 'Den po dni' @@ -1393,10 +1447,11 @@ function init() { ,ko: '일별 그래프' ,tr: 'Günden Güne' ,zh_cn: '日到日' + ,hu: 'Napi' } ,'Week to week' : { cs: 'Week to week' - ,de: 'Week to week' + ,de: 'Woche zu Woche' ,es: 'Week to week' ,fr: 'Week to week' ,el: 'Week to week' @@ -1410,12 +1465,13 @@ function init() { ,fi: 'Week to week' ,nb: 'Week to week' ,he: 'Week to week' - ,pl: 'Week to week' + ,pl: 'Tydzień po tygodniu' ,ru: 'По неделям' ,sk: 'Week to week' ,nl: 'Week to week' ,ko: '주별 그래프' ,zh_cn: 'Week to week' + ,hu: 'Heti' } ,'Daily Stats' : { cs: 'Denní statistiky' @@ -1441,6 +1497,7 @@ function init() { ,ko: '일간 통계' ,tr: 'Günlük İstatistikler' ,zh_cn: '每日状态' + ,hu: 'Napi statisztika' } ,'Percentile Chart' : { cs: 'Percentil' @@ -1466,6 +1523,7 @@ function init() { ,ko: '백분위 그래프' ,tr: 'Yüzdelik Grafiği' ,zh_cn: '百分位图形' + ,hu: 'Százalékos' } ,'Distribution' : { cs: 'Rozložení' @@ -1491,6 +1549,7 @@ function init() { ,ko: '분포' ,tr: 'Dağılım' ,zh_cn: '分布' + ,hu: 'Szétosztás' } ,'Hourly stats' : { cs: 'Statistika po hodinách' @@ -1516,6 +1575,7 @@ function init() { ,ko: '시간대별 통계' ,tr: 'Saatlik istatistikler' ,zh_cn: '每小时状态' + ,hu: 'Óránkra való szétosztás' } ,'netIOB stats': { // hourlystats.js nl: 'netIOB stats' @@ -1526,8 +1586,10 @@ function init() { ,fi: 'netIOB tilasto' ,bg: 'netIOB татистика' ,hr: 'netIOB statistika' + , pl: 'Statystyki netIOP' ,ru: 'статистика нетто активн инс netIOB' ,tr: 'netIOB istatistikleri' + ,hu: 'netIOB statisztika' } ,'temp basals must be rendered to display this report': { //hourlystats.js nl: 'tijdelijk basaal moet zichtbaar zijn voor dit rapport' @@ -1537,8 +1599,10 @@ function init() { ,bg: 'временните базали трябва да са показани за да се покаже тази това' ,hr: 'temp bazali moraju biti prikazani kako bi se vidio ovaj izvještaj' ,he: 'חובה לאפשר רמה בזלית זמנית כדי לרות דוח זה' + , pl: 'Tymczasowa dawka podstawowa jest wymagana aby wyświetlić ten raport' ,ru: 'для этого отчета требуется прорисовка врем базалов' ,tr: 'Bu raporu görüntülemek için geçici bazal oluşturulmalıdır' + ,hu: 'Az átmeneti bazálnak meg kell lennie jelenítve az adott jelentls megtekintéséhez' } ,'Weekly success' : { cs: 'Statistika po týdnech' @@ -1564,6 +1628,7 @@ function init() { ,ko: '주간 통계' ,tr: 'Haftalık başarı' ,zh_cn: '每周统计' + ,hu: 'Heti sikeresség' } ,'No data available' : { cs: 'Žádná dostupná data' @@ -1589,6 +1654,7 @@ function init() { ,ko: '활용할 수 있는 데이터 없음' ,tr: 'Veri yok' ,zh_cn: '无可用数据' + ,hu: 'Nincs elérhető adat' } ,'Low' : { cs: 'Nízká' @@ -1614,6 +1680,7 @@ function init() { ,ko: '낮음' ,tr: 'Düşük' ,zh_cn: '低血糖' + ,hu: 'Alacsony' } ,'In Range' : { cs: 'V rozsahu' @@ -1639,10 +1706,11 @@ function init() { ,ko: '범위 안 ' ,tr: 'Hedef alanında' ,zh_cn: '范围内' + ,hu: 'Normális' } ,'Period' : { cs: 'Období' - ,de: 'Periode' + ,de: 'Zeitabschnitt' ,es: 'Periodo' ,fr: 'Période' ,el: 'Περίοδος' @@ -1664,6 +1732,7 @@ function init() { ,ko: '기간 ' ,tr: 'Periyot' ,zh_cn: '期间' + ,hu: 'Időszak' } ,'High' : { cs: 'Vysoká' @@ -1689,6 +1758,7 @@ function init() { ,ko: '높음' ,tr: 'Yüksek' ,zh_cn: '高血糖' + ,hu: 'Magas' } ,'Average' : { cs: 'Průměr' @@ -1714,6 +1784,7 @@ function init() { ,ko: '평균' ,tr: 'Ortalama' ,zh_cn: '平均' + ,hu: 'Átlagos' } ,'Low Quartile' : { cs: 'Nízký kvartil' @@ -1739,6 +1810,7 @@ function init() { ,ko: '낮은 4분위' ,tr: 'Alt Çeyrek' ,zh_cn: '下四分位数' + ,hu: 'Alacsony kvartil' } ,'Upper Quartile' : { cs: 'Vysoký kvartil' @@ -1764,6 +1836,7 @@ function init() { ,ko: '높은 4분위' ,tr: 'Üst Çeyrek' ,zh_cn: '上四分位数' + ,hu: 'Magas kvartil' } ,'Quartile' : { cs: 'Kvartil' @@ -1789,6 +1862,7 @@ function init() { ,ko: '4분위' ,tr: 'Çeyrek' ,zh_cn: '四分位数' + ,hu: 'Kvartil' } ,'Date' : { cs: 'Datum' @@ -1814,6 +1888,7 @@ function init() { ,ko: '날짜' ,tr: 'Tarih' ,zh_cn: '日期' + ,hu: 'Dátum' } ,'Normal' : { cs: 'Normální' @@ -1839,6 +1914,7 @@ function init() { ,ko: '보통' ,tr: 'Normal' ,zh_cn: '正常' + ,hu: 'Normális' } ,'Median' : { cs: 'Medián' @@ -1864,6 +1940,7 @@ function init() { ,ko: '중간값' ,tr: 'Orta Değer' ,zh_cn: '中值' + ,hu: 'Medián' } ,'Readings' : { cs: 'Záznamů' @@ -1889,6 +1966,7 @@ function init() { ,ko: '혈당' ,tr: 'Ölçüm' ,zh_cn: '读数' + ,hu: 'Értékek' } ,'StDev' : { cs: 'Směrodatná odchylka' @@ -1914,6 +1992,7 @@ function init() { ,ko: '표준 편차' ,tr: 'Standart Sapma' ,zh_cn: '标准偏差' + ,hu: 'Standard eltérés' } ,'Daily stats report' : { cs: 'Denní statistiky' @@ -1939,6 +2018,7 @@ function init() { ,ko: '일간 통계 보고서' ,tr: 'Günlük istatistikler raporu' ,zh_cn: '每日状态报表' + ,hu: 'Napi statisztikák' } ,'Glucose Percentile report' : { cs: 'Tabulka percentil glykémií' @@ -1964,6 +2044,7 @@ function init() { ,ko: '혈당 백분위 보고서' ,tr: 'Glikoz Yüzdelik raporu' ,zh_cn: '血糖百分位报表' + ,hu: 'Cukorszint percentil jelentés' } ,'Glucose distribution' : { cs: 'Rozložení glykémií' @@ -1989,6 +2070,7 @@ function init() { ,ko: '혈당 분포' ,tr: 'Glikoz dağılımı' ,zh_cn: '血糖分布' + ,hu: 'Cukorszint szétosztása' } ,'days total' : { cs: 'dní celkem' @@ -2014,10 +2096,11 @@ function init() { ,ko: '일 전체' ,tr: 'toplam gün' ,zh_cn: '天总计' + ,hu: 'nap összesen' } ,'Total per day' : { cs: 'dní celkem' - ,de: 'Gesamttage' + ,de: 'Gesamt pro Tag' ,es: 'Total de días' ,fr: 'Total journalier' ,el: 'ημέρες συνολικά' @@ -2038,6 +2121,7 @@ function init() { ,ko: '하루 총량' ,tr: 'Günlük toplam' ,zh_cn: '天总计' + ,hu: 'Naponta összesen' } ,'Overall' : { cs: 'Celkem' @@ -2057,12 +2141,13 @@ function init() { ,nb: 'Generelt' ,he: 'סך הכל' ,pl: 'Ogółem' - ,ru: 'Всего' + ,ru: 'Суммарно' ,sk: 'Súhrn' ,nl: 'Totaal' ,ko: '전체' ,tr: 'Tüm' ,zh_cn: '概览' + ,hu: 'Összesen' } ,'Range' : { cs: 'Rozsah' @@ -2088,6 +2173,7 @@ function init() { ,ko: '범위' ,tr: 'Alan' ,zh_cn: '范围' + ,hu: 'Tartomány' } ,'% of Readings' : { cs: '% záznamů' @@ -2113,6 +2199,7 @@ function init() { ,ko: '수신된 혈당 비율(%)' ,tr: '% Okumaların' ,zh_cn: '%已读取' + ,hu: '% az értékeknek' } ,'# of Readings' : { cs: 'počet záznamů' @@ -2138,6 +2225,7 @@ function init() { ,ko: '수신된 혈당 개수(#)' ,tr: '# Okumaların' ,zh_cn: '#已读取' + ,hu: 'Olvasott értékek száma' } ,'Mean' : { cs: 'Střední hodnota' @@ -2163,6 +2251,7 @@ function init() { ,ko: '평균' ,tr: 'ortalama' ,zh_cn: '平均' + ,hu: 'Közép' } ,'Standard Deviation' : { cs: 'Standardní odchylka' @@ -2188,6 +2277,7 @@ function init() { ,ko: '표준 편차' ,tr: 'Standart Sapma' ,zh_cn: '标准偏差' + ,hu: 'Átlagos eltérés' } ,'Max' : { cs: 'Max' @@ -2213,6 +2303,7 @@ function init() { ,ko: '최대값' ,tr: 'Max' ,zh_cn: '最大值' + ,hu: 'Max' } ,'Min' : { cs: 'Min' @@ -2238,6 +2329,7 @@ function init() { ,ko: '최소값' ,tr: 'Min' ,zh_cn: '最小值' + ,hu: 'Min' } ,'A1c estimation*' : { cs: 'Předpokládané HBA1c*' @@ -2257,12 +2349,13 @@ function init() { ,nb: 'Beregnet HbA1c' ,he: 'משוער A1c' ,pl: 'HbA1c przewidywany' - ,ru: 'Ожидаемый HbA1c' + ,ru: 'Ожидаемый HbA1c*' ,sk: 'Odhadované HbA1C*' ,nl: 'Geschatte HbA1C' ,ko: '예상 당화혈 색소' ,tr: 'Tahmini A1c *' ,zh_cn: '糖化血红蛋白估算' + ,hu: 'Megközelítőleges HbA1c' } ,'Weekly Success' : { cs: 'Týdenní úspěšnost' @@ -2288,6 +2381,7 @@ function init() { ,ko: '주간 통계' ,tr: 'Haftalık Başarı' ,zh_cn: '每周统计' + ,hu: 'Heti sikeresség' } ,'There is not sufficient data to run this report. Select more days.' : { cs: 'Není dostatek dat. Vyberte delší časové období.' @@ -2313,6 +2407,7 @@ function init() { ,ko: '이 보고서를 실행하기 위한 데이터가 충분하지 않습니다. 더 많은 날들을 선택해 주세요.' ,tr: 'Bu raporu çalıştırmak için yeterli veri yok. Daha fazla gün seçin.' ,zh_cn: '没有足够的数据生成报表,请选择更长时间段。' + ,hu: 'Nincs elég adat a jelentés elkészítéséhez. Válassz több napot.' } // food editor ,'Using stored API secret hash' : { @@ -2340,6 +2435,7 @@ function init() { ,tr: 'Kaydedilmiş API secret hash kullan' ,zh_cn: '使用已存储的API密钥哈希值' ,zh_tw: '使用已存儲的API密鑰哈希值' + ,hu: 'Az elmentett API hash jelszót használom' } ,'No API secret hash stored yet. You need to enter API secret.' : { cs: 'Není uložený žádný hash API hesla. Musíte zadat API heslo.' @@ -2366,6 +2462,7 @@ function init() { ,tr: 'Henüz bir API secret hash saklanmadı. API parolasını girmeniz gerekiyor.' ,zh_cn: '没有已存储的API密钥,请输入API密钥。' ,zh_tw: '沒有已存儲的API密鑰,請輸入API密鑰。' + ,hu: 'Még nem lett a titkos API hash elmentve. Add meg a titkos API jelszót' } ,'Database loaded' : { cs: 'Databáze načtena' @@ -2391,6 +2488,7 @@ function init() { ,ko: '데이터베이스 로드' ,tr: 'Veritabanı yüklendi' ,zh_cn: '数据库已载入' + ,hu: 'Adatbázis betöltve' } ,'Error: Database failed to load' : { cs: 'Chyba při načítání databáze' @@ -2410,12 +2508,13 @@ function init() { ,nb: 'Feil: Database kan ikke leses' ,he: 'שגיאה: לא ניתן לטעון בסיס נתונים' ,pl: 'Błąd, baza danych nie może być załadowana' - ,ru: 'Не удалось загрузить базу данных' + ,ru: 'Ошибка: Не удалось загрузить базу данных' ,sk: 'Chyba pri načítaní databázy' ,nl: 'FOUT: Database niet geladen' ,ko: '에러: 데이터베이스 로드 실패' ,tr: 'Hata: Veritabanı yüklenemedi' ,zh_cn: '错误:数据库载入失败' + ,hu: 'Hiba: Az adatbázist nem sikerült betölteni' } ,'Error' : { cs: 'Error' @@ -2441,6 +2540,7 @@ function init() { ,tr: 'Error' ,zh_cn: 'Error' ,zh_tw: 'Error' + ,hu: 'Hiba' } ,'Create new record' : { cs: 'Vytvořit nový záznam' @@ -2466,6 +2566,7 @@ function init() { ,ko: '새입력' ,tr: 'Yeni kayıt oluştur' ,zh_cn: '新增记录' + ,hu: 'Új bejegyzés' } ,'Save record' : { cs: 'Uložit záznam' @@ -2491,6 +2592,7 @@ function init() { ,ko: '저장' ,tr: 'Kayıtları kaydet' ,zh_cn: '保存记录' + ,hu: 'Bejegyzés mentése' } ,'Portions' : { cs: 'Porcí' @@ -2516,6 +2618,7 @@ function init() { ,ko: '부분' ,tr: 'Porsiyonlar' ,zh_cn: '部分' + ,hu: 'Porció' } ,'Unit' : { cs: 'Jedn' @@ -2541,6 +2644,7 @@ function init() { ,ko: '단위' ,tr: 'Birim' ,zh_cn: '单位' + ,hu: 'Egység' } ,'GI' : { cs: 'GI' @@ -2560,12 +2664,13 @@ function init() { ,fi: 'GI' ,nb: 'GI' ,pl: 'IG' - ,ru: 'ГИ' + ,ru: 'гл индекс ГИ' ,sk: 'GI' ,nl: 'Glycemische index ' ,ko: '혈당 지수' ,tr: 'GI-Glisemik İndeks' ,zh_cn: 'GI(血糖生成指数)' + ,hu: 'GI' } ,'Edit record' : { cs: 'Upravit záznam' @@ -2591,6 +2696,7 @@ function init() { ,ko: '편집기록' ,tr: 'Kaydı düzenle' ,zh_cn: '编辑记录' + ,hu: 'Bejegyzés szerkesztése' } ,'Delete record' : { cs: 'Smazat záznam' @@ -2616,6 +2722,7 @@ function init() { ,ko: '삭제기록' ,tr: 'Kaydı sil' ,zh_cn: '删除记录' + ,hu: 'Bejegyzés törlése' } ,'Move to the top' : { cs: 'Přesuň na začátek' @@ -2641,6 +2748,7 @@ function init() { ,ko: '맨처음으로 이동' ,tr: 'En üste taşı' ,zh_cn: '移至顶端' + ,hu: 'Áthelyezni az elejére' } ,'Hidden' : { cs: 'Skrytý' @@ -2666,6 +2774,7 @@ function init() { ,ko: '숨김' ,tr: 'Gizli' ,zh_cn: '隐藏' + ,hu: 'Elrejtett' } ,'Hide after use' : { cs: 'Skryj po použití' @@ -2691,6 +2800,7 @@ function init() { ,ko: '사용 후 숨김' ,tr: 'Kullandıktan sonra gizle' ,zh_cn: '使用后隐藏' + ,hu: 'Elrejteni használat után' } ,'Your API secret must be at least 12 characters long' : { cs: 'Vaše API heslo musí mít alespoň 12 znaků' @@ -2710,13 +2820,14 @@ function init() { ,fi: 'API-avaimen tulee olla ainakin 12 merkin mittainen' ,nb: 'Din API nøkkel må være minst 12 tegn lang' ,pl: 'Twój poufny klucz API musi zawierać co majmniej 12 znaków' - ,ru: 'Ваш пароль API должен быть не менее 12 знаков' + ,ru: 'Ваш пароль API должен иметь не менее 12 знаков' ,sk: 'Vaše API heslo musí mať najmenej 12 znakov' ,nl: 'Uw API wachtwoord dient tenminste 12 karakters lang te zijn' ,ko: 'API secret는 최소 12자 이상이여야 합니다.' ,tr: 'PI parolanız en az 12 karakter uzunluğunda olmalıdır' ,zh_cn: 'API密钥最少需要12个字符' ,zh_tw: 'API密鑰最少需要12個字符' + ,hu: 'Az API jelszó több mint 12 karakterből kell hogy álljon' } ,'Bad API secret' : { cs: 'Chybné API heslo' @@ -2743,6 +2854,7 @@ function init() { ,tr: 'Hatalı API parolası' ,zh_cn: 'API密钥错误' ,zh_tw: 'API密鑰錯誤' + ,hu: 'Helytelen API jelszó' } ,'API secret hash stored' : { cs: 'Hash API hesla uložen' @@ -2769,6 +2881,7 @@ function init() { ,tr: 'API secret hash parolası saklandı' ,zh_cn: 'API密钥已存储' ,zh_tw: 'API密鑰已存儲' + ,hu: 'API jelszó elmentve' } ,'Status' : { cs: 'Status' @@ -2794,6 +2907,7 @@ function init() { ,ko: '상태' ,tr: 'Durum' ,zh_cn: '状态' + ,hu: 'Állapot' } ,'Not loaded' : { cs: 'Nenačtený' @@ -2819,6 +2933,7 @@ function init() { ,ko: '로드되지 않음' ,tr: 'Yüklü değil' ,zh_cn: '未载入' + ,hu: 'Nincs betöltve' } ,'Food Editor' : { cs: 'Editor jídel' @@ -2838,12 +2953,13 @@ function init() { ,fi: 'Muokkaa ruokia' ,nb: 'Mat editor' ,pl: 'Edytor posiłków' - ,ru: 'Редактор епродуктов' + ,ru: 'Редактор продуктов' ,sk: 'Editor jedál' ,nl: 'Voeding beheer' ,ko: '음식 편집' ,tr: 'Gıda Editörü' ,zh_cn: '食物编辑器' + ,hu: 'Étel szerkesztése' } ,'Your database' : { cs: 'Vaše databáze' @@ -2869,6 +2985,7 @@ function init() { ,ko: '당신의 데이터베이스' ,tr: 'Sizin Veritabanınız' ,zh_cn: '你的数据库' + ,hu: 'Ön adatbázisa' } ,'Filter' : { cs: 'Filtr' @@ -2894,6 +3011,7 @@ function init() { ,ko: '필터' ,tr: 'Filtre' ,zh_cn: '过滤器' + ,hu: 'Filter' } ,'Save' : { cs: 'Ulož' @@ -2920,6 +3038,7 @@ function init() { ,tr: 'Kaydet' ,zh_cn: '保存' ,zh_tw: '保存' + ,hu: 'Mentés' } ,'Clear' : { cs: 'Vymaž' @@ -2945,6 +3064,7 @@ function init() { ,ko: '취소' ,tr: 'Temizle' ,zh_cn: '清除' + ,hu: 'Kitöröl' } ,'Record' : { cs: 'Záznam' @@ -2970,6 +3090,7 @@ function init() { ,ko: '기록' ,tr: 'Kayıt' ,zh_cn: '记录' + ,hu: 'Bejegyzés' } ,'Quick picks' : { cs: 'Rychlý výběr' @@ -2995,6 +3116,7 @@ function init() { ,ko: '빠른 선택' ,tr: 'Hızlı seçim' ,zh_cn: '快速选择' + ,hu: 'Gyors választás' } ,'Show hidden' : { cs: 'Zobraz skryté' @@ -3020,12 +3142,21 @@ function init() { ,ko: '숨김 보기' ,tr: 'Gizli göster' ,zh_cn: '显示隐藏值' + ,hu: 'Eltakart mutatása' } ,'Your API secret or token' : { fi: 'API salaisuus tai avain' + ,pl: 'Twój hash API lub token' + ,ru: 'Ваш пароль API или код доступа ' + ,de: 'Deine API-Prüfsumme oder Token' + ,hu: 'Az API jelszo' } ,'Remember this device. (Do not enable this on public computers.)' : { fi: 'Muista tämä laite (Älä valitse julkisilla tietokoneilla)' + , pl: 'Zapamiętaj to urządzenie (Nie używaj tej opcji korzystając z publicznych komputerów.)' + ,ru: 'Запомнить это устройство (Не применяйте в общем доступе)' + ,de: 'An dieses Gerät erinnern. (Nicht auf öffentlichen Geräten verwenden)' + ,hu: 'A berendezés megjegyzése. (Csak saját berendezésen használd' } ,'Treatments' : { cs: 'Ošetření' @@ -3051,6 +3182,7 @@ function init() { ,ko: '관리' ,tr: 'Tedaviler' ,zh_cn: '操作' + ,hu: 'Kezelések' } ,'Time' : { cs: 'Čas' @@ -3077,6 +3209,7 @@ function init() { ,tr: 'Zaman' ,zh_cn: '时间' ,zh_tw: '時間' + ,hu: 'Idő' } ,'Event Type' : { cs: 'Typ události' @@ -3102,6 +3235,7 @@ function init() { ,ko: '입력 유형' ,tr: 'Etkinlik tipi' ,zh_cn: '事件类型' + ,hu: 'Esemény típusa' } ,'Blood Glucose' : { cs: 'Glykémie' @@ -3127,6 +3261,7 @@ function init() { ,ko: '혈당' ,tr: 'Kan Şekeri' ,zh_cn: '血糖值' + ,hu: 'Vércukor szint' } ,'Entered By' : { cs: 'Zadal' @@ -3146,12 +3281,13 @@ function init() { ,nb: 'Lagt inn av' ,he: 'הוזן על-ידי' ,pl: 'Wprowadzono przez' - ,ru: 'Введено от' + ,ru: 'Внесено через' ,sk: 'Zadal' ,nl: 'Ingevoerd door' ,ko: '입력 내용' ,tr: 'Tarafından girildi' ,zh_cn: '输入人' + ,hu: 'Beírta' } ,'Delete this treatment?' : { cs: 'Vymazat toto ošetření?' @@ -3177,6 +3313,7 @@ function init() { ,ko: '이 대처를 지울까요?' ,tr: 'Bu tedaviyi sil?' ,zh_cn: '删除这个操作?' + ,hu: 'Kezelés törlése?' } ,'Carbs Given' : { cs: 'Sacharidů' @@ -3202,6 +3339,7 @@ function init() { ,ko: '탄수화물 요구량' ,tr: 'Karbonhidrat Verilen' ,zh_cn: '碳水化合物量' + ,hu: 'Szénhidrátok' } ,'Inzulin Given' : { cs: 'Inzulínu' @@ -3227,6 +3365,7 @@ function init() { ,ko: '인슐린 요구량' ,tr: 'İnsülin Verilen' ,zh_cn: '胰岛素输注' + ,hu: 'Beadott inzulin' } ,'Event Time' : { cs: 'Čas události' @@ -3252,6 +3391,7 @@ function init() { ,ko: '입력 시간' ,tr: 'Etkinliğin zamanı' ,zh_cn: '事件时间' + ,hu: 'Időpont' } ,'Please verify that the data entered is correct' : { cs: 'Prosím zkontrolujte, zda jsou údaje zadány správně' @@ -3277,6 +3417,7 @@ function init() { ,ko: '입력한 데이터가 정확한지 확인해 주세요.' ,tr: 'Lütfen girilen verilerin doğru olduğunu kontrol edin.' ,zh_cn: '请验证输入的数据是否正确' + ,hu: 'Kérlek ellenőrizd, hogy az adatok helyesek.' } ,'BG' : { cs: 'Glykémie' @@ -3302,6 +3443,7 @@ function init() { ,ko: '혈당' ,tr: 'KŞ' ,zh_cn: '血糖' + ,hu: 'Cukorszint' } ,'Use BG correction in calculation' : { cs: 'Použij korekci na glykémii' @@ -3327,6 +3469,7 @@ function init() { ,ko: '계산에 보정된 혈당을 사용하세요.' ,tr: 'Hesaplamada KŞ düzeltmesini kullan' ,zh_cn: '使用血糖值修正计算' + ,hu: 'Használj korekciót a számításban' } ,'BG from CGM (autoupdated)' : { cs: 'Glykémie z CGM (automaticky aktualizovaná)' @@ -3352,6 +3495,7 @@ function init() { ,ko: 'CGM 혈당(자동 업데이트)' ,tr: 'CGM den KŞ (otomatik güncelleme)' ,zh_cn: 'CGM(连续血糖监测)测量的血糖值(自动更新)' + ,hu: 'Cukorszint a CGM-ből (Automatikus frissítés)' } ,'BG from meter' : { cs: 'Glykémie z glukoměru' @@ -3377,6 +3521,7 @@ function init() { ,ko: '혈당 측정기에서의 혈당' ,tr: 'Glikometre KŞ' ,zh_cn: '血糖仪测量的血糖值' + ,hu: 'Cukorszint a merőből' } ,'Manual BG' : { cs: 'Ručně zadaná glykémie' @@ -3402,6 +3547,7 @@ function init() { ,ko: '수동 입력 혈당' ,tr: 'Manuel KŞ' ,zh_cn: '手动输入的血糖值' + ,hu: 'Kézi cukorszint' } ,'Quickpick' : { cs: 'Rychlý výběr' @@ -3427,6 +3573,7 @@ function init() { ,ko: '빠른 선택' ,tr: 'Hızlı seçim' ,zh_cn: '快速选择' + ,hu: 'Gyors választás' } ,'or' : { cs: 'nebo' @@ -3452,10 +3599,11 @@ function init() { ,ko: '또는' ,tr: 'veya' ,zh_cn: '或' + ,hu: 'vagy' } ,'Add from database' : { cs: 'Přidat z databáze' - ,de: 'Ergänzt aus Datenbank' + ,de: 'Ergänze aus Datenbank' ,es: 'Añadir desde la base de datos' ,fr: 'Ajouter à partir de la base de données' ,el: 'Επιλογή από τη Βάση Δεδομένων' @@ -3477,6 +3625,7 @@ function init() { ,ko: '데이터베이스로 부터 추가' ,tr: 'Veritabanından ekle' ,zh_cn: '从数据库增加' + ,hu: 'Hozzáadás adatbázisból' } ,'Use carbs correction in calculation' : { cs: 'Použij korekci na sacharidy' @@ -3496,12 +3645,13 @@ function init() { ,fi: 'Käytä hiilihydraattikorjausta laskennassa' ,nb: 'Bruk karbohydratkorrigering i beregning' ,pl: 'Użyj wartość węglowodanów w obliczeniach korekty' - ,ru: 'Пользуйтесь коррекцией на углеводы при расчете' + ,ru: 'Пользоваться коррекцией на углеводы при расчете' ,sk: 'Použite korekciu na sacharidy' ,nl: 'Gebruik KH correctie in berekening' ,ko: '계산에 보정된 탄수화물을 사용하세요.' ,tr: 'Hesaplamada karbonhidrat düzeltmesini kullan' ,zh_cn: '使用碳水化合物修正计算结果' + ,hu: 'Használj szénhidrát korekciót a számításban' } ,'Use COB correction in calculation' : { cs: 'Použij korekci na COB' @@ -3521,12 +3671,13 @@ function init() { ,fi: 'Käytä aktiivisia hiilihydraatteja laskennassa' ,nb: 'Benytt aktive karbohydrater i beregning' ,pl: 'Użyj COB do obliczenia korekty' - ,ru: 'Учитывайте активные углеводы COB при расчете' + ,ru: 'Учитывать активные углеводы COB при расчете' ,sk: 'Použite korekciu na COB' ,nl: 'Gebruik ingenomen KH in berekening' ,ko: '계산에 보정된 COB를 사용하세요.' ,tr: 'Hesaplamada COB aktif karbonhidrat düzeltmesini kullan' ,zh_cn: '使用COB(活性碳水化合物)修正计算结果' + ,hu: 'Használj COB korrekciót a számításban' } ,'Use IOB in calculation' : { cs: 'Použij IOB ve výpočtu' @@ -3546,12 +3697,13 @@ function init() { ,fi: 'Käytä aktiviivista insuliinia laskennassa' ,nb: 'Bruk aktivt insulin i beregningen' ,pl: 'Użyj IOB w obliczeniach' - ,ru: 'Учитывайте активный инсулин IOB при расчете' + ,ru: 'Учитывать активный инсулин IOB при расчете' ,sk: 'Použite IOB vo výpočte' ,nl: 'Gebruik IOB in berekening' ,ko: '계산에 IOB를 사용하세요.' ,tr: 'Hesaplamada IOB aktif insülin düzeltmesini kullan' ,zh_cn: '使用IOB(活性胰岛素)修正计算结果' + ,hu: 'Használj IOB kalkulációt' } ,'Other correction' : { cs: 'Jiná korekce' @@ -3577,6 +3729,7 @@ function init() { ,ko: '다른 보정' ,tr: 'Diğer düzeltme' ,zh_cn: '其它修正' + ,hu: 'Egyébb korrekció' } ,'Rounding' : { cs: 'Zaokrouhlení' @@ -3602,6 +3755,7 @@ function init() { ,ko: '라운딩' ,tr: 'yuvarlama' ,zh_cn: '取整' + ,hu: 'Kerekítés' } ,'Enter insulin correction in treatment' : { cs: 'Zahrň inzulín do záznamu ošetření' @@ -3621,12 +3775,13 @@ function init() { ,fi: 'Syötä insuliinikorjaus' ,nb: 'Task inn insulinkorrigering' ,pl: 'Wprowadź wartość korekty w leczeniu' - ,ru: 'Введите коррекцию инсулина в лечение' + ,ru: 'Внести коррекцию инсулина в лечение' ,sk: 'Zadajte korekciu inzulínu do ošetrenia' ,nl: 'Voer insuline correctie toe aan behandeling' ,ko: '대처를 위해 보정된 인슐린을 입력하세요.' ,tr: 'Tedavide insülin düzeltmesini girin' ,zh_cn: '在操作中输入胰岛素修正' + ,hu: 'Add be az inzulin korrekciót a kezeléshez' } ,'Insulin needed' : { cs: 'Potřebný inzulín' @@ -3652,6 +3807,7 @@ function init() { ,ko: '인슐린 필요' ,tr: 'İnsülin gerekli' ,zh_cn: '需要的胰岛素量' + ,hu: 'Inzulin szükséges' } ,'Carbs needed' : { cs: 'Potřebné sach' @@ -3677,6 +3833,7 @@ function init() { ,ko: '탄수화물 필요' ,tr: 'Karbonhidrat gerekli' ,zh_cn: '需要的碳水量' + ,hu: 'Szenhidrát szükséges' } ,'Carbs needed if Insulin total is negative value' : { cs: 'Chybějící sacharidy v případě, že výsledek je záporný' @@ -3702,6 +3859,7 @@ function init() { ,ko: '인슐린 전체가 마이너스 값이면 탄수화물이 필요합니다.' ,tr: 'Toplam insülin negatif değer olduğunda karbonhidrat gereklidir' ,zh_cn: '如果胰岛素总量为负时所需的碳水化合物量' + ,hu: 'Szénhidrát szükséges ha az összes inzulin negatív érték' } ,'Basal rate' : { cs: 'Bazál' @@ -3727,11 +3885,12 @@ function init() { ,ko: 'Basal 단위' ,tr: 'Basal oranı' ,zh_cn: '基础率' + ,hu: 'Bazál arány' } ,'60 minutes earlier' : { cs: '60 min předem' ,he: 'שישים דקות מוקדם יותר' - ,de: '60 Min. früher' + ,de: '60 Minuten früher' ,es: '60 min antes' ,fr: '60 min plus tôt' ,el: '60 λεπτά πριν' @@ -3752,11 +3911,12 @@ function init() { ,ko: '60분 더 일찍' ,tr: '60 dak. önce' //erken önce ??? ,zh_cn: '60分钟前' + ,hu: '60 perccel korábban' } ,'45 minutes earlier' : { cs: '45 min předem' ,he: 'ארבעים דקות מוקדם יותר' - ,de: '45 Min. früher' + ,de: '45 Minuten früher' ,es: '45 min antes' ,fr: '45 min plus tôt' ,el: '45 λεπτά πριν' @@ -3777,11 +3937,12 @@ function init() { ,ko: '45분 더 일찍' ,tr: '45 dak. önce' ,zh_cn: '45分钟前' + ,hu: '45 perccel korábban' } ,'30 minutes earlier' : { cs: '30 min předem' ,he: 'שלושים דקות מוקדם יותר' - ,de: '30 Min früher' + ,de: '30 Minuten früher' ,es: '30 min antes' ,fr: '30 min plus tôt' ,el: '30 λεπτά πριν' @@ -3802,11 +3963,12 @@ function init() { ,ko: '30분 더 일찍' ,tr: '30 dak. önce' ,zh_cn: '30分钟前' + ,hu: '30 perccel korábban' } ,'20 minutes earlier' : { cs: '20 min předem' ,he: 'עשרים דקות מוקדם יותר' - ,de: '20 Min. früher' + ,de: '20 Minuten früher' ,es: '20 min antes' ,fr: '20 min plus tôt' ,el: '20 λεπτά πριν' @@ -3827,11 +3989,12 @@ function init() { ,ko: '20분 더 일찍' ,tr: '20 dak. önce' ,zh_cn: '20分钟前' + ,hu: '20 perccel korábban' } ,'15 minutes earlier' : { cs: '15 min předem' ,he: 'חמש עשרה דקות מוקדם יותר' - ,de: '15 Min. früher' + ,de: '15 Minuten früher' ,es: '15 min antes' ,fr: '15 min plus tôt' ,el: '15 λεπτά πριν' @@ -3852,6 +4015,7 @@ function init() { ,ko: '15분 더 일찍' ,tr: '15 dak. önce' ,zh_cn: '15分钟前' + ,hu: '15 perccel korábban' } ,'Time in minutes' : { cs: 'Čas v minutách' @@ -3876,10 +4040,11 @@ function init() { ,ko: '분' ,tr: 'Dakika cinsinden süre' ,zh_cn: '1分钟前' + ,hu: 'Idő percekben' } ,'15 minutes later' : { cs: '15 min po' - ,de: '15 Min. später' + ,de: '15 Minuten später' ,es: '15 min más tarde' ,fr: '15 min plus tard' ,el: '15 λεπτά αργότερα' @@ -3901,10 +4066,11 @@ function init() { ,ko: '15분 더 나중에' ,tr: '15 dak. sonra' //sonra daha sonra ,zh_cn: '15分钟后' + ,hu: '15 perccel később' } ,'20 minutes later' : { cs: '20 min po' - ,de: '20 Min. später' + ,de: '20 Minuten später' ,es: '20 min más tarde' ,fr: '20 min plus tard' ,el: '20 λεπτά αργότερα' @@ -3926,10 +4092,11 @@ function init() { ,ko: '20분 더 나중에' ,tr: '20 dak. sonra' ,zh_cn: '20分钟后' + ,hu: '20 perccel később' } ,'30 minutes later' : { cs: '30 min po' - ,de: '30 Min. später' + ,de: '30 Minuten später' ,es: '30 min más tarde' ,fr: '30 min plus tard' ,el: '30 λεπτά αργότερα' @@ -3951,10 +4118,11 @@ function init() { ,ko: '30분 더 나중에' ,tr: '30 dak. sonra' ,zh_cn: '30分钟后' + ,hu: '30 perccel kesőbb' } ,'45 minutes later' : { cs: '45 min po' - ,de: '45 Min. später' + ,de: '45 Minuten später' ,es: '45 min más tarde' ,fr: '45 min plus tard' ,el: '45 λεπτά αργότερα' @@ -3976,10 +4144,11 @@ function init() { ,ko: '45분 더 나중에' ,tr: '45 dak. sonra' ,zh_cn: '45分钟后' + ,hu: '45 perccel később' } ,'60 minutes later' : { cs: '60 min po' - ,de: '60 Min. später' + ,de: '60 Minuten später' ,es: '60 min más tarde' ,fr: '60 min plus tard' ,el: '60 λεπτά αργότερα' @@ -4001,6 +4170,7 @@ function init() { ,ko: '60분 더 나중에' ,tr: '60 dak. sonra' ,zh_cn: '60分钟后' + ,hu: '60 perccel később' } ,'Additional Notes, Comments' : { cs: 'Dalši poznámky, komentáře' @@ -4026,11 +4196,12 @@ function init() { ,ko: '추가 메모' ,tr: 'Ek Notlar, Yorumlar' ,zh_cn: '备注' + ,hu: 'Feljegyzések, hozzászólások' } ,'RETRO MODE' : { cs: 'V MINULOSTI' ,he: 'מצב רטרו' - ,de: 'RETRO MODUS' + ,de: 'Retro-Modus' ,es: 'Modo Retrospectivo' ,fr: 'MODE RETROSPECTIF' ,el: 'Αναδρομική Λειτουργία' @@ -4051,6 +4222,7 @@ function init() { ,ko: 'PETRO MODE' ,tr: 'RETRO MODE' ,zh_cn: '历史模式' + ,hu: 'RETRO mód' } ,'Now' : { cs: 'Nyní' @@ -4076,6 +4248,7 @@ function init() { ,ko: '현재' ,tr: 'Şimdi' ,zh_cn: '现在' + ,hu: 'Most' } ,'Other' : { cs: 'Jiný' @@ -4101,6 +4274,7 @@ function init() { ,ko: '다른' ,tr: 'Diğer' ,zh_cn: '其它' + ,hu: 'Más' } ,'Submit Form' : { cs: 'Odeslat formulář' @@ -4126,6 +4300,7 @@ function init() { ,ko: '양식 제출' ,tr: 'Formu gönder' ,zh_cn: '提交' + ,hu: 'Elküldés' } ,'Profile Editor' : { cs: 'Editor profilu' @@ -4152,6 +4327,7 @@ function init() { ,tr: 'Profil Düzenleyicisi' ,zh_cn: '配置文件编辑器' ,zh_tw: '配置文件編輯器' + ,hu: 'Profil Szerkesztő' } ,'Reports' : { cs: 'Výkazy' @@ -4178,6 +4354,7 @@ function init() { ,tr: 'Raporlar' ,zh_cn: '生成报表' ,zh_tw: '生成報表' + ,hu: 'Jelentések' } ,'Add food from your database' : { cs: 'Přidat jidlo z Vaší databáze' @@ -4197,12 +4374,13 @@ function init() { ,fi: 'Lisää ruoka tietokannasta' ,nb: 'Legg til mat fra din database' ,pl: 'Dodaj posiłek z twojej bazy danych' - ,ru: 'Добавьте продукт из вашей базы данных' + ,ru: 'Добавить продукт из вашей базы данных' ,sk: 'Pridať jedlo z Vašej databázy' ,nl: 'Voeg voeding toe uit uw database' ,ko: '데이터베이스에서 음식을 추가하세요.' ,tr: 'Veritabanınızdan yemek ekleyin' ,zh_cn: '从数据库增加食物' + ,hu: 'Étel hozzáadása az adatbázisból' } ,'Reload database' : { cs: 'Znovu nahraj databázi' @@ -4222,12 +4400,13 @@ function init() { ,fi: 'Lataa tietokanta uudelleen' ,nb: 'Last inn databasen på nytt' ,pl: 'Odśwież bazę danych' - ,ru: 'Перезагрузите базу данных' + ,ru: 'Перезагрузить базу данных' ,sk: 'Obnoviť databázu' ,nl: 'Database opnieuw laden' ,ko: '데이터베이스 재로드' ,tr: 'Veritabanını yeniden yükle' ,zh_cn: '重新载入数据库' + ,hu: 'Adatbázis újratöltése' } ,'Add' : { cs: 'Přidej' @@ -4247,12 +4426,13 @@ function init() { ,fi: 'Lisää' ,nb: 'Legg til' ,pl: 'Dodaj' - ,ru: 'Добавьте' + ,ru: 'Добавить' ,sk: 'Pridať' ,nl: 'Toevoegen' ,ko: '추가' ,tr: 'Ekle' ,zh_cn: '增加' + ,hu: 'Hozzáadni' } ,'Unauthorized' : { cs: 'Neautorizováno' @@ -4279,6 +4459,7 @@ function init() { ,tr: 'Yetkisiz' ,zh_cn: '未授权' ,zh_tw: '未授權' + ,hu: 'Nincs autorizávla' } ,'Entering record failed' : { cs: 'Vložení záznamu selhalo' @@ -4304,6 +4485,7 @@ function init() { ,ko: '입력 실패' ,tr: 'Kayıt girişi başarısız oldu' ,zh_cn: '输入记录失败' + ,hu: 'Hozzáadás nem sikerült' } ,'Device authenticated' : { cs: 'Zařízení ověřeno' @@ -4330,6 +4512,7 @@ function init() { ,tr: 'Cihaz kimliği doğrulandı' ,zh_cn: '设备已认证' ,zh_tw: '設備已認證' + ,hu: 'Berendezés hitelesítve' } ,'Device not authenticated' : { cs: 'Zařízení není ověřeno' @@ -4356,6 +4539,7 @@ function init() { ,tr: 'Cihaz kimliği doğrulanmamış' ,zh_cn: '设备未认证' ,zh_tw: '設備未認證' + ,hu: 'Berendezés nincs hitelesítve' } ,'Authentication status' : { cs: 'Stav ověření' @@ -4382,6 +4566,7 @@ function init() { ,tr: 'Kimlik doğrulama durumu' ,zh_cn: '认证状态' ,zh_tw: '認證狀態' + ,hu: 'Hitelesítés állapota' } ,'Authenticate' : { cs: 'Ověřit' @@ -4408,6 +4593,7 @@ function init() { ,tr: 'Kimlik doğrulaması' ,zh_cn: '认证' ,zh_tw: '認證' + ,hu: 'Hitelesítés' } ,'Remove' : { cs: 'Vymazat' @@ -4434,6 +4620,7 @@ function init() { ,tr: 'Kaldır' ,zh_cn: '取消' ,zh_tw: '取消' + ,hu: 'Eltávolítani' } ,'Your device is not authenticated yet' : { cs: 'Toto zařízení nebylo dosud ověřeno' @@ -4460,6 +4647,7 @@ function init() { ,tr: 'Cihazınız henüz doğrulanmamış' ,zh_cn: '此设备还未进行认证' ,zh_tw: '這個設備還未進行認證' + ,hu: 'A berendezés még nincs hitelesítve' } ,'Sensor' : { cs: 'Senzor' @@ -4485,6 +4673,7 @@ function init() { ,ko: '센서' ,tr: 'Sensor' ,zh_cn: 'CGM探头' + ,hu: 'Szenzor' } ,'Finger' : { cs: 'Glukoměr' @@ -4510,6 +4699,7 @@ function init() { ,ko: '손가락' ,tr: 'Parmak' ,zh_cn: '手指' + ,hu: 'Új' } ,'Manual' : { cs: 'Ručně' @@ -4535,6 +4725,7 @@ function init() { ,ko: '수' ,tr: 'Elle' ,zh_cn: '手动' + ,hu: 'Kézi' } ,'Scale' : { cs: 'Měřítko' @@ -4561,6 +4752,7 @@ function init() { ,tr: 'Ölçek' ,zh_cn: '函数' ,zh_tw: '函數' + ,hu: 'Mérték' } ,'Linear' : { cs: 'Lineární' @@ -4587,6 +4779,7 @@ function init() { ,tr: 'Doğrusal' //çizgisel ,zh_cn: '线性' ,zh_tw: '線性' + ,hu: 'Lineáris' } ,'Logarithmic' : { cs: 'Logaritmické' @@ -4613,6 +4806,7 @@ function init() { ,tr: 'Logaritmik' ,zh_cn: '对数' ,zh_tw: '對數' + ,hu: 'Logaritmikus' } ,'Logarithmic (Dynamic)' : { cs: 'Logaritmické (Dynamické)' @@ -4639,6 +4833,7 @@ function init() { ,tr: 'Logaritmik (Dinamik)' ,zh_cn: '对数(动态)' ,zh_tw: '對數(動態)' + ,hu: 'Logaritmikus (Dinamikus)' } ,'Insulin-on-Board' : { cs: 'IOB' @@ -4665,6 +4860,7 @@ function init() { ,tr: 'Aktif İnsülin (IOB)' ,zh_cn: '活性胰岛素(IOB)' ,zh_tw: '活性胰島素(IOB)' + ,hu: 'Aktív inzulin (IOB)' } ,'Carbs-on-Board' : { cs: 'COB' @@ -4691,6 +4887,7 @@ function init() { ,tr: 'Aktif Karbonhidrat (COB)' ,zh_cn: '活性碳水化合物(COB)' ,zh_tw: '活性碳水化合物(COB)' + ,hu: 'Aktív szénhidrát (COB)' } ,'Bolus Wizard Preview' : { cs: 'BWP-Náhled bolusového kalk.' @@ -4717,6 +4914,7 @@ function init() { ,tr: 'Bolus hesaplama Sihirbazı Önizlemesi (BWP)' //İnsülin etkinlik süresi hesaplaması ,zh_cn: '大剂量向导预览(BWP)' ,zh_tw: '大劑量嚮導預覽(BWP)' + ,hu: 'Bolus Varázsló' } ,'Value Loaded' : { cs: 'Hodnoty načteny' @@ -4743,6 +4941,7 @@ function init() { ,tr: 'Yüklenen Değer' ,zh_cn: '数值已读取' ,zh_tw: '數值已讀取' + ,hu: 'Érték betöltve' } ,'Cannula Age' : { cs: 'CAGE-Stáří kanyly' @@ -4762,13 +4961,14 @@ function init() { ,sv: 'Kanylålder (CAGE)' ,pl: 'Czas wkłucia (CAGE)' ,pt: 'Idade da Cânula (ICAT)' - ,ru: 'Канюля отработала' + ,ru: 'Катетер проработал' ,sk: 'Zavedenie kanyly (CAGE)' ,nl: 'Canule leeftijd (CAGE)' ,ko: '캐뉼라 사용기간' ,tr: 'Kanül yaşı' ,zh_cn: '管路使用时间(CAGE)' ,zh_tw: '管路使用時間(CAGE)' + ,hu: 'Kanula élettartalma (CAGE)' } ,'Basal Profile' : { cs: 'Bazál' @@ -4795,6 +4995,7 @@ function init() { ,tr: 'Bazal Profil' ,zh_cn: '基础率配置文件' ,zh_tw: '基礎率配置文件' + ,hu: 'Bazál profil' } ,'Silence for 30 minutes' : { cs: 'Ztlumit na 30 minut' @@ -4821,6 +5022,7 @@ function init() { ,tr: '30 dakika sessizlik' ,zh_cn: '静音30分钟' ,zh_tw: '靜音30分鐘' + ,hu: 'Lehalkítás 30 percre' } ,'Silence for 60 minutes' : { cs: 'Ztlumit na 60 minut' @@ -4847,7 +5049,8 @@ function init() { ,tr: '60 dakika sessizlik' ,zh_cn: '静音60分钟' ,zh_tw: '靜音60分鐘' - } + ,hu: 'Lehalkítás 60 percre' + } ,'Silence for 90 minutes' : { cs: 'Ztlumit na 90 minut' ,he: 'השתק לתשעים דקות' @@ -4873,7 +5076,8 @@ function init() { ,tr: '90 dakika sessizlik' ,zh_cn: '静音90分钟' ,zh_tw: '靜音90分鐘' - } + ,hu: 'Lehalkítás 90 percre' + } ,'Silence for 120 minutes' : { cs: 'Ztlumit na 120 minut' ,he: 'השתק לשעתיים' @@ -4899,7 +5103,8 @@ function init() { ,tr: '120 dakika sessizlik' ,zh_cn: '静音2小时' ,zh_tw: '靜音2小時' - } + ,hu: 'Lehalkítás 120 percre' + } ,'Settings' : { cs: 'Nastavení' ,he: 'הגדרות' @@ -4925,6 +5130,7 @@ function init() { ,tr: 'Ayarlar' ,zh_cn: '设置' ,zh_tw: '設置' + ,hu: 'Beállítások' } ,'Units' : { cs: 'Jednotky' @@ -4950,6 +5156,7 @@ function init() { ,tr: 'Birim' //Birim Ünite ,zh_cn: '计量单位' ,zh_tw: '计量單位' + ,hu: 'Egységek' } ,'Date format' : { cs: 'Formát datumu' @@ -4976,6 +5183,7 @@ function init() { ,tr: 'Veri formatı' ,zh_cn: '时间格式' ,zh_tw: '時間格式' + ,hu: 'Időformátum' } ,'12 hours' : { cs: '12 hodin' @@ -5002,6 +5210,7 @@ function init() { ,tr: '12 saat' ,zh_cn: '12小时制' ,zh_tw: '12小時制' + ,hu: '12 óra' } ,'24 hours' : { cs: '24 hodin' @@ -5028,6 +5237,7 @@ function init() { ,tr: '24 saat' ,zh_cn: '24小时制' ,zh_tw: '24小時制' + ,hu: '24 óra' } ,'Log a Treatment' : { cs: 'Záznam ošetření' @@ -5047,16 +5257,17 @@ function init() { ,nb: 'Logg en hendelse' ,he: 'הזן רשומה' ,pl: 'Wprowadź leczenie' - ,ru: 'Журнал лечения' + ,ru: 'Записать лечение' ,sk: 'Záznam ošetrenia' ,nl: 'Registreer een behandeling' ,ko: 'Treatment 로그' ,tr: 'Tedaviyi günlüğe kaydet' ,zh_cn: '记录操作' + ,hu: 'Kezelés bejegyzése' } ,'BG Check' : { cs: 'Kontrola glykémie' - ,de: 'BG-Prüfung' + ,de: 'BG-Messung' ,es: 'Control de glucemia' ,fr: 'Contrôle glycémie' ,el: 'Έλεγχος Γλυκόζης' @@ -5078,6 +5289,7 @@ function init() { ,ko: '혈당 체크' ,tr: 'KŞ Kontol' ,zh_cn: '测量血糖' + ,hu: 'Cukorszint ellenőrzés' } ,'Meal Bolus' : { cs: 'Bolus na jídlo' @@ -5103,6 +5315,7 @@ function init() { ,ko: '식사 인슐린' ,tr: 'Yemek bolus' ,zh_cn: '正餐大剂量' + ,hu: 'Étel bólus' } ,'Snack Bolus' : { cs: 'Bolus na svačinu' @@ -5128,6 +5341,7 @@ function init() { ,ko: '스넥 인슐린' ,tr: 'Aperatif (Snack) Bolus' ,zh_cn: '加餐大剂量' + ,hu: 'Tízórai/Uzsonna bólus' } ,'Correction Bolus' : { cs: 'Bolus na glykémii' @@ -5153,6 +5367,7 @@ function init() { ,ko: '수정 인슐린' ,tr: 'Düzeltme Bolusu' ,zh_cn: '临时大剂量' + ,hu: 'Korrekciós bólus' } ,'Carb Correction' : { cs: 'Přídavek sacharidů' @@ -5178,6 +5393,7 @@ function init() { ,ko: '탄수화물 수정' ,tr: 'Karbonhidrat Düzeltme' ,zh_cn: '碳水修正' + ,hu: 'Szénhidrát korrekció' } ,'Note' : { cs: 'Poznámka' @@ -5203,6 +5419,7 @@ function init() { ,ko: '메모' ,tr: 'Not' ,zh_cn: '备忘' + ,hu: 'Jegyzet' } ,'Question' : { cs: 'Otázka' @@ -5228,6 +5445,7 @@ function init() { ,ko: '질문' ,tr: 'Soru' ,zh_cn: '问题' + ,hu: 'Kérdés' } ,'Exercise' : { cs: 'Cvičení' @@ -5253,6 +5471,7 @@ function init() { ,ko: '운동' ,tr: 'Egzersiz' ,zh_cn: '运动' + ,hu: 'Edzés' } ,'Pump Site Change' : { cs: 'Výměna setu' @@ -5272,12 +5491,13 @@ function init() { ,nb: 'Pumpebytte' ,he: 'החלפת צינורית משאבה' ,pl: 'Zmiana miejsca wkłucia pompy' - ,ru: 'Смена места катетора помпы' + ,ru: 'Смена катетера помпы' ,sk: 'Výmena setu' ,nl: 'Nieuwe pomp infuus' ,ko: '펌프 위치 변경' ,tr: 'Pompa Kanül değişimi' ,zh_cn: '更换胰岛素输注部位' + ,hu: 'Pumpa szett csere' } ,'CGM Sensor Start' : { cs: 'Spuštění sensoru' @@ -5303,6 +5523,7 @@ function init() { ,ko: 'CGM 센서 시작' ,tr: 'CGM Sensörü Başlat' ,zh_cn: '启动CGM(连续血糖监测)探头' + ,hu: 'CGM Szenzor Indítása' } ,'CGM Sensor Stop' : { cs: 'CGM Sensor Stop' @@ -5322,12 +5543,13 @@ function init() { ,nb: 'CGM Sensor Stop' ,he: 'CGM Sensor Stop' ,pl: 'CGM Sensor Stop' - ,ru: 'Остановка сенсора' + ,ru: 'Стоп сенсор' ,sk: 'CGM Sensor Stop' ,nl: 'CGM Sensor Stop' ,ko: 'CGM Sensor Stop' ,tr: 'CGM Sensor Stop' ,zh_cn: 'CGM Sensor Stop' + ,hu: 'CGM Szenzor Leállítása' } ,'CGM Sensor Insert' : { cs: 'Výměna sensoru' @@ -5353,6 +5575,7 @@ function init() { ,ko: 'CGM 센서 삽입' ,tr: 'CGM Sensor yerleştir' ,zh_cn: '植入CGM(连续血糖监测)探头' + ,hu: 'CGM Szenzor Csere' } ,'Dexcom Sensor Start' : { cs: 'Spuštění sensoru' @@ -5372,13 +5595,14 @@ function init() { ,nb: 'Dexcom sensor start' ,he: 'אתחול חיישן סוכר של דקסקום' ,pl: 'Start sensora DEXCOM' - ,ru: 'Старт сенсора Декском' + ,ru: 'Старт сенсора' ,sk: 'Spustenie senzoru DEXCOM' ,nl: 'Dexcom sensor start' ,ko: 'Dexcom 센서 시작' ,tr: 'Dexcom Sensör Başlat' ,zh_cn: '启动Dexcom探头' - } + ,hu: 'Dexcom Szenzor Indítása' + } ,'Dexcom Sensor Change' : { cs: 'Výměna sensoru' ,de: 'Dexcom Sensor Wechsel' @@ -5403,7 +5627,8 @@ function init() { ,ko: 'Dexcom 센서 교체' ,tr: 'Dexcom Sensör değiştir' ,zh_cn: '更换Dexcom探头' - } + ,hu: 'Dexcom Szenzor Csere' + } ,'Insulin Cartridge Change' : { cs: 'Výměna inzulínu' ,de: 'Insulin Ampullenwechsel' @@ -5428,6 +5653,7 @@ function init() { ,ko: '인슐린 카트리지 교체' ,tr: 'İnsülin rezervuar değişimi' ,zh_cn: '更换胰岛素储液器' + ,hu: 'Inzulin Tartály Csere' } ,'D.A.D. Alert' : { cs: 'D.A.D. Alert' @@ -5453,6 +5679,7 @@ function init() { ,ko: 'D.A.D(Diabetes Alert Dog) 알림' ,tr: 'D.A.D(Diabetes Alert Dog)' ,zh_cn: 'D.A.D(低血糖通报犬)警告' + ,hu: 'D.A.D Figyelmeztetés' } ,'Glucose Reading' : { cs: 'Hodnota glykémie' @@ -5477,6 +5704,7 @@ function init() { ,ko: '혈당 읽기' ,tr: 'Glikoz Değeri' ,zh_cn: '血糖数值' + ,hu: 'Vércukorszint Érték' } ,'Measurement Method' : { cs: 'Metoda měření' @@ -5502,6 +5730,7 @@ function init() { ,ko: '측정 방법' ,tr: 'Ölçüm Metodu' ,zh_cn: '测量方法' + ,hu: 'Cukorszint mérés metódusa' } ,'Meter' : { cs: 'Glukoměr' @@ -5527,6 +5756,7 @@ function init() { ,ko: '혈당 측정기' ,tr: 'Glikometre' ,zh_cn: '血糖仪' + ,hu: 'Cukorszint mérő' } ,'Insulin Given' : { cs: 'Inzulín' @@ -5546,12 +5776,13 @@ function init() { ,nb: 'Insulin' ,he: 'אינסולין שניתן' ,pl: 'Podana insulina' - ,ru: 'Введенный инсулин' + ,ru: 'Введен инсулин' ,sk: 'Podaný inzulín' ,nl: 'Toegediende insuline' ,ko: '인슐린 요구량' ,tr: 'Verilen İnsülin' ,zh_cn: '胰岛素输注量' + ,hu: 'Inzulin Beadva' } ,'Amount in grams' : { cs: 'Množství v gramech' @@ -5577,6 +5808,7 @@ function init() { ,ko: '합계(grams)' ,tr: 'Gram cinsinden miktar' ,zh_cn: '总量(g)' + ,hu: 'Adag grammokban (g)' } ,'Amount in units' : { cs: 'Množství v jednotkách' @@ -5602,10 +5834,11 @@ function init() { ,ko: '합계(units)' ,tr: 'Birim miktarı' ,zh_cn: '总量(U)' + ,hu: 'Adag egységekben' } ,'View all treatments' : { cs: 'Zobraz všechny ošetření' - ,de: 'Zeige alle Eingaben' + ,de: 'Zeige alle Behandlungen' ,es: 'Visualizar todos los tratamientos' ,fr: 'Voir tous les traitements' ,el: 'Προβολή όλων των ενεργειών' @@ -5627,6 +5860,7 @@ function init() { ,ko: '모든 treatments 보기' ,tr: 'Tüm tedavileri görüntüle' ,zh_cn: '查看所有操作' + ,hu: 'Összes kezelés mutatása' } ,'Enable Alarms' : { cs: 'Povolit alarmy' @@ -5653,6 +5887,7 @@ function init() { ,tr: 'Alarmları Etkinleştir' ,zh_cn: '启用报警' ,zh_tw: '啟用報警' + ,hu: 'Figyelmeztetők bekapcsolása' } ,'Pump Battery Change' : { nl: 'Pompbatterij vervangen' @@ -5666,6 +5901,7 @@ function init() { ,pl: 'Zmiana baterii w pompie' ,ru: 'замена батареи помпы' ,tr: 'Pompa pil değişimi' + ,hu: 'Pumpa elem csere' } ,'Pump Battery Low Alarm' : { nl: 'Pompbatterij bijna leeg Alarm' @@ -5679,6 +5915,7 @@ function init() { ,pl: 'Alarm! Niski poziom baterii w pompie' ,ru: 'Внимание! низкий заряд батареи помпы' ,tr: 'Pompa Düşük pil alarmı' + ,hu: 'Alacsony pumpa töltöttség figyelmeztetés' } ,'Pump Battery change overdue!' : { // batteryage.js nl: 'Pompbatterij moet vervangen worden!' @@ -5692,6 +5929,7 @@ function init() { , pl: 'Bateria pompy musi być wymieniona!' ,ru: 'пропущен срок замены батареи!' ,tr: 'Pompa pil değişimi gecikti!' + ,hu: 'A pumpa eleme cserére szorul' } ,'When enabled an alarm may sound.' : { cs: 'Při povoleném alarmu zní zvuk' @@ -5711,13 +5949,14 @@ function init() { ,nb: 'Når aktivert er alarmer aktive' ,he: 'כשמופעל התראות יכולות להישמע.' ,pl: 'Sygnalizacja dzwiękowa przy włączonym alarmie' - ,ru: 'При активации сигналы слышны' + ,ru: 'При активации может звучать сигнал' ,sk: 'Pri aktivovanom alarme znie zvuk ' ,nl: 'Als ingeschakeld kan alarm klinken' ,ko: '알림을 활성화 하면 알람이 울립니다.' ,tr: 'Etkinleştirilirse, alarm çalar.' ,zh_cn: '启用后可发出声音报警' ,zh_tw: '啟用後可發出聲音報警' + ,hu: 'Bekapcsoláskor hang figyelmeztetés várható' } ,'Urgent High Alarm' : { cs: 'Urgentní vysoká glykémie' @@ -5744,6 +5983,7 @@ function init() { ,tr: 'Acil Yüksek Alarm' //Dikkat yüksek alarm ,zh_cn: '血糖过高报警' ,zh_tw: '血糖過高報警' + ,hu: 'Nagyon magas cukorszint figyelmeztetés' } ,'High Alarm' : { cs: 'Vysoká glykémie' @@ -5770,6 +6010,7 @@ function init() { ,tr: 'Yüksek Alarmı' ,zh_cn: '高血糖报警' ,zh_tw: '高血糖報警' + ,hu: 'Magas cukorszint fegyelmeztetés' } ,'Low Alarm' : { cs: 'Nízká glykémie' @@ -5796,6 +6037,7 @@ function init() { ,tr: 'Düşük Alarmı' ,zh_cn: '低血糖报警' ,zh_tw: '低血糖報警' + ,hu: 'Alacsony cukorszint figyelmeztetés' } ,'Urgent Low Alarm' : { cs: 'Urgentní nízká glykémie' @@ -5822,6 +6064,7 @@ function init() { ,tr: 'Acil Düşük Alarmı' ,zh_cn: '血糖过低报警' ,zh_tw: '血糖過低報警' + ,hu: 'Nagyon alacsony cukorszint figyelmeztetés' } ,'Stale Data: Warn' : { cs: 'Zastaralá data' @@ -5848,6 +6091,7 @@ function init() { ,tr: 'Eski Veri: Uyarı' //Uyarı: veri artık geçerli değil ,zh_cn: '数据过期:提醒' ,zh_tw: '數據過期:提醒' + ,hu: 'Figyelmeztetés: Az adatok öregnek tűnnek' } ,'Stale Data: Urgent' : { cs: 'Zastaralá data urgentní' @@ -5874,11 +6118,12 @@ function init() { ,tr: 'Eski Veri: Acil' ,zh_cn: '数据过期:警告' ,zh_tw: '數據過期:警告' + ,hu: 'Figyelmeztetés: Az adatok nagyon öregnek tűnnek' } ,'mins' : { cs: 'min' ,he: 'דקות' - ,de: 'min' + ,de: 'Minuten' ,es: 'min' ,fr: 'mins' ,el: 'λεπτά' @@ -5900,6 +6145,7 @@ function init() { ,tr: 'dk.' ,zh_cn: '分' ,zh_tw: '分' + ,hu: 'perc' } ,'Night Mode' : { cs: 'Noční mód' @@ -5926,6 +6172,7 @@ function init() { ,tr: 'Gece Modu' ,zh_cn: '夜间模式' ,zh_tw: '夜間模式' + ,hu: 'Éjjeli üzemmód' } ,'When enabled the page will be dimmed from 10pm - 6am.' : { cs: 'Když je povoleno, obrazovka je ztlumena 22:00 - 6:00' @@ -5952,6 +6199,7 @@ function init() { ,tr: 'Etkinleştirildiğinde, ekran akşam 22\'den sabah 6\'ya kadar kararır.' ,zh_cn: '启用后将在夜间22点至早晨6点降低页面亮度' ,zh_tw: '啟用後將在夜間22點至早晨6點降低頁面亮度' + ,hu: 'Ezt bekapcsolva a képernyő halványabb lesz 22-től 6-ig' } ,'Enable' : { cs: 'Povoleno' @@ -5978,6 +6226,7 @@ function init() { ,tr: 'Etkinleştir' ,zh_cn: '启用' ,zh_tw: '啟用' + ,hu: 'Engedélyezve' } ,'Show Raw BG Data' : { cs: 'Zobraz RAW data' @@ -5996,14 +6245,15 @@ function init() { ,dk: 'Vis rå BS data' ,fi: 'Näytä raaka VS tieto' ,nb: 'Vis rådata' - ,pl: 'Wyświetl surowe dane RAW' - ,ru: 'Показывать необработанные RAW данные' + ,pl: 'Wyświetl surowe dane BG' + ,ru: 'Показывать необработанные данные RAW' ,sk: 'Zobraziť RAW dáta' ,nl: 'Laat ruwe data zien' ,ko: 'Raw 혈당 데이터 보기' ,tr: 'Ham KŞ verilerini göster' ,zh_cn: '显示原始血糖数据' ,zh_tw: '顯示原始血糖數據' + ,hu: 'Nyers BG adatok mutatása' } ,'Never' : { cs: 'Nikdy' @@ -6030,6 +6280,7 @@ function init() { ,tr: 'Hiçbir zaman' //Asla ,zh_cn: '不显示' ,zh_tw: '不顯示' + ,hu: 'Soha' } ,'Always' : { cs: 'Vždy' @@ -6056,6 +6307,7 @@ function init() { ,tr: 'Her zaman' ,zh_cn: '一直显示' ,zh_tw: '一直顯示' + ,hu: 'Mindíg' } ,'When there is noise' : { cs: 'Při šumu' @@ -6082,6 +6334,7 @@ function init() { ,tr: 'Gürültü olduğunda' ,zh_cn: '当有噪声时显示' ,zh_tw: '當有噪聲時顯示' + ,hu: 'Ha zavar van:' } ,'When enabled small white dots will be displayed for raw BG data' : { cs: 'Když je povoleno, malé tečky budou zobrazeny pro RAW data' @@ -6108,6 +6361,7 @@ function init() { ,tr: 'Etkinleştirildiğinde, ham KŞ verileri için küçük beyaz noktalar görüntülenecektir.' ,zh_cn: '启用后将使用小白点标注原始血糖数据' ,zh_tw: '啟用後將使用小白點標註原始血糖數據' + ,hu: 'Bekapcsolasnál kis fehért pontok fogják jelezni a nyers BG adatokat' } ,'Custom Title' : { cs: 'Vlastní název stránky' @@ -6134,11 +6388,12 @@ function init() { ,tr: 'Özel Başlık' ,zh_cn: '自定义标题' ,zh_tw: '自定義標題' + ,hu: 'Saját Cím' } ,'Theme' : { cs: 'Téma' ,he: 'נושא' - ,de: 'Thema' + ,de: 'Aussehen' ,es: 'Tema' ,fr: 'Thème' ,el: 'Θέμα απεικόνισης' @@ -6160,6 +6415,7 @@ function init() { ,tr: 'Tema' ,zh_cn: '主题' ,zh_tw: '主題' + ,hu: 'Téma' } ,'Default' : { cs: 'Výchozí' @@ -6186,6 +6442,7 @@ function init() { ,tr: 'Varsayılan' ,zh_cn: '默认' ,zh_tw: '默認' + ,hu: 'Alap' } ,'Colors' : { cs: 'Barevné' @@ -6212,6 +6469,7 @@ function init() { ,tr: 'Renkler' ,zh_cn: '彩色' ,zh_tw: '彩色' + ,hu: 'Színek' } ,'Colorblind-friendly colors' : { cs: 'Pro barvoslepé' @@ -6238,6 +6496,7 @@ function init() { ,pl: 'Kolory dla niedowidzących' ,tr: 'Renk körü dostu görünüm' ,ru: 'Цветовая гамма для людей с нарушениями восприятия цвета' + ,hu: 'Beállítás színvakok számára' } ,'Reset, and use defaults' : { cs: 'Vymaž a nastav výchozí hodnoty' @@ -6264,6 +6523,7 @@ function init() { ,tr: 'Sıfırla ve varsayılanları kullan' ,zh_cn: '使用默认值重置' ,zh_tw: '使用默認值重置' + ,hu: 'Visszaállítás a kiinduló állapotba' } ,'Calibrations' : { cs: 'Kalibrace' @@ -6289,6 +6549,7 @@ function init() { ,ko: '보정' ,tr: 'Kalibrasyon' ,zh_cn: '校准' + ,hu: 'Kalibráció' } ,'Alarm Test / Smartphone Enable' : { cs: 'Test alarmu' @@ -6315,6 +6576,7 @@ function init() { ,tr: 'Alarm Testi / Akıllı Telefon için Etkin' ,zh_cn: '报警测试/智能手机启用' ,zh_tw: '報警測試/智能手機啟用' + ,hu: 'Figyelmeztetés teszt / Mobiltelefon aktiválása' } ,'Bolus Wizard' : { cs: 'Bolusový kalkulátor' @@ -6341,6 +6603,7 @@ function init() { ,tr: 'Bolus Hesaplayıcısı' ,zh_cn: '大剂量向导' ,zh_tw: '大劑量嚮導' + ,hu: 'Bólus Varázsló' } ,'in the future' : { cs: 'v budoucnosti' @@ -6367,6 +6630,7 @@ function init() { ,tr: 'gelecekte' ,zh_cn: '在未来' ,zh_tw: '在未來' + ,hu: 'a jövőben' } ,'time ago' : { cs: 'min zpět' @@ -6393,6 +6657,7 @@ function init() { ,tr: 'süre önce' //yakın zamanda ,zh_cn: '在过去' ,zh_tw: '在過去' + ,hu: 'idő elött' } ,'hr ago' : { cs: 'hod zpět' @@ -6419,6 +6684,7 @@ function init() { ,tr: 'saat önce' ,zh_cn: '小时前' ,zh_tw: '小時前' + ,hu: 'óra elött' } ,'hrs ago' : { cs: 'hod zpět' @@ -6445,6 +6711,7 @@ function init() { ,tr: 'saat önce' ,zh_cn: '小时前' ,zh_tw: '小時前' + ,hu: 'órája' } ,'min ago' : { cs: 'min zpět' @@ -6464,13 +6731,14 @@ function init() { ,fi: 'minuutti sitten' ,nb: 'minutter siden' ,pl: 'minuta temu' - ,ru: 'мин. назад' + ,ru: 'мин назад' ,sk: 'min. pred' - ,nl: 'm geleden' + ,nl: 'minuut geleden' ,ko: '분 전' ,tr: 'dk. önce' ,zh_cn: '分钟前' ,zh_tw: '分鐘前' + ,hu: 'perce' } ,'mins ago' : { cs: 'min zpět' @@ -6492,11 +6760,12 @@ function init() { ,pl: 'minut temu' ,ru: 'минут назад' ,sk: 'min. pred' - ,nl: 'm geleden' + ,nl: 'minuten geleden' ,ko: '분 전' ,tr: 'dakika önce' ,zh_cn: '分钟前' ,zh_tw: '分鐘前' + ,hu: 'perce' } ,'day ago' : { cs: 'den zpět' @@ -6523,6 +6792,7 @@ function init() { ,tr: 'gün önce' ,zh_cn: '天前' ,zh_tw: '天前' + ,hu: 'napja' } ,'days ago' : { cs: 'dnů zpět' @@ -6549,6 +6819,7 @@ function init() { ,tr: 'günler önce' ,zh_cn: '天前' ,zh_tw: '天前' + ,hu: 'napja' } ,'long ago' : { cs: 'dlouho zpět' @@ -6575,11 +6846,12 @@ function init() { ,tr: 'uzun zaman önce' ,zh_cn: '很长时间前' ,zh_tw: '很長時間前' + ,hu: 'nagyon régen' } ,'Clean' : { cs: 'Čistý' ,he: 'נקה' - ,de: 'Rein' + ,de: 'Löschen' ,es: 'Limpio' ,fr: 'Propre' ,el: 'Καθαρισμός' @@ -6601,6 +6873,7 @@ function init() { ,tr: 'Temiz' ,zh_cn: '无' ,zh_tw: '無' + ,hu: 'Tiszta' } ,'Light' : { cs: 'Lehký' @@ -6627,6 +6900,7 @@ function init() { ,tr: 'Kolay' ,zh_cn: '轻度' ,zh_tw: '輕度' + ,hu: 'Könnyű' } ,'Medium' : { cs: 'Střední' @@ -6653,6 +6927,7 @@ function init() { ,tr: 'Orta' ,zh_cn: '中度' ,zh_tw: '中度' + ,hu: 'Közepes' } ,'Heavy' : { cs: 'Velký' @@ -6679,10 +6954,11 @@ function init() { ,zh_cn: '重度' ,zh_tw: '嚴重' ,he: 'כבד' + ,hu: 'Nehéz' } ,'Treatment type' : { cs: 'Typ ošetření' - ,de: 'Eingabe-Typ' + ,de: 'Behandlungstyp' ,es: 'Tipo de tratamiento' ,fr: 'Type de traitement' ,el: 'Τύπος Ενέργειας' @@ -6704,7 +6980,8 @@ function init() { ,tr: 'Tedavi tipi' ,zh_cn: '操作类型' ,he: 'סוג הטיפול' - } + ,hu: 'Kezelés típusa' + } ,'Raw BG' : { cs: 'Glykémie z RAW dat' ,de: 'Roh-BG' @@ -6727,7 +7004,8 @@ function init() { ,ko: 'Raw 혈당' ,tr: 'Ham KŞ' ,zh_cn: '原始血糖' - } + ,hu: 'Nyers BG' + } ,'Device' : { cs: 'Zařízení' ,de: 'Gerät' @@ -6752,7 +7030,8 @@ function init() { ,tr: 'Cihaz' ,zh_cn: '设备' ,he: 'התקן' - } + ,hu: 'Berendezés' + } ,'Noise' : { cs: 'Šum' ,he: 'רַעַשׁ' @@ -6777,6 +7056,7 @@ function init() { ,ko: '노이즈' ,tr: 'parazit' // gürültü ,zh_cn: '噪声' + ,hu: 'Zavar' } ,'Calibration' : { cs: 'Kalibrace' @@ -6802,6 +7082,7 @@ function init() { ,ko: '보정' ,tr: 'Kalibrasyon' ,zh_cn: '校准' + ,hu: 'Kalibráció' } ,'Show Plugins' : { cs: 'Zobrazuj pluginy' @@ -6826,8 +7107,8 @@ function init() { ,nl: 'Laat Plug-Ins zien' ,ko: '플러그인 보기' ,tr: 'Eklentileri Göster' - ,zh_cn: '显示插件' - ,zh_tw: '顯示插件' + ,zh_cn: '校准' + ,hu: 'Mutasd a kiegészítőket' } ,'About' : { cs: 'O aplikaci' @@ -6854,6 +7135,7 @@ function init() { ,tr: 'Hakkında' ,zh_cn: '关于' ,zh_tw: '關於' + ,hu: 'Az aplikációról' } ,'Value in' : { cs: 'Hodnota v' @@ -6879,6 +7161,7 @@ function init() { ,ko: '값' ,tr: 'Değer cinsinden' ,zh_cn: '数值' + ,hu: 'Érték' } ,'Carb Time' : { cs: 'Čas jídla' @@ -6903,7 +7186,8 @@ function init() { ,nl: 'Koolhydraten tijd' ,ko: '탄수화물 시간' ,tr: 'Karbonhidratların alım zamanı' - ,zh_cn: '碳水时间' + ,zh_cn: '数值' + ,hu: 'Étkezés ideje' } ,'Language' : { cs: 'Jazyk' @@ -6930,6 +7214,7 @@ function init() { ,tr: 'Dil' ,zh_cn: '语言' ,zh_tw: '語言' + ,hu: 'Nyelv' } ,'Add new' : { cs: 'Přidat nový' @@ -6955,6 +7240,7 @@ function init() { ,ja: '新たに加える' ,tr: 'Yeni ekle' ,zh_cn: '新增' + ,hu: 'Új hozzáadása' } ,'g' : { // grams shortcut cs: 'g' @@ -6980,6 +7266,7 @@ function init() { ,tr: 'g' ,zh_cn: '克' ,zh_tw: '克' + ,hu: 'g' } ,'ml' : { // milliliters shortcut cs: 'ml' @@ -7004,7 +7291,8 @@ function init() { ,ja: 'ml' ,tr: 'ml' ,zh_cn: '毫升' - ,zh_tw: '毫升' + ,zh_tw: '克' + ,hu: 'ml' } ,'pcs' : { // pieces shortcut cs: 'ks' @@ -7030,6 +7318,7 @@ function init() { ,tr: 'parça' ,zh_cn: '件' ,zh_tw: '件' + ,hu: 'db' } ,'Drag&drop food here' : { cs: 'Sem táhni & pusť jídlo' @@ -7054,6 +7343,7 @@ function init() { ,tr: 'Yiyecekleri buraya sürükle bırak' ,zh_cn: '拖放食物到这' ,nl: 'Maaltijd naar hier verplaatsen' + ,hu: 'Húzd ide és ereszd el az ételt' } ,'Care Portal' : { cs: 'Portál ošetření' @@ -7078,6 +7368,7 @@ function init() { ,tr: 'Care Portal' ,zh_cn: '服务面板' ,zh_tw: '服務面板' + ,hu: 'Care portál' } ,'Medium/Unknown' : { // GI of food cs: 'Střední/Neznámá' @@ -7102,6 +7393,7 @@ function init() { ,it: 'Media/Sconosciuto' ,tr: 'Orta/Bilinmeyen' ,zh_cn: '中等/不知道' + ,hu: 'Átlagos/Ismeretlen' } ,'IN THE FUTURE' : { cs: 'V BUDOUCNOSTI' @@ -7126,6 +7418,7 @@ function init() { ,it: 'NEL FUTURO' ,tr: 'GELECEKTE' ,zh_cn: '在未来' + ,hu: 'A JÖVŐBEN' } ,'Update' : { // Update button cs: 'Aktualizovat' @@ -7151,6 +7444,7 @@ function init() { ,tr: 'Güncelleştirme' ,zh_cn: '更新认证状态' ,zh_tw: '更新認證狀態' + ,hu: 'Frissítés' } ,'Order' : { cs: 'Pořadí' @@ -7175,6 +7469,7 @@ function init() { ,ko: '순서' ,tr: 'Sıra' ,zh_cn: '排序' + ,hu: 'Sorrend' } ,'oldest on top' : { cs: 'nejstarší nahoře' @@ -7199,7 +7494,8 @@ function init() { ,ko: '오래된 것 부터' ,tr: 'en eski üste' ,zh_cn: '按时间升序排列' - } + ,hu: 'legöregebb a telejére' + } ,'newest on top' : { cs: 'nejnovější nahoře' ,he: 'החדש ביותר למעלה' @@ -7223,6 +7519,7 @@ function init() { ,ko: '새로운 것 부터' ,tr: 'en yeni üste' ,zh_cn: '按时间降序排列' + ,hu: 'legújabb a tetejére' } ,'All sensor events' : { cs: 'Všechny události sensoru' @@ -7248,6 +7545,7 @@ function init() { ,ko: '모든 센서 이벤트' ,tr: 'Tüm sensör olayları' ,zh_cn: '所有探头事件' + ,hu: 'Az összes szenzor esemény' } ,'Remove future items from mongo database' : { cs: 'Odebrání položek v budoucnosti z Mongo databáze' @@ -7273,6 +7571,7 @@ function init() { ,tr: 'Gelecekteki öğeleri mongo veritabanından kaldır' ,zh_cn: '从数据库中清除所有未来条目' ,zh_tw: '從數據庫中清除所有未來條目' + ,hu: 'Töröld az összes jövőben lévő adatot az adatbázisból' } ,'Find and remove treatments in the future' : { cs: 'Najít a odstranit záznamy ošetření v budoucnosti' @@ -7298,6 +7597,7 @@ function init() { ,tr: 'Gelecekte tedavileri bulun ve kaldır' ,zh_cn: '查找并清除所有未来的操作' ,zh_tw: '查找並清除所有未來的操作' + ,hu: 'Töröld az összes kezelést a jövőben az adatbázisból' } ,'This task find and remove treatments in the future.' : { cs: 'Tento úkol najde a odstraní ošetření v budoucnosti.' @@ -7323,6 +7623,7 @@ function init() { ,tr: 'Bu görev gelecekte tedavileri bul ve kaldır.' ,zh_cn: '此功能查找并清除所有未来的操作。' ,zh_tw: '此功能查找並清除所有未來的操作。' + ,hu: 'Ez a feladat megkeresi és eltávolítja az összes jövőben lévő kezelést' } ,'Remove treatments in the future' : { cs: 'Odstraň ošetření v budoucnosti' @@ -7348,6 +7649,7 @@ function init() { ,tr: 'Gelecekte tedavileri kaldır' ,zh_cn: '清除未来操作' ,zh_tw: '清除未來操作' + ,hu: 'Jövőbeli kerelések eltávolítésa' } ,'Find and remove entries in the future' : { cs: 'Najít a odstranit CGM data v budoucnosti' @@ -7366,13 +7668,14 @@ function init() { ,fi: 'Etsi ja poista tapahtumat' ,pl: 'Znajdź i usuń wpisy z przyszłości' ,pt: 'Encontrar e remover entradas futuras' - ,ru: 'Найти и удалить данные с сенсора из будущего' + ,ru: 'Найти и удалить данные сенсора из будущего' ,sk: 'Nájsť a odstrániť CGM dáta v budúcnosti' ,nl: 'Zoek en verwijder behandelingen met datum in de toekomst' ,ko: '미래에 입력을 검색하고 지우세요.' ,tr: 'Gelecekteki girdileri bul ve kaldır' ,zh_cn: '查找并清除所有的未来的记录' ,zh_tw: '查找並清除所有的未來的記錄' + ,hu: 'Jövőbeli bejegyzések eltávolítása' } ,'This task find and remove CGM data in the future created by uploader with wrong date/time.' : { cs: 'Tento úkol najde a odstraní CGM data v budoucnosti vzniklé špatně nastaveným datem v uploaderu.' @@ -7391,13 +7694,14 @@ function init() { ,fi: 'Tämä työkalu etsii ja poistaa sensorimerkinnät joiden aikamerkintä sijaitsee tulevaisuudessa.' ,pl: 'To narzędzie odnajduje i usuwa dane CGM utworzone przez uploader w przyszłości - ze złą datą/czasem.' ,pt: 'Este comando procura e remove dados de sensor futuros criados por um uploader com data ou horário errados.' - ,ru: 'Эта опция найдет и удалит данные с сенсора созданные загрузчиком с неверными датой/временем' + ,ru: 'Эта опция найдет и удалит данные сенсора созданные загрузчиком с неверными датой/временем' ,sk: 'Táto úloha nájde a odstráni CGM dáta v budúcnosti vzniknuté zle nastaveným časom uploaderu.' ,nl: 'Dit commando zoekt en verwijdert behandelingen met datum in de toekomst' ,ko: '이 작업은 잘못된 날짜/시간으로 업로드 되어 생성된 미래의 CGM 데이터를 검색하고 지우는 것입니다.' ,tr: 'Yükleyicinin oluşturduğu gelecekteki CGM verilerinin yanlış tarih/saat olanlarını bul ve kaldır.' ,zh_cn: '此功能查找并清除所有上传时日期时间错误导致生成在未来时间的CGM数据。' ,zh_tw: '此功能查找並清除所有上傳時日期時間錯誤導致生成在未來時間的CGM數據。' + ,hu: 'Ez a feladat megkeresi és eltávolítja az összes CGM adatot amit a feltöltő rossz idővel-dátummal töltött fel' } ,'Remove entries in the future' : { cs: 'Odstraň CGM data v budoucnosti' @@ -7423,6 +7727,7 @@ function init() { ,tr: 'Gelecekteki girdileri kaldır' ,zh_cn: '清除未来记录' ,zh_tw: '清除未來記錄' + ,hu: 'Jövőbeli bejegyzések törlése' } ,'Loading database ...' : { cs: 'Nahrávám databázi ...' @@ -7448,6 +7753,7 @@ function init() { ,tr: 'Veritabanı yükleniyor ...' ,zh_cn: '载入数据库...' ,zh_tw: '載入數據庫...' + ,hu: 'Adatbázis betöltése...' } ,'Database contains %1 future records' : { cs: 'Databáze obsahuje %1 záznamů v budoucnosti' @@ -7473,6 +7779,7 @@ function init() { ,tr: 'Veritabanı %1 gelecekteki girdileri içeriyor' ,zh_cn: '数据库包含%1条未来记录' ,zh_tw: '數據庫包含%1條未來記錄' + ,hu: 'Az adatbázis %1 jövöbeli adatot tartalmaz' } ,'Remove %1 selected records?' : { cs: 'Odstranit %1 vybraných záznamů' @@ -7498,6 +7805,7 @@ function init() { ,tr: 'Seçilen %1 kayıtlar kaldırılsın? ' ,zh_cn: '清除%1条选择的记录?' ,zh_tw: '清除%1條選擇的記錄?' + ,hu: 'Kitöröljük a %1 kiválasztott adatot?' } ,'Error loading database' : { cs: 'Chyba při nahrávání databáze' @@ -7523,6 +7831,7 @@ function init() { ,tr: 'Veritabanını yüklerken hata oluştu' ,zh_cn: '载入数据库错误' ,zh_tw: '載入數據庫錯誤' + ,hu: 'Hiba az adatbázis betöltése közben' } ,'Record %1 removed ...' : { cs: 'Záznam %1 odstraněn ...' @@ -7548,6 +7857,7 @@ function init() { ,tr: '%1 kaydı silindi ...' ,zh_cn: '%1条记录已清除' ,zh_tw: '%1條記錄已清除' + ,hu: 'A %1 bejegyzés törölve...' } ,'Error removing record %1' : { cs: 'Chyba při odstaňování záznamu %1' @@ -7573,6 +7883,7 @@ function init() { ,tr: '%1 kayıt kaldırılırken hata oluştu' ,zh_cn: '%1条记录清除出错' ,zh_tw: '%1條記錄清除出錯' + ,hu: 'Hiba lépett fel a %1 bejegyzés törlése közben' } ,'Deleting records ...' : { cs: 'Odstraňování záznamů ...' @@ -7598,10 +7909,14 @@ function init() { ,tr: 'Kayıtlar siliniyor ...' ,zh_cn: '正在删除记录...' ,zh_tw: '正在刪除記錄...' + ,hu: 'Bejegyzések törlése...' } ,'%1 records deleted' : { hr: 'obrisano %1 zapisa' ,de: '%1 Einträge gelöscht' + , pl: '%1 rekordów zostało usuniętych' + ,ru: '% записей удалено' + ,hu: '%1 bejegyzés törölve' } ,'Clean Mongo status database' : { cs: 'Vyčištění Mongo databáze statusů' @@ -7626,6 +7941,7 @@ function init() { ,ko: 'Mongo 상태 데이터베이스를 지우세요.' ,tr: 'Mongo durum veritabanını temizle' ,zh_cn: '清除状态数据库' + ,hu: 'Mongo állapot (status) adatbázis tisztítása' } ,'Delete all documents from devicestatus collection' : { cs: 'Odstranění všech záznamů z kolekce devicestatus' @@ -7650,6 +7966,7 @@ function init() { ,tr: 'Devicestatus koleksiyonundan tüm dokümanları sil' ,zh_cn: '从设备状态采集删除所有文档' ,nl: 'Verwijder alle documenten uit "devicestatus" database' + ,hu: 'Az összes "devicestatus" dokumentum törlése' } ,'This task removes all documents from devicestatus collection. Useful when uploader battery status is not properly updated.' : { cs: 'Tento úkol odstraní všechny dokumenty z kolekce devicestatus. Je to vhodné udělat, pokud se ukazatel stavu baterie neobnovuje správně.' @@ -7665,7 +7982,7 @@ function init() { ,hr: 'Ovo briše sve zapise o statusima. Korisno kada se status baterije uploadera ne osvježava ispravno.' ,it: 'Questa attività elimina tutti i documenti dalla collezione "devicestatus". Utile quando lo stato della batteria uploader/xdrip non si aggiorna.' ,fi: 'Tämä työkalu poistaa kaikki tiedot statustietokannasta, mikä korjaa tilanteen, jossa puhelimen akun lataustilanne ei näy oikein.' - ,pl: 'To narzędzie usuwa wszystkie dokumenty z kolekcji devicestatus. Potrzebne jest wtedy, gdy status baterii uploadera nie jest aktualizowany' + ,pl: 'To narzędzie usuwa wszystkie dokumenty z kolekcji devicestatus. Przydatne, gdy status baterii uploadera nie jest aktualizowany.' ,pt: 'Este comando remove todos os documentos da coleção devicestatus. Útil quando o status da bateria do uploader não é atualizado corretamente.' ,ru: 'Эта опция удаляет все документы из коллекции статус устройства. Полезно когда состояние батвреи загрузчика не обновляется' ,sk: 'Táto úloha vymaže všetky záznamy z kolekcie "devicestatus". Je to vhodné keď sa stav batérie nezobrazuje správne.' @@ -7673,6 +7990,7 @@ function init() { ,tr: 'Bu görev tüm durumları Devicestatus koleksiyonundan kaldırır. Yükleyici pil durumu güncellenmiyorsa kullanışlıdır.' ,zh_cn: '此功能从设备状态采集中删除所有文档。适用于上传设备电量信息不能正常同步时使用。' ,nl: 'Dit commando verwijdert alle documenten uit "devicestatus" database. Handig wanneer de batterij status niet correct wordt geupload.' + ,hu: 'Ez a feladat kitörli az összes "devicestatus" dokumentumot. Hasznos ha a feltöltő elem állapota nem jelenik meg helyesen.' } ,'Delete all documents' : { cs: 'Odstranit všechny dokumenty' @@ -7691,12 +8009,13 @@ function init() { ,fi: 'Poista kaikki tiedot' ,pl: 'Usuń wszystkie dokumenty' ,pt: 'Apagar todos os documentos' - ,ru: 'Стереть все документы' + ,ru: 'Удалить все документы' ,sk: 'Zmazať všetky záznamy' ,nl: 'Verwijder alle documenten' ,ko: '모든 문서들을 지우세요' ,tr: 'Tüm Belgeleri sil' ,zh_cn: '删除所有文档' + ,hu: 'Az összes dokumentum törlése' } ,'Delete all documents from devicestatus collection?' : { cs: 'Odstranit všechny dokumenty z kolekce devicestatus?' @@ -7715,12 +8034,13 @@ function init() { ,fi: 'Poista tiedot statustietokannasta?' ,pl: 'Czy na pewno usunąć wszystkie dokumenty z kolekcji devicestatus?' ,pt: 'Apagar todos os documentos da coleção devicestatus?' - ,ru: 'Стереть все документы коллекции статус устройства?' + ,ru: 'Удалить все документы коллекции статус устройства?' ,sk: 'Zmazať všetky záznamy z kolekcie "devicestatus"?' ,ko: 'devicestatus 수집의 모든 문서들을 지우세요.' ,tr: 'Tüm Devicestatus koleksiyon belgeleri silinsin mi?' ,zh_cn: '从设备状态采集删除所有文档?' ,nl: 'Wil je alle data van "devicestatus" database verwijderen?' + ,hu: 'Az összes dokumentum törlése a "devicestatus" gyűjteményből?' } ,'Database contains %1 records' : { cs: 'Databáze obsahuje %1 záznamů' @@ -7745,6 +8065,7 @@ function init() { ,ko: '데이터베이스는 %1 기록을 포함합니다.' ,tr: 'Veritabanı %1 kayıt içeriyor' ,zh_cn: '数据库包含%1条记录' + ,hu: 'Az adatbázis %1 bejegyzést tartalmaz' } ,'All records removed ...' : { cs: 'Všechny záznamy odstraněny ...' @@ -7769,72 +8090,113 @@ function init() { ,ko: '모든 기록들이 지워졌습니다.' ,tr: 'Tüm kayıtlar kaldırıldı ...' ,zh_cn: '所有记录已经被清除' + ,hu: 'Az összes bejegyzés törölve...' } ,'Delete all documents from devicestatus collection older than 30 days' : { hr: 'Obriši sve statuse starije od 30 dana' - ,ru: 'Удалить все записи коллекции devicestatus' + ,ru: 'Удалить все записи коллекции devicestatus старше 30 дней' ,de: 'Alle Dokumente der Gerätestatus-Sammlung löschen, die älter als 30 Tage sind' + , pl: 'Usuń wszystkie dokumenty z kolekcji devicestatus starsze niż 30 dni' + , hu: 'Az összes "devicestatus" dokumentum törlése ami 30 napnál öregebb' } ,'Number of Days to Keep:' : { hr: 'Broj dana za sačuvati:' ,ru: 'Оставить дней' ,de: 'Daten löschen, die älter sind (in Tagen) als:' + , pl: 'Ilość dni do zachowania:' + , hu: 'Mentés ennyi napra:' } ,'This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.' : { hr: 'Ovo uklanja sve statuse starije od 30 dana. Korisno kada se status baterije uploadera ne osvježava ispravno.' + , pl: 'To narzędzie usuwa wszystkie dokumenty z kolekcji devicestatus starsze niż 30 dni. Przydatne, gdy status baterii uploadera nie jest aktualizowany.' ,ru: 'Это удалит все документы коллекции devicestatus которым более 30 дней. Полезно, когда статус батареи не обновляется или обновляется неверно.' ,de: 'Diese Aufgabe entfernt alle Dokumente aus der Gerätestatus-Sammlung, die älter sind als 30 Tage. Nützlich wenn der Uploader-Batteriestatus sich nicht aktualisiert.' + ,hu: 'Ez a feladat törli az összes "devicestatus" dokumentumot a gyűjteményből ami 30 napnál öregebb. Hasznos ha a feltöltő elem állapota nem jelenik meg rendesen. ' } ,'Delete old documents from devicestatus collection?' : { hr: 'Obriši stare statuse' ,de: 'Alte Dokumente aus der Gerätestatus-Sammlung entfernen?' - + , pl: 'Czy na pewno chcesz usunąć stare dokumenty z kolekcji devicestatus?' + ,ru: 'Удалить старыые документы коллекции devicestatus' + ,hu: 'Kitorli az öreg dokumentumokat a "devicestatus" gyűjteményből?' } ,'Clean Mongo entries (glucose entries) database' : { hr: 'Obriši GUK zapise iz baze' ,de: 'Mongo-Einträge (Glukose-Einträge) Datenbank bereinigen' + , pl: 'Wyczyść bazę wpisów (wpisy glukozy) Mongo' + ,ru: 'Очистить записи данных в базе Mongo' + ,hu: 'Mongo bejegyzés adatbázis tisztítása' } ,'Delete all documents from entries collection older than 180 days' : { hr: 'Obriši sve zapise starije od 180 dana' ,de: 'Alle Dokumente aus der Einträge-Sammlung löschen, die älter sind als 180 Tage' + , pl: 'Usuń wszystkie dokumenty z kolekcji wpisów starsze niż 180 dni' + ,ru: 'Удалить все документы коллекции entries старше 180 дней ' + ,hu: 'Az összes bejegyzés gyűjtemény törlése ami 180 napnál öregebb' } ,'This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.' : { hr: 'Ovo briše sve zapise starije od 180 dana. Korisno kada se status baterije uploadera ne osvježava.' ,de: 'Diese Aufgabe entfernt alle Dokumente aus der Einträge-Sammlung, die älter sind als 180 Tage. Nützlich wenn der Uploader-Batteriestatus sich nicht aktualisiert.' + , pl: 'To narzędzie usuwa wszystkie dokumenty z kolekcji wpisów starsze niż 180 dni. Przydatne, gdy status baterii uploadera nie jest aktualizowany.' + ,ru: 'Это удалит все документы коллекции entries старше 180 дней. Полезно, когда статус батареи загрузчика должным образом не обновляется' + ,hu: 'A feladat kitörli az összes bejegyzésekből álló dokumentumot ami 180 napnál öregebb. Hasznos ha a feltöltő elem állapota nem jelenik meg helyesen.' } ,'Delete old documents' : { hr: 'Obriši stare zapise' ,de: 'Alte Dokumente löschen' + , pl: 'Usuń stare dokumenty' + ,ru: 'Удалить старые документы' + ,hu: 'Öreg dokumentumok törlése' } ,'Delete old documents from entries collection?' : { hr: 'Obriši stare zapise?' ,de: 'Alte Dokumente aus der Einträge-Sammlung entfernen?' + , pl: 'Czy na pewno chcesz usunąć stare dokumenty z kolekcji wpisów?' + ,ru: 'Удалить старые документы коллекции entries?' + ,hu: 'Az öreg dokumentumok törlése a bejegyzések gyűjteményéből?' } ,'%1 is not a valid number' : { hr: '%1 nije valjan broj' ,de: '%1 ist keine gültige Zahl' ,he: 'זה לא מיספר %1' + , pl: '%1 nie jest poprawną liczbą' + ,ru: '% не является допустимым значением' + ,hu: 'A %1 nem érvényes szám' } ,'%1 is not a valid number - must be more than 2' : { hr: '%1 nije valjan broj - mora biti veći od 2' ,de: '%1 ist keine gültige Zahl - Eingabe muss größer als 2 sein' + , pl: '%1 nie jest poprawną liczbą - musi być większe od 2' + ,ru: '% не является допустимым значением - должно быть больше 2' + ,hu: 'A %1 nem érvényes szám - nagyobb számnak kell lennie mint a 2' } ,'Clean Mongo treatments database' : { hr: 'Obriši tretmane iz baze' ,de: 'Mongo-Behandlungsdatenbank bereinigen' + , pl: 'Wyczyść bazę leczenia Mongo' + ,ru: 'Очистить базу лечения Mongo' + ,hu: 'Mondo kezelési datbázisának törlése' } ,'Delete all documents from treatments collection older than 180 days' : { hr: 'Obriši tretmane starije od 180 dana iz baze' ,de: 'Alle Dokumente aus der Behandlungs-Sammlung löschen, die älter sind als 180 Tage' + , pl: 'Usuń wszystkie dokumenty z kolekcji leczenia starsze niż 180 dni' + ,ru: 'Удалить все документы коллекции treatments старше 180 дней' + ,hu: 'Töröld az összes 180 napnál öregebb kezelési dokumentumot' } ,'This task removes all documents from treatments collection that are older than 180 days. Useful when uploader battery status is not properly updated.' : { hr: 'Ovo briše sve tretmane starije od 180 dana iz baze. Korisno kada se status baterije uploadera ne osvježava.' ,de: 'Diese Aufgabe entfernt alle Dokumente aus der Behandlungs-Sammlung, die älter sind als 180 Tage. Nützlich wenn der Uploader-Batteriestatus sich nicht aktualisiert.' + , pl: 'To narzędzie usuwa wszystkie dokumenty z kolekcji leczenia starsze niż 180 dni. Przydatne, gdy status baterii uploadera nie jest aktualizowany.' + ,ru: 'Это удалит все документы коллекции treatments старше 180 дней. Полезно, когда статус батареи загрузчика не обновляется должным образом' + ,hu: 'A feladat eltávolítja az összes kezelési dokumentumot ami öregebb 180 napnál. Hasznos ha a feltöltő elem állapota nem jelenik meg helyesen.' } ,'Delete old documents from treatments collection?' : { hr: 'Obriši stare tretmane?' - ,ru: 'Удалить старые документы из коллекции лечения?' + ,ru: 'Удалить старые документы из коллекции treatments?' ,de: 'Alte Dokumente aus der Behandlungs-Sammlung entfernen?' + , pl: 'Czy na pewno chcesz usunąć stare dokumenty z kolekcji leczenia?' + , hu: 'Törölni az összes doumentumot a kezelési gyűjteményből?' } ,'Admin Tools' : { cs: 'Nástroje pro správu' @@ -7861,6 +8223,7 @@ function init() { ,tr: 'Yönetici araçları' ,zh_cn: '管理工具' ,zh_tw: '管理工具' + ,hu: 'Adminisztrációs eszközök' } ,'Nightscout reporting' : { cs: 'Nightscout - Výkazy' @@ -7885,6 +8248,7 @@ function init() { ,ko: 'Nightscout 보고서' ,tr: 'NightScout raporları' ,zh_cn: 'Nightscout报表生成器' + ,hu: 'Nightscout jelentések' } ,'Cancel' : { cs: 'Zrušit' @@ -7910,6 +8274,7 @@ function init() { ,ko: '취소' ,tr: 'İptal' ,zh_cn: '取消' + ,hu: 'Vissza' } ,'Edit treatment' : { cs: 'Upravit ošetření' @@ -7934,6 +8299,7 @@ function init() { ,ko: 'Treatments 편집' ,tr: 'Tedaviyi düzenle' ,zh_cn: '编辑操作' + ,hu: 'Kezelés szerkesztése' } ,'Duration' : { cs: 'Doba trvání' @@ -7958,6 +8324,7 @@ function init() { ,ko: '기간' ,tr: 'süre' ,zh_cn: '持续' + ,hu: 'Behelyezés óta eltelt idő' } ,'Duration in minutes' : { cs: 'Doba trvání v minutách' @@ -7982,6 +8349,7 @@ function init() { ,ko: '분당 지속 기간' ,tr: 'Süre dakika cinsinden' ,zh_cn: '持续时间(分钟)' + ,hu: 'Idő percekben' } ,'Temp Basal' : { cs: 'Dočasný bazál' @@ -8005,6 +8373,7 @@ function init() { ,ko: '임시 basal' ,tr: 'Geçici Bazal Oranı' ,zh_cn: '临时基础率' + ,hu: 'Átmeneti bazál' } ,'Temp Basal Start' : { cs: 'Dočasný bazál začátek' @@ -8028,6 +8397,7 @@ function init() { ,ko: '임시 basal 시작' ,tr: 'Geçici Bazal Oranını Başlanğıcı' ,zh_cn: '临时基础率开始' + ,hu: 'Átmeneti bazál Kezdete' } ,'Temp Basal End' : { cs: 'Dočasný bazál konec' @@ -8051,6 +8421,7 @@ function init() { ,ko: '임시 basal 종료' ,tr: 'Geçici bazal oranını Bitişi' ,zh_cn: '临时基础率结束' + ,hu: 'Átmeneti bazál Vége' } ,'Percent' : { // value in % for temp basal cs: 'Procenta' @@ -8075,6 +8446,7 @@ function init() { ,ko: '퍼센트' ,tr: 'Yüzde' ,zh_cn: '百分比' + ,hu: 'Százalék' } ,'Basal change in %' : { cs: 'Změna bazálu v %' @@ -8098,6 +8470,7 @@ function init() { ,ko: '% 이내의 basal 변경' ,tr: 'Bazal değişimi % cinsinden' ,zh_cn: '基础率变化百分比' + ,hu: 'Bazál változása %' } ,'Basal value' : { // absolute value for temp basal cs: 'Hodnota bazálu' @@ -8115,12 +8488,13 @@ function init() { ,fi: 'Basaalin määrä' ,pl: 'Dawka podstawowa' ,pt: 'Valor da basal' - ,ru: 'величина временного базалал' + ,ru: 'величина временного базала' ,sk: 'Hodnota bazálu' ,nl: 'Basaal snelheid' ,ko: 'Basal' ,tr: 'Bazal değeri' ,zh_cn: '基础率值' + ,hu: 'Bazál értéke' } ,'Absolute basal value' : { cs: 'Hodnota bazálu' @@ -8144,6 +8518,7 @@ function init() { ,ko: '절대적인 basal' ,tr: 'Mutlak bazal değeri' ,zh_cn: '绝对基础率值' + ,hu: 'Abszolút bazál érték' } ,'Announcement' : { cs: 'Oznámení' @@ -8168,6 +8543,7 @@ function init() { ,ko: '공지' ,tr: 'Duyuru' ,zh_cn: '通告' + ,hu: 'Közlemény' } ,'Loading temp basal data' : { cs: 'Nahrávám dočasné bazály' @@ -8191,6 +8567,7 @@ function init() { ,ko: '임시 basal 로딩' ,tr: 'Geçici bazal verileri yükleniyor' ,zh_cn: '载入临时基础率数据' + ,hu: 'Az étmeneti bazál adatainak betöltése' } ,'Save current record before changing to new?' : { cs: 'Uložit současný záznam před změnou na nový?' @@ -8215,6 +8592,7 @@ function init() { ,it: 'Salvare i dati correnti prima di cambiarli?' ,tr: 'Yenisine geçmeden önce mevcut girişleri kaydet?' ,zh_cn: '在修改至新值前保存当前记录?' + ,hu: 'Elmentsem az aktuális adatokat mielőtt újra váltunk?' } ,'Profile Switch' : { cs: 'Přepnutí profilu' @@ -8239,6 +8617,7 @@ function init() { ,it: 'Cambio profilo' ,tr: 'Profil Değiştir' ,zh_cn: '切换配置文件' + ,hu: 'Profil csere' } ,'Profile' : { cs: 'Profil' @@ -8263,6 +8642,7 @@ function init() { ,ko: '프로파일' ,tr: 'Profil' ,zh_cn: '配置文件' + ,hu: 'Profil' } ,'General profile settings' : { cs: 'Obecná nastavení profilu' @@ -8287,6 +8667,7 @@ function init() { ,it: 'Impostazioni generali profilo' ,tr: 'Genel profil ayarları' ,zh_cn: '通用配置文件设置' + ,hu: 'Általános profil beállítások' } ,'Title' : { cs: 'Název' @@ -8304,13 +8685,14 @@ function init() { ,hr: 'Naslov' ,pl: 'Nazwa' ,pt: 'Título' - ,ru: 'Наименование' + ,ru: 'Название' ,sk: 'Názov' ,nl: 'Titel' ,ko: '제목' ,it: 'Titolo' ,tr: 'Başlık' ,zh_cn: '标题' + ,hu: 'Elnevezés' } ,'Database records' : { cs: 'Záznamy v databázi' @@ -8335,6 +8717,7 @@ function init() { ,tr: 'Veritabanı kayıtları' ,zh_cn: '数据库记录' ,nl: 'Database gegevens' + ,hu: 'Adatbázis bejegyzések' } ,'Add new record' : { cs: 'Přidat nový záznam' @@ -8360,6 +8743,7 @@ function init() { ,ja: '新しい記録を加える' ,tr: 'Yeni kayıt ekle' ,zh_cn: '新增记录' + ,hu: 'Új bejegyzés hozzáadása' } ,'Remove this record' : { cs: 'Vymazat tento záznam' @@ -8385,6 +8769,7 @@ function init() { ,ja: 'この記録を除く' ,tr: 'Bu kaydı kaldır' ,zh_cn: '删除记录' + ,hu: 'Bejegyzés törlése' } ,'Clone this record to new' : { cs: 'Zkopíruj tento záznam do nového' @@ -8409,6 +8794,7 @@ function init() { ,it: 'Clona questo record in uno nuovo' ,tr: 'Bu kaydı yeniden kopyala' ,zh_cn: '复制记录' + ,hu: 'A kiválasztott bejegyzés másolása' } ,'Record valid from' : { cs: 'Záznam platný od' @@ -8433,6 +8819,7 @@ function init() { ,it: 'Record valido da' ,tr: 'Kayıt itibaren geçerli' ,zh_cn: '有效记录,从' + ,hu: 'Bejegyzés érvényessége' } ,'Stored profiles' : { cs: 'Uložené profily' @@ -8457,6 +8844,7 @@ function init() { ,it: 'Profili salvati' ,tr: 'Kaydedilmiş profiller' //Kayıtlı profiller,Saklanan profiller ,zh_cn: '配置文件已存储' + ,hu: 'Tárolt profilok' } ,'Timezone' : { cs: 'Časová zóna' @@ -8481,6 +8869,7 @@ function init() { ,it: 'Fuso orario' ,tr: 'Saat dilimi' ,zh_cn: '时区' + ,hu: 'Időzóna' } ,'Duration of Insulin Activity (DIA)' : { cs: 'Doba působnosti inzulínu (DIA)' @@ -8505,6 +8894,7 @@ function init() { ,it: 'Durata Attività Insulinica (DIA)' ,tr: 'İnsülin Etki Süresi (DIA)' ,zh_cn: '胰岛素作用时间(DIA)' + ,hu: 'Inzulin aktivitás időtartalma' } ,'Represents the typical duration over which insulin takes effect. Varies per patient and per insulin type. Typically 3-4 hours for most pumped insulin and most patients. Sometimes also called insulin lifetime.' : { cs: 'Představuje typickou dobu, po kterou inzulín působí. Bývá různá podle pacienta a inzulínu. Typicky 3-4 hodiny pro pacienty s pumpou.' @@ -8522,13 +8912,14 @@ function init() { ,hr: 'Predstavlja uobičajeno trajanje djelovanje inzulina. Varira po vrstama inzulina i osobama. Tipično je to 3-4 sata za inzuline u pumpama za većinu osoba. Ponekad se naziva i vijek inzulina' ,pl: 'Odzwierciedla czas działania insuliny. Może różnić się w zależności od chorego i rodzaju insuliny. Zwykle są to 3-4 godziny dla insuliny podawanej pompą u większości chorych. Inna nazwa to czas trwania insuliny.' ,pt: 'Representa a tempo típico durante o qual a insulina tem efeito. Varia de acordo com o paciente e tipo de insulina. Tipicamente 3-4 horas para a maioria das insulinas usadas em bombas e dos pacientes. Algumas vezes chamada de tempo de vida da insulina' - ,ru: 'Представляет типичную продолжительность действия инсулина. Зависит от пациента и от типа инсулина. Обычно 3-4 часа для большинства помповых инсулинов и большинства пациентов' + ,ru: 'Отражает типичную продолжительность действия инсулина. Зависит от пациента и от типа инсулина. Обычно 3-4 часа для большинства помповых инсулинов и большинства пациентов' ,sk: 'Predstavuje typickú dobu počas ktorej inzulín pôsobí. Býva rôzna od pacienta a od typu inzulínu. Zvyčajne sa pohybuje medzi 3-4 hodinami u pacienta s pumpou.' ,nl: 'Geeft de werkingsduur van de insuline in het lichaam aan. Dit verschilt van patient tot patient er per soort insuline, algemeen gemiddelde is 3 tot 4 uur. ' ,ko: '인슐린이 작용하는 지속시간을 나타냅니다. 사람마다 그리고 인슐린 종류에 따라 다르고 일반적으로 3~4시간간 동안 지속되며 인슐린 작용 시간(Insulin lifetime)이라고 불리기도 합니다.' ,it: 'Rappresenta la durata tipica nel quale l\'insulina ha effetto. Varia in base al paziente ed al tipo d\'insulina. Tipicamente 3-4 ore per la maggior parte dei microinfusori e dei pazienti. Chiamata anche durata d\'azione insulinica.' ,tr: 'İnsülinin etki ettiği tipik süreye karşılık gelir. Hastaya ve insülin tipine göre değişir. Çoğu pompa insülini ve çoğu hasta için genellikle 3-4 saattir. Bazen de insülin etki süresi de denir.' ,zh_cn: '体现典型的胰岛素活性持续时间。 通过百分比和胰岛素类型体现。对于大多数胰岛素和患者来说是3至4个小时。也称为胰岛素生命周期。' + ,hu: 'Kimutatja hogy általában meddig hat az inzulin. Változó különböző pácienseknél és inzulinoknál. Általában 3-4 óra között mozog. Néha inzulin élettartalomnak is nevezik.' } ,'Insulin to carb ratio (I:C)' : { cs: 'Inzulíno-sacharidový poměr (I:C).' @@ -8553,6 +8944,7 @@ function init() { ,it: 'Rapporto Insulina-Carboidrati (I:C)' ,tr: 'İnsülin/Karbonhidrat oranı (I:C)' ,zh_cn: '碳水化合物系数(ICR)' + ,hu: 'Inzulin-szénhidrát arány' } ,'Hours:' : { cs: 'Hodin:' @@ -8577,6 +8969,7 @@ function init() { ,it: 'Ore:' ,tr: 'Saat:' ,zh_cn: '小时:' + ,hu: 'Óra:' } ,'hours' : { cs: 'hodin' @@ -8601,6 +8994,7 @@ function init() { ,it: 'ore' ,tr: 'saat' ,zh_cn: '小时' + ,hu: 'óra' } ,'g/hour' : { cs: 'g/hod' @@ -8624,6 +9018,7 @@ function init() { ,it: 'g/ora' ,tr: 'g/saat' ,zh_cn: 'g/小时' + ,hu: 'g/óra' } ,'g carbs per U insulin. The ratio of how many grams of carbohydrates are offset by each U of insulin.' : { cs: 'gramy na jednotku inzulínu. Poměr, jaké množství sacharidů pokryje jednotku inzulínu.' @@ -8648,6 +9043,7 @@ function init() { ,tr: 'İnsülin ünite başına g karbonhidrat. İnsülin ünite başına kaç gram karbonhidrat tüketildiği oranıdır.' ,zh_cn: '克碳水每单位胰岛素。每单位胰岛素可以抵消的碳水化合物克值比例。' ,nl: 'G KH per Eh insuline. De verhouding tussen hoeveel grammen koohlhydraten er verwerkt kunnen worden per eenheid insuline.' + ,hu: 'g szénhidrát per egység inzulin. Az arány, hogy hány gramm szénhidrát fed le bizonyos egységnyi inzulint' } ,'Insulin Sensitivity Factor (ISF)' : { cs: 'Citlivost inzulínu (ISF)' @@ -8672,6 +9068,7 @@ function init() { ,it: 'Fattore di Sensibilità Insulinica (ISF)' ,tr: '(ISF) İnsülin Duyarlılık Faktörü' ,zh_cn: '胰岛素敏感系数(ISF)' + ,hu: 'Inzulin Érzékenységi Faktor (ISF)' } ,'mg/dL or mmol/L per U insulin. The ratio of how much BG changes with each U of corrective insulin.' : { cs: 'mg/dL nebo mmol/L na jednotku inzulínu. Poměr, jak se změní glykémie po podaní jednotky inzulínu' @@ -8696,6 +9093,7 @@ function init() { ,it: 'mg/dL o mmol/L per U insulina. Il rapporto di quanto la glicemia varia per ogni U di correzione insulinica.' ,tr: 'Ünite insülin başına mg/dL veya mmol/L. Her bir Ünite düzeltme insülin ile KŞ\'nin ne kadar değiştiğini gösteren orandır.' ,zh_cn: 'mg/dL或mmol/L每单位胰岛素。每单位输入胰岛素导致血糖变化的比例' + ,hu: 'mg/dL vagy mmol/L per inzulin egység. Az aránya annak hogy mennyire változik a cukorszint bizonyos egység inzulintól' } ,'Carbs activity / absorption rate' : { cs: 'Rychlost absorbce sacharidů' @@ -8720,8 +9118,9 @@ function init() { ,it: 'Attività carboidrati / Velocità di assorbimento' ,tr: 'Karbonhidrat aktivitesi / emilim oranı' ,zh_cn: '碳水化合物活性/吸收率' + ,hu: 'Szénhidrátok felszívódásának gyorsasága' } - ,'grams peUr unit time. Represents both the change in COB per unit of time, as well as the amount of carbs that should take effect over that time. Carb absorption / activity curves are less well understood than insulin activity, but can be approximated using an initial delay followed by a constant rate of absorption (g/hr).' : { + ,'grams per unit time. Represents both the change in COB per unit of time, as well as the amount of carbs that should take effect over that time. Carb absorption / activity curves are less well understood than insulin activity, but can be approximated using an initial delay followed by a constant rate of absorption (g/hr).' : { cs: 'gramy za jednotku času. Reprezentuje jak změnu COB za jednoku času, tak množství sacharidů, které se za tu dobu projevily. Křivka absorbce sacharidů je mnohem méně pochopitelná než IOB, ale může být aproximována počáteční pauzou následovanou konstantní hodnotou absorbce (g/hod).' ,he: 'גרם ליחידת זמן. מייצג הן את השינוי בפחמימות ליחידת זמן והן את כמות הפחמימות אשר אמורות להיכנס לתוקף במהלך אותה תקופה. ספיגת הפחמימות / פעילות הם פחות מובן מאשר פעילות האינסולין, אך ניתן להתקרב באמצעות עיכוב ראשוני ואחריו שיעור קבוע של קליטה (g / hr) ' ,el: 'Γραμμάρια ανά μονάδα χρόνου. Αναπαριστά τόσο την μεταβολή του COB στη μονάδα του χρόνου. Οι καμπύλες της απορρόφησης υδατανθράκων και της άσκησης δεν έχουν κατανοηθεί πλήρως από την επιστημονική κοινότητα, αλλά μπορούν να προσεγγιστούν βάζοντας μία αρχική καθυστέρηση ακολουθούμενη από έναν σταθερό ρυθμό απορρόφησης (g/hr).' @@ -8744,6 +9143,7 @@ function init() { ,tr: 'Ur birim zaman başına gram. Birim zamanda (COB) Aktif Krabonhidratdaki değişimin yanı sıra o zaman üzerinde etki etmesi gereken karbonhidrat miktarını ifade eder. Karbonhidrat emme/aktivite eğrileri, insülin aktivitesinden daha zor anlaşılmaktadır, ancak bir başlangıç gecikmesi ve ardından sabit bir emilim oranı (g/hr) kullanılarak yaklaşık olarak tahmin edilebilmektedir.' ,zh_cn: '克每单位时间。表示每单位时间COB(活性碳水化合物)的变化,以及在该时间应该生效的碳水化合物的量。碳水化合物活性/吸收曲线比胰岛素活性难理解,但可以使用初始延迟,接着恒定吸收速率(克/小时)来近似模拟。' ,nl: 'grammen per tijdseenheid. Geeft de wijzigingen in COB per tijdseenheid alsookde hoeveelheid KH dat impact zou moeten hebben over deze tijdspanne. KH absorbtie / activiteits curveszijn minder eenvoudig uitzetbaar, maar kunnen geschat worden door gebruik te maken van een startvertreging en daarna een constante curve van absorbtie (g/u).' + ,hu: 'gramm per idő egység. Kifejezi a COB változását es a szénhidrátok felszívódását bizonyos idő elteltével. A szénhidrát felszívódásának tengelye nehezebben értelmezhető mint az inzulin aktivitás (IOB), de hasonló lehet a kezdeti késedelemhez és a felszívódáshoz (g/óra). ' } ,'Basal rates [unit/hour]' : { cs: 'Bazály [U/hod].' @@ -8761,13 +9161,14 @@ function init() { ,hr: 'Bazali [jedinica/sat]' ,pl: 'Dawka podstawowa [j/h]' ,pt: 'Taxas de basal [unidades/hora]' - ,ru: 'Базал ед/час' + ,ru: 'Базал [unit/hour]' ,sk: 'Bazál [U/hod]' ,nl: 'Basaal snelheid [eenheden/uur]' ,ko: 'Basal 비율[unit/hour]' ,it: 'Basale [unità/ora]' ,tr: 'Bazal oranı [ünite/saat]' ,zh_cn: '基础率 [U/小时]' + ,hu: 'Bazál [egység/óra]' } ,'Target BG range [mg/dL,mmol/L]' : { cs: 'Cílový rozsah glykémií [mg/dL,mmol/L]' @@ -8792,6 +9193,7 @@ function init() { ,it: 'Obiettivo d\'intervallo glicemico [mg/dL,mmol/L]' ,tr: 'Hedef KŞ aralığı [mg / dL, mmol / L]' ,zh_cn: '目标血糖范围 [mg/dL,mmol/L]' + ,hu: 'Cukorszint választott tartomány [mg/dL,mmol/L]' } ,'Start of record validity' : { cs: 'Začátek platnosti záznamu' @@ -8816,6 +9218,7 @@ function init() { ,it: 'Inizio di validità del dato' ,tr: 'Kayıt geçerliliği başlangıcı' ,zh_cn: '有效记录开始' + ,hu: 'Bejegyzés kezdetének érvényessége' } ,'Icicle' : { cs: 'Rampouch' @@ -8827,7 +9230,7 @@ function init() { ,es: 'Inverso' ,ro: 'Țurțure' ,sv: 'Istapp' - ,nb: 'Isfjell' + ,nb: 'Istapp' ,fi: 'Jääpuikko' ,bg: 'Висящ' ,hr: 'Padajuće' @@ -8840,6 +9243,7 @@ function init() { ,tr: 'Buzsaçağı' //Sarkıt ,zh_cn: 'Icicle' ,zh_tw: 'Icicle' + ,hu: 'Inverzió' } ,'Render Basal' : { cs: 'Zobrazení bazálu' @@ -8858,13 +9262,14 @@ function init() { ,hr: 'Iscrtaj bazale' ,pl: 'Zmiana dawki bazowej' ,pt: 'Renderizar basal' - ,ru: 'отрисовать базал' + ,ru: 'Отображать базал' ,sk: 'Zobrazenie bazálu' ,nl: 'Toon basaal' ,ko: 'Basal 사용하기' ,tr: 'Bazal Grafik' ,zh_cn: '使用基础率' ,zh_tw: '使用基礎率' + ,hu: 'Bazál megjelenítése' } ,'Profile used' : { cs: 'Použitý profil' @@ -8889,6 +9294,7 @@ function init() { ,it: 'Profilo usato' ,tr: 'Kullanılan profil' ,zh_cn: '配置文件已使用' + ,hu: 'Használatban lévő profil' } ,'Calculation is in target range.' : { cs: 'Kalkulace je v cílovém rozsahu.' @@ -8906,13 +9312,14 @@ function init() { ,hr: 'Izračun je u ciljanom rasponu.' ,pl: 'Obliczenie mieści się w zakresie docelowym' ,pt: 'O cálculo está dentro da meta' - ,ru: 'Расчет в целевом диапазоне ' + ,ru: 'Расчет в целевом диапазоне' ,sk: 'Výpočet je v cieľovom rozsahu.' ,nl: 'Berekening valt binnen doelwaards' ,ko: '계산은 목표 범위 안에 있습니다.' ,it: 'Calcolo all\'interno dell\'intervallo' ,tr: 'Hesaplama hedef aralıktadır.' ,zh_cn: '预计在目标范围内' + ,hu: 'A számítás a cél tartományban található' } ,'Loading profile records ...' : { cs: 'Nahrávám profily ...' @@ -8937,6 +9344,7 @@ function init() { ,it: 'Caricamento dati del profilo ...' ,tr: 'Profil kayıtları yükleniyor ...' ,zh_cn: '载入配置文件记录...' + ,hu: 'Profil bejegyzéseinek betöltése...' } ,'Values loaded.' : { cs: 'Data nahrána.' @@ -8961,6 +9369,7 @@ function init() { ,it: 'Valori caricati.' ,tr: 'Değerler yüklendi.' ,zh_cn: '已载入数值' + ,hu: 'Értékek betöltése.' } ,'Default values used.' : { cs: 'Použity výchozí hodnoty.' @@ -8985,6 +9394,7 @@ function init() { ,it: 'Valori standard usati.' ,tr: 'Varsayılan değerler kullanıldı.' ,zh_cn: '已使用默认值' + ,hu: 'Alap értékek használva.' } ,'Error. Default values used.' : { cs: 'CHYBA: Použity výchozí hodnoty.' @@ -9009,6 +9419,7 @@ function init() { ,it: 'Errore. Valori standard usati.' ,tr: 'Hata. Varsayılan değerler kullanıldı.' ,zh_cn: '错误,已使用默认值' + ,hu: 'Hiba: Alap értékek használva' } ,'Time ranges of target_low and target_high don\'t match. Values are restored to defaults.' : { cs: 'Rozsahy časů pro limity glykémií si neodpovídají. Budou nastaveny výchozí hodnoty.' @@ -9026,13 +9437,14 @@ function init() { ,hr: 'Vremenski rasponi donje ciljane i gornje ciljane vrijednosti nisu ispravni. Vrijednosti vraćene na zadano.' ,pl: 'Zakres czasu w docelowo niskim i wysokim przedziale nie są dopasowane. Przywrócono wartości domyślne' ,pt: 'Os intervalos de tempo da meta inferior e da meta superior não conferem. Os valores padrão serão restaurados.' - ,ru: 'Диапазон времени нижних и верхних целевых значений не совпадают. Восстановлены значения по умолчанию' + ,ru: 'Диапазоны времени нижних и верхних целевых значений не совпадают. Восстановлены значения по умолчанию' ,sk: 'Časové rozsahy pre cieľové glykémie sa nezhodujú. Hodnoty nastavené na východzie.' ,ko: '설정한 저혈당과 고혈당의 시간 범위와 일치하지 않습니다. 값은 초기 설정값으로 다시 저장 될 것입니다.' ,it: 'Intervalli di tempo della glicemia obiettivo inferiore e superiore non corretti. Valori ripristinati a quelli standard.' ,nl: 'Tijdspanne van laag en hoog doel zijn niet correct. Standaard waarden worden gebruikt' ,tr: 'Target_low ve target_high öğelerinin zaman aralıkları eşleşmiyor. Değerler varsayılanlara geri yüklendi.' ,zh_cn: '时间范围内的目标高低血糖值不匹配。已恢复使用默认值。' + ,hu: 'A cukorszint-cél időtartománya nem egyezik. Visszaállítás az alapértékekre' } ,'Valid from:' : { cs: 'Platné od:' @@ -9057,6 +9469,7 @@ function init() { ,it: 'Valido da:' ,tr: 'Tarihinden itibaren geçerli' ,zh_cn: '生效从:' + ,hu: 'Érvényes:' } ,'Save current record before switching to new?' : { cs: 'Uložit současný záznam před přepnutím na nový?' @@ -9081,7 +9494,8 @@ function init() { ,it: 'Salvare il dato corrente prima di passare ad uno nuovo?' ,tr: 'Yenisine geçmeden önce mevcut kaydı kaydet' ,zh_cn: '切换至新记录前保存当前记录?' - } + ,hu: 'Elmentsem az aktuális adatokat mielőtt újra válunk?' + } ,'Add new interval before' : { cs: 'Přidat nový interval před' ,he: 'הוסף מרווח חדש לפני ' @@ -9105,6 +9519,7 @@ function init() { ,it: 'Aggiungere prima un nuovo intervallo' ,tr: 'Daha önce yeni aralık ekle' ,zh_cn: '在此前新增区间' + ,hu: 'Új intervallum hozzáadása elötte' } ,'Delete interval' : { cs: 'Smazat interval' @@ -9129,6 +9544,7 @@ function init() { ,it: 'Elimina intervallo' ,tr: 'Aralığı sil' ,zh_cn: '删除区间' + ,hu: 'Intervallum törlése' } ,'I:C' : { cs: 'I:C' @@ -9136,7 +9552,7 @@ function init() { ,nb: 'IKH' ,fr: 'I:C' ,ro: 'ICR' - ,de: 'I:KH' + ,de: 'IE:KH' ,dk: 'I:C' ,es: 'I:C' ,sv: 'I:C' @@ -9152,6 +9568,7 @@ function init() { ,it: 'I:C' ,tr: 'İ:K' ,zh_cn: 'ICR' + ,hu: 'I:C' } ,'ISF' : { cs: 'ISF' @@ -9169,12 +9586,13 @@ function init() { ,pl: 'ISF' ,pt: 'ISF' ,nl: 'ISF' - ,ru: 'Чувствительность к инсулину ISF' + ,ru: 'Чувств к инс ISF' ,sk: 'ISF' ,ko: 'ISF' ,it: 'ISF' ,tr: 'ISF' ,zh_cn: 'ISF' + ,hu: 'ISF' } ,'Combo Bolus' : { cs: 'Kombinovaný bolus' @@ -9192,13 +9610,14 @@ function init() { ,hr: 'Dual bolus' ,fi: 'Yhdistelmäbolus' ,pt: 'Bolus duplo' - ,ru: 'Комбинированный болюс' + ,ru: 'Комбинир болюс' ,sk: 'Kombinovaný bolus' ,nl: 'Pizza Bolus' ,ko: 'Combo Bolus' ,it: 'Combo Bolo' ,tr: 'Kombo (Yayma) Bolus' ,zh_cn: '双波' + ,hu: 'Kombinált bólus' } ,'Difference' : { cs: 'Rozdíl' @@ -9223,6 +9642,7 @@ function init() { ,it: 'Differenza' ,tr: 'fark' ,zh_cn: '差别' + ,hu: 'Különbség' } ,'New time' : { cs: 'Nový čas' @@ -9247,6 +9667,7 @@ function init() { ,it: 'Nuovo Orario' ,tr: 'Yeni zaman' ,zh_cn: '新时间' + ,hu: 'Új idő:' } ,'Edit Mode' : { cs: 'Editační mód' @@ -9273,6 +9694,7 @@ function init() { ,tr: 'Düzenleme Modu' ,zh_cn: '编辑模式' ,zh_tw: '編輯模式' + ,hu: 'Szerkesztési mód' } ,'When enabled icon to start edit mode is visible' : { cs: 'Pokud je povoleno, ikona pro vstup do editačního módu je zobrazena' @@ -9298,6 +9720,7 @@ function init() { ,tr: 'Etkinleştirildiğinde düzenleme modunun başında simgesi görünecektir.' ,zh_cn: '启用后开始编辑模式图标可见' ,zh_tw: '啟用後開始編輯模式圖標可見' + ,hu: 'Engedélyezés után a szerkesztési ikon látható' } ,'Operation' : { cs: 'Operace' @@ -9322,6 +9745,7 @@ function init() { ,it: 'Operazione' ,tr: 'İşlem' //Operasyon ,zh_cn: '操作' + ,hu: 'Operáció' } ,'Move' : { cs: 'Přesunout' @@ -9346,6 +9770,7 @@ function init() { ,it: 'Muovi' ,tr: 'Taşı' ,zh_cn: '移动' + ,hu: 'Áthelyezés' } ,'Delete' : { cs: 'Odstranit' @@ -9371,6 +9796,7 @@ function init() { ,ja: '削除' ,tr: 'Sil' ,zh_cn: '删除' + ,hu: 'Törlés' } ,'Move insulin' : { cs: 'Přesunout inzulín' @@ -9395,6 +9821,7 @@ function init() { ,it: 'Muovi Insulina' ,tr: 'İnsülini taşı' ,zh_cn: '移动胰岛素' + ,hu: 'Inzulin áthelyezése' } ,'Move carbs' : { cs: 'Přesunout sacharidy' @@ -9419,6 +9846,7 @@ function init() { ,it: 'Muovi carboidrati' ,tr: 'Karbonhidratları taşı' ,zh_cn: '移动碳水' + ,hu: 'Szénhidrát áthelyezése' } ,'Remove insulin' : { cs: 'Odstranit inzulín' @@ -9443,6 +9871,7 @@ function init() { ,it: 'Rimuovi insulina' ,tr: 'İnsülini kaldır' ,zh_cn: '去除胰岛素' + ,hu: 'Inzulin törlése' } ,'Remove carbs' : { cs: 'Odstranit sacharidy' @@ -9467,6 +9896,7 @@ function init() { ,it: 'Rimuovi carboidrati' ,tr: 'Karbonhidratları kaldır' ,zh_cn: '去除碳水' + ,hu: 'Szénhidrát törlése' } ,'Change treatment time to %1 ?' : { cs: 'Změnit čas ošetření na %1 ?' @@ -9491,6 +9921,7 @@ function init() { ,it: 'Cambiare tempo alla somministrazione a %1 ?' ,tr: 'Tedavi tarihini %1 e değiştirilsin mi?' ,zh_cn: '修改操作时间到%1?' + ,hu: 'A kezelés időpontjának áthelyezése %1?' } ,'Change carbs time to %1 ?' : { cs: 'Změnit čas sacharidů na %1 ?' @@ -9506,7 +9937,7 @@ function init() { ,bg: 'Да променя ли времето на ВХ с %1?' ,hr: 'Promijeni vrijeme UGH na %1?' ,fi: 'Muuta hiilihydraattien aika? Uusi: %1' - ,ru: 'Изменить время подачи углеводов на % ?' + ,ru: 'Изменить время приема углеводов на % ?' ,sk: 'Zmeniť čas sacharidov na %1 ?' ,pl: 'Zmień czas węglowodanów na %1 ?' ,pt: 'Alterar horário do carboidrato para %1 ?' @@ -9515,6 +9946,7 @@ function init() { ,it: 'Cambiare durata carboidrati a %1 ?' ,tr: 'Karbonhidrat zamanını %1 e değiştirilsin mi?' ,zh_cn: '修改碳水时间到%1?' + ,hu: 'Szénhidrát időpontjának áthelyezése %1' } ,'Change insulin time to %1 ?' : { cs: 'Změnit čas inzulínu na %1 ?' @@ -9539,6 +9971,7 @@ function init() { ,it: 'Cambiare durata insulina a %1 ?' ,tr: 'İnsülin tarihini %1 e değiştirilsin mi?' // zamanı ,zh_cn: '修改胰岛素时间到%1?' + ,hu: 'Inzulin időpont áthelyezése %1' } ,'Remove treatment ?' : { cs: 'Odstranit ošetření ?' @@ -9563,6 +9996,7 @@ function init() { ,it: 'Rimuovere somministrazione ?' ,tr: 'Tedavi kaldırılsın mı? ' ,zh_cn: '去除操作?' + ,hu: 'Kezelés törlése?' } ,'Remove insulin from treatment ?' : { cs: 'Odstranit inzulín z ošetření ?' @@ -9587,6 +10021,7 @@ function init() { ,it: 'Rimuovere insulina dalla somministrazione ?' ,tr: 'İnsülini tedaviden çıkartılsın mı?' ,zh_cn: '从操作中去除胰岛素?' + ,hu: 'Inzulin törlése a kezelésből?' } ,'Remove carbs from treatment ?' : { cs: 'Odstranit sacharidy z ošetření ?' @@ -9611,6 +10046,7 @@ function init() { ,it: 'Rimuovere carboidrati dalla somministrazione ?' ,tr: 'Karbonhidratları tedaviden çıkartılsın mı ?' // kaldırılsın mı ,zh_cn: '从操作中去除碳水化合物?' + ,hu: 'Szénhidrát törlése a kezelésből?' } ,'Rendering' : { cs: 'Vykresluji' @@ -9635,6 +10071,7 @@ function init() { ,it: 'Traduzione' ,tr: 'Grafik oluşturuluyor...' ,zh_cn: '渲染' + ,hu: 'Kirajzolás' } ,'Loading OpenAPS data of' : { cs: 'Nahrávám OpenAPS data z' @@ -9659,6 +10096,7 @@ function init() { ,nl: 'OpenAPS gegevens opladen van' ,tr: 'dan OpenAPS verileri yükleniyor' ,zh_cn: '载入OpenAPS数据从' + ,hu: 'OpenAPS adatainak betöltése innen' } ,'Loading profile switch data' : { cs: 'Nahrávám data přepnutí profilu' @@ -9683,6 +10121,7 @@ function init() { ,nl: 'Ophalen van data om profiel te wisselen' ,tr: 'Veri profili değişikliği yükleniyor' ,zh_cn: '载入配置文件交换数据' + ,hu: 'Profil változás adatainak betöltése' } ,'Redirecting you to the Profile Editor to create a new profile.' : { cs: 'Chybě nastavený profil.\nNení definovaný žádný platný profil k času zobrazení.\nProvádím přesměrování na editor profilu.' @@ -9698,7 +10137,7 @@ function init() { ,sv: 'Fel profilinställning.\nIngen profil vald för vald tid.\nOmdirigerar för att skapa ny profil.' ,nb: 'Feil profilinstilling.\nIngen profil valgt for valgt tid.\nVideresender for å lage ny profil.' ,fi: 'Väärä profiiliasetus tai profiilia ei löydy.\nSiirrytään profiilin muokkaamiseen uuden profiilin luontia varten.' - ,ru: 'Неверные настройки профиля. Для отображаемого времени не определен профиль. Переход к редактору профиля для создания нового' + ,ru: 'Переход к редактору профиля для создания нового' ,sk: 'Zle nastavený profil.\nK zobrazenému času nieje definovaný žiadny profil.\nPresmerovávam na vytvorenie profilu.' ,pl: 'Złe ustawienia profilu.\nDla podanego czasu nie zdefiniowano profilu.\nPrzekierowuję do edytora profili aby utworzyć nowy.' ,pt: 'Configuração de perfil incorreta. \nNão há perfil definido para mostrar o horário. \nRedirecionando para o editor de perfil para criar um perfil novo.' @@ -9707,6 +10146,7 @@ function init() { ,nl: 'Verkeerde profiel instellingen.\ngeen profiel beschibaar voor getoonde tijd.\nVerder naar profiel editor om een profiel te maken.' ,tr: 'Yanlış profil ayarı.\nGörüntülenen zamana göre profil tanımlanmamış.\nYeni profil oluşturmak için profil düzenleyicisine yönlendiriliyor.' ,zh_cn: '配置文件设置错误。\n没有配置文件定义为显示时间。\n返回配置文件编辑器以新建配置文件。' + ,hu: 'Átirányítás a profil szerkesztőre, hogy egy új profilt készítsen' } ,'Pump' : { cs: 'Pumpa' @@ -9726,11 +10166,12 @@ function init() { ,nl: 'Pomp' ,ko: '펌프' ,fi: 'Pumppu' + , pl: 'Pompa' ,pt: 'Bomba' ,it: 'Pompa' ,tr: 'Pompa' ,zh_cn: '胰岛素泵' - ,pl: 'Pompa' + ,hu: 'Pumpa' } ,'Sensor Age' : { cs: 'Stáří senzoru (SAGE)' @@ -9746,16 +10187,17 @@ function init() { ,bg: 'Възраст на сензора (ВС)' ,hr: 'Starost senzora' ,ro: 'Vechimea senzorului' - ,ru: 'Сенсор отработал' + ,ru: 'Сенсор работает' ,nl: 'Sensor leeftijd' ,ko: '센서 사용 기간' ,fi: 'Sensorin ikä' + , pl: 'Wiek sensora' ,pt: 'Idade do sensor' ,it: 'SAGE - Durata Sensore' ,tr: '(SAGE) Sensör yaşı ' ,zh_cn: '探头使用时间(SAGE)' ,zh_tw: '探頭使用時間(SAGE)' - ,pl: 'Wiek sensora' + ,hu: 'Szenzor élettartalma (SAGE)' } ,'Insulin Age' : { cs: 'Stáří inzulínu (IAGE)' @@ -9771,16 +10213,17 @@ function init() { ,bg: 'Възраст на инсулина (ВИ)' ,hr: 'Starost inzulina' ,ro: 'Vechimea insulinei' - ,ru: 'инсулин отработал' + ,ru: 'Инсулин работает' ,ko: '인슐린 사용 기간' ,fi: 'Insuliinin ikä' + , pl: 'Wiek insuliny' ,pt: 'Idade da insulina' ,it: 'IAGE - Durata Insulina' ,nl: 'Insuline ouderdom (IAGE)' ,tr: '(IAGE) İnsülin yaşı' ,zh_cn: '胰岛素使用时间(IAGE)' ,zh_tw: '胰島素使用時間(IAGE)' - ,pj: 'Wiek insuliny' + ,hu: 'Inzulin élettartalma (IAGE)' } ,'Temporary target' : { cs: 'Dočasný cíl' @@ -9800,10 +10243,12 @@ function init() { ,nl: 'Tijdelijk doel' ,ko: '임시 목표' ,fi: 'Tilapäinen tavoite' + , pl: 'Tymczasowy cel' ,pt: 'Meta temporária' ,it: 'Obiettivo Temporaneo' ,tr: 'Geçici hedef' ,zh_cn: '临时目标' + ,hu: 'Átmeneti cél' } ,'Reason' : { cs: 'Důvod' @@ -9823,11 +10268,12 @@ function init() { ,ru: 'Причина' ,ko: '근거' ,fi: 'Syy' + , pl: 'Powód' ,pt: 'Razão' ,it: 'Ragionare' ,tr: 'Neden' // Gerekçe ,zh_cn: '原因' - ,pl: 'Powód' + ,hu: 'Indok' } ,'Eating soon' : { cs: 'Následuje jídlo' @@ -9836,21 +10282,22 @@ function init() { ,fr: 'Repas sous peu' ,sv: 'Snart matdags' ,nb: 'Snart tid for mat' - ,de: 'Bald essend' + ,de: 'Bald essen' ,dk: 'Spiser snart' ,es: 'Comer pronto' ,bg: 'Ядене скоро' ,hr: 'Uskoro jelo' ,ro: 'Mâncare în curând' - ,ru: 'Приближается прием пищи' + ,ru: 'Ожидаемый прием пищи' ,nl: 'Binnenkort eten' ,ko: '편집 중' ,fi: 'Syödään pian' + , pl: 'Zjedz wkrótce' ,pt: 'Refeição em breve' ,it: 'Mangiare prossimamente' ,tr: 'Yakında yemek' // Kısa zamanda yemek yenecek ,zh_cn: '接近用餐时间' - ,pl: 'Zjedz wkrótce' + ,hu: 'Hamarosan eszem' } ,'Top' : { cs: 'Horní' @@ -9875,6 +10322,7 @@ function init() { ,tr: 'Üst' ,zh_cn: '顶部' ,pl: 'Góra' + ,hu: 'Felső' } ,'Bottom' : { cs: 'Dolní' @@ -9899,6 +10347,7 @@ function init() { ,tr: 'Alt' //aşağı, alt, düşük ,zh_cn: '底部' ,pl: "Dół" + ,hu: "Alsó" } ,'Activity' : { cs: 'Aktivita' @@ -9923,6 +10372,7 @@ function init() { ,tr: 'Aktivite' ,zh_cn: '有效的' ,pl: 'Aktywność' + ,hu: 'Aktivitás' } ,'Targets' : { cs: 'Cíl' @@ -9947,6 +10397,7 @@ function init() { ,tr: 'Hedefler' ,zh_cn: '目标' ,pl: 'Cele' + ,hu: 'Célok' } ,'Bolus insulin:' : { cs: 'Bolusový inzulín:' @@ -9971,6 +10422,7 @@ function init() { ,tr: 'Bolus insülin:' ,zh_cn: '大剂量胰岛素' ,pl: 'Bolus insuliny' + ,hu: 'Bólus inzulin' } ,'Base basal insulin:' : { cs: 'Základní bazální inzulín:' @@ -9980,7 +10432,7 @@ function init() { ,ro: 'Bazala obișnuită:' ,el: 'Βασική Ινσουλίνη' ,es: 'Insulina basal básica' - ,ru: 'Основной базальный инсулин' + ,ru: 'Профильный базальный инсулин' ,sv: 'Basalinsulin:' ,nb: 'Basalinsulin:' ,hr: 'Osnovni bazal:' @@ -9995,6 +10447,7 @@ function init() { ,tr: 'Temel bazal insülin' ,zh_cn: '基础率胰岛素' ,pl: 'Bazowa dawka insuliny' + ,hu: 'Általános bazal inzulin' } ,'Positive temp basal insulin:' : { cs: 'Pozitivní dočasný bazální inzulín:' @@ -10012,13 +10465,14 @@ function init() { ,fi: 'Positiivinen tilapäisbasaali:' ,de: 'Positives temporäres Basal Insulin:' ,dk: 'Positiv midlertidig basalinsulin:' + , pl: 'Zwiększona bazowa dawka insuliny' ,pt: 'Insulina basal temporária positiva:' ,sk: 'Pozitívny dočasný bazálny inzulín:' ,it: 'Insulina basale temp positiva:' ,nl: 'Extra tijdelijke basaal insuline' ,tr: 'Pozitif geçici bazal insülin:' ,zh_cn: '实际临时基础率胰岛素' - , pl: 'Zwiększona bazowa dawka insuliny' + ,hu: 'Pozitív átmeneti bazál inzulin' } ,'Negative temp basal insulin:' : { cs:'Negativní dočasný bazální inzulín:' @@ -10036,13 +10490,14 @@ function init() { ,fi: 'Negatiivinen tilapäisbasaali:' ,de: 'Negatives temporäres Basal Insulin:' ,dk: 'Negativ midlertidig basalinsulin:' + , pl: 'Zmniejszona bazowa dawka insuliny' ,pt: 'Insulina basal temporária negativa:' ,sk: 'Negatívny dočasný bazálny inzulín:' ,it: 'Insulina basale Temp negativa:' ,nl: 'Negatieve tijdelijke basaal insuline' ,tr: 'Negatif geçici bazal insülin:' ,zh_cn: '其余临时基础率胰岛素' - , pl: 'Zmniejszona bazowa dawka insuliny' + ,hu: 'Negatív átmeneti bazál inzulin' } ,'Total basal insulin:' : { cs: 'Celkový bazální inzulín:' @@ -10060,13 +10515,14 @@ function init() { ,fi: 'Basaali yhteensä:' ,de: 'Gesamt Basal Insulin:' ,dk: 'Total daglig basalinsulin:' + , pl: 'Całkowita ilość bazowej dawki insuliny' ,pt: 'Insulina basal total:' ,sk: 'Celkový bazálny inzulín:' ,it: 'Insulina Basale Totale:' ,nl: 'Totaal basaal insuline' ,tr: 'Toplam bazal insülin:' ,zh_cn: '基础率胰岛素合计' - , pl: 'Całkowita ilość bazowej dawki insuliny' + ,hu: 'Teljes bazál inzulin' } ,'Total daily insulin:' : { cs:'Celkový denní inzulín:' @@ -10084,13 +10540,14 @@ function init() { ,de: 'Gesamtes tägliches Insulin:' ,dk: 'Total dagsdosis insulin' ,es: 'Total Insulina diaria:' + ,pl: 'Całkowita dzienna ilość insuliny' ,pt: 'Insulina diária total:' ,sk: 'Celkový denný inzulín:' ,it: 'Totale giornaliero d\'insulina:' ,nl: 'Totaal dagelijkse insuline' ,tr: 'Günlük toplam insülin:' ,zh_cn: '每日胰岛素合计' - ,pl: 'Całkowita dzienna ilość insuliny' + ,hu: 'Teljes napi inzulin' } ,'Unable to %1 Role' : { // PUT or POST cs: 'Chyba volání %1 Role:' @@ -10106,6 +10563,7 @@ function init() { ,fi: '%1 operaatio roolille opäonnistui' ,de: 'Unpassend zu %1 Rolle' ,dk: 'Kan ikke slette %1 rolle' + ,pl: 'Nie można %1 roli' ,pt: 'Função %1 não foi possível' ,sk: 'Chyba volania %1 Role' ,ko: '%1로 비활성' @@ -10113,7 +10571,7 @@ function init() { ,nl: 'Kan %1 rol niet verwijderen' ,tr: '%1 Rolü yapılandırılamadı' ,zh_cn: '%1角色不可用' - ,pl: 'Nie można %1 roli' + ,hu: 'Hiba a %1 szabály hívásánál' } ,'Unable to delete Role' : { cs: 'Nelze odstranit Roli:' @@ -10137,6 +10595,7 @@ function init() { ,tr: 'Rol silinemedi' ,zh_cn: '无法删除角色' ,pl: 'Nie można usunąć roli' + ,hu: 'Nem lehetett a Szerepet törölni' } ,'Database contains %1 roles' : { cs: 'Databáze obsahuje %1 rolí' @@ -10152,6 +10611,7 @@ function init() { ,fi: 'Tietokanta sisältää %1 roolia' ,de: 'Datenbank enthält %1 Rollen' ,dk: 'Databasen indeholder %1 roller' + , pl: 'Baza danych zawiera %1 ról' ,pt: 'Banco de dados contém %1 Funções' ,sk: 'Databáza obsahuje %1 rolí' ,ko: '데이터베이스가 %1 포함' @@ -10159,7 +10619,7 @@ function init() { ,nl: 'Database bevat %1 rollen' ,tr: 'Veritabanı %1 rol içerir' ,zh_cn: '数据库包含%1个角色' - , pl: 'Baza danych zawiera %1 ról' + ,hu: 'Az adatbázis %1 szerepet tartalmaz' } ,'Edit Role' : { cs:'Editovat roli' @@ -10175,6 +10635,7 @@ function init() { ,de: 'Rolle editieren' ,dk: 'Rediger rolle' ,es: 'Editar Rol' + ,pl: 'Edycja roli' ,pt: 'Editar Função' ,sk: 'Editovať rolu' ,ko: '편집 모드' @@ -10182,7 +10643,7 @@ function init() { ,nl: 'Pas rol aan' ,tr: 'Rolü düzenle' ,zh_cn: '编辑角色' - ,pl: 'Edycja roli' + ,hu: 'Szerep szerkesztése' } ,'admin, school, family, etc' : { cs: 'administrátor, škola, rodina atd...' @@ -10198,6 +10659,7 @@ function init() { ,fi: 'ylläpitäjä, koulu, perhe jne' ,de: 'Administrator, Schule, Familie, etc' ,dk: 'Administrator, skole, familie, etc' + ,pl: 'administrator, szkoła, rodzina, itp' ,pt: 'Administrador, escola, família, etc' ,sk: 'administrátor, škola, rodina atď...' ,ko: '관리자, 학교, 가족 등' @@ -10205,7 +10667,7 @@ function init() { ,nl: 'admin, school, familie, etc' ,tr: 'yönetici, okul, aile, vb' ,zh_cn: '政府、学校、家庭等' - ,pl: 'administrator, szkoła, rodzina, itp' + ,hu: 'admin, iskola, család, stb' } ,'Permissions' : { cs: 'Oprávnění' @@ -10221,6 +10683,7 @@ function init() { ,de: 'Berechtigungen' ,dk: 'Rettigheder' ,es: 'Permisos' + ,pl: 'Uprawnienia' ,pt: 'Permissões' ,sk: 'Oprávnenia' ,ko: '허가' @@ -10228,7 +10691,7 @@ function init() { ,nl: 'Rechten' ,tr: 'İzinler' ,zh_cn: '权限' - ,pl: 'Uprawnienia' + ,hu: 'Engedély' } ,'Are you sure you want to delete: ' : { cs: 'Opravdu vymazat: ' @@ -10241,9 +10704,10 @@ function init() { ,sv: 'Är du säker att du vill ta bort:' ,nb: 'Er du sikker på at du vil slette:' ,fi: 'Oletko varmat että haluat tuhota: ' - ,de: ' Sind sie sicher, das Sie löschen wollen:' + ,de: 'Sind sie sicher, das Sie löschen wollen:' ,dk: 'Er du sikker på at du vil slette:' ,es: 'Seguro que quieres eliminarlo:' + ,pl: 'Jesteś pewien, że chcesz usunąć:' ,pt: 'Tem certeza de que deseja apagar:' ,sk: 'Naozaj zmazať:' ,ko: '정말로 삭제하시겠습니까: ' @@ -10251,7 +10715,7 @@ function init() { ,nl: 'Weet u het zeker dat u wilt verwijderen?' ,tr: 'Silmek istediğinizden emin misiniz:' ,zh_cn: '你确定要删除:' - ,pl: 'Jesteś pewien, że chcesz usunąć:' + ,hu: 'Biztos, hogy törölni szeretnéd: ' } ,'Each role will have a 1 or more permissions. The * permission is a wildcard, permissions are a hierarchy using : as a separator.' : { cs: 'Každá role má 1 nebo více oprávnění. Oprávnění * je zástupný znak, oprávnění jsou hiearchie používající : jako oddělovač.' @@ -10266,6 +10730,7 @@ function init() { ,fi: 'Jokaisella roolilla on yksi tai useampia oikeuksia. * on jokeri (tunnistuu kaikkina oikeuksina), oikeudet ovat hierarkia joka käyttää : merkkiä erottimena.' ,de: 'Jede Rolle hat eine oder mehrere Berechtigungen. Die * Berechtigung ist ein Platzhalter, Berechtigungen sind hierachrchisch mit : als Separator.' ,es: 'Cada Rol tiene uno o más permisos. El permiso * es un marcador de posición y los permisos son jerárquicos con : como separador.' + , pl: 'Każda rola będzie mieć 1 lub więcej uprawnień. Symbol * uprawnia do wszystkiego. Uprawnienia są hierarchiczne, używając : jako separatora.' ,pt: 'Cada função terá uma ou mais permissões. A permissão * é um wildcard, permissões são uma hierarquia utilizando * como um separador.' ,sk: 'Každá rola má 1 alebo viac oprávnení. Oprávnenie * je zástupný znak, oprávnenia sú hierarchie používajúce : ako oddelovač.' ,ko: '각각은 1 또는 그 이상의 허가를 가지고 있습니다. 허가는 예측이 안되고 구분자로 : 사용한 계층이 있습니다' @@ -10273,7 +10738,7 @@ function init() { ,nl: 'Elke rol heeft mintens 1 machtiging. De * machtiging is een wildcard, machtigingen hebben een hyrarchie door gebruik te maken van : als scheidingsteken.' ,tr: 'Her rolün bir veya daha fazla izni vardır.*izni bir yer tutucudur ve izinler ayırıcı olarak : ile hiyerarşiktir.' ,zh_cn: '每个角色都具有一个或多个权限。权限设置时使用*作为通配符,层次结构使用:作为分隔符。' - , pl: 'Każda rola będzie mieć 1 lub więcej uprawnień. Symbol * uprawnia do wszystkiego. Uprawnienia są hierarchiczne, używając : jako separatora.' + ,hu: 'Minden szerepnek egy vagy több engedélye van. A * engedély helyettesítő engedély amely a hierarchiához : használja elválasztásnak.' } ,'Add new Role' : { cs: 'Přidat novou roli' @@ -10297,6 +10762,7 @@ function init() { ,tr: 'Yeni Rol ekle' ,zh_cn: '添加新角色' ,pl: 'Dodaj nową rolę' + ,hu: 'Új szerep hozzáadása' } ,'Roles - Groups of People, Devices, etc' : { cs: 'Role - Skupiny lidí, zařízení atd.' @@ -10320,6 +10786,7 @@ function init() { ,tr: 'Roller - İnsan grupları, Cihazlar vb.' ,zh_cn: '角色 - 一组人或设备等' ,pl: 'Role - Grupy ludzi, urządzeń, itp' + ,hu: 'Szerepek - Emberek csoportja, berendezések, stb.' } ,'Edit this role' : { cs: 'Editovat tuto roli' @@ -10343,6 +10810,7 @@ function init() { ,tr: 'Bu rolü düzenle' ,zh_cn: '编辑角色' ,pl: 'Edytuj rolę' + ,hu: 'Szerep szerkesztése' } ,'Admin authorized' : { cs: 'Admin autorizován' @@ -10367,6 +10835,7 @@ function init() { ,zh_cn: '已授权' ,zh_tw: '已授權' ,pl: 'Administrator autoryzowany' + ,hu: 'Adminisztrátor engedélyezve' } ,'Subjects - People, Devices, etc' : { cs: 'Subjekty - Lidé, zařízení atd.' @@ -10389,7 +10858,8 @@ function init() { ,nl: 'Onderwerpen - Mensen, apparaten etc' ,tr: 'Konular - İnsanlar, Cihazlar, vb.' ,zh_cn: '用户 - 人、设备等' - ,pl: 'Obiekty - ludzie, urządzenia itp' + ,pl: 'Obiekty - ludzie, urządzenia itp' + ,hu: 'Semélyek - Emberek csoportja, berendezések, stb.' } ,'Each subject will have a unique access token and 1 or more roles. Click on the access token to open a new view with the selected subject, this secret link can then be shared.' : { cs: 'Každý subjekt má svůj unikátní token a 1 nebo více rolí. Klikem na přístupový token se otevře nové okno pro tento subjekt. Tento link je možné sdílet.' @@ -10413,6 +10883,7 @@ function init() { ,tr: 'Her konu benzersiz bir erişim anahtarı ve bir veya daha fazla rol alır. Seçilen konuyla ilgili yeni bir görünüm elde etmek için erişim tuşuna tıklayın. Bu gizli bağlantı paylaşılabilinir.' ,zh_cn: '每个用户具有唯一的访问令牌和一个或多个角色。在访问令牌上单击打开新窗口查看已选择用户,此时该链接可分享。' ,pl: 'Każdy obiekt będzie miał unikalny token dostępu i jedną lub więcej ról. Kliknij token dostępu, aby otworzyć nowy widok z wybranym obiektem, ten tajny link może być następnie udostępniony' + ,hu: 'Mindegyik személynek egy egyedi hozzáférése lesz 1 vagy több szereppel. Kattints a tokenre, hogy egy új nézetet kapj - a kapott linket megoszthatod velük.' } ,'Add new Subject' : { cs: 'Přidat nový subjekt' @@ -10436,6 +10907,7 @@ function init() { ,tr: 'Yeni konu ekle' ,zh_cn: '添加新用户' ,pl: 'Dodaj obiekt' + ,hu: 'Új személy hozzáadása' } ,'Unable to %1 Subject' : { // PUT or POST cs: 'Chyba volání %1 Subjektu:' @@ -10459,6 +10931,7 @@ function init() { ,tr: '%1 konu yapılamıyor' ,zh_cn: '%1用户不可用' ,pl: 'Nie można %1 obiektu' + ,hu: 'A %1 személy hozáadása nem sikerült' } ,'Unable to delete Subject' : { cs: 'Nelze odstranit Subjekt:' @@ -10482,6 +10955,7 @@ function init() { ,tr: 'Konu silinemedi' ,zh_cn: '无法删除用户' ,pl: 'Nie można usunąć obiektu' + ,hu: 'A személyt nem sikerült törölni' } ,'Database contains %1 subjects' : { cs: 'Databáze obsahuje %1 subjektů' @@ -10490,7 +10964,7 @@ function init() { ,hr: 'Baza sadrži %1 subjekata' ,fr: 'La base de données contient %1 utilisateurs' ,fi: 'Tietokanta sisältää %1 käyttäjää' - ,ru: 'База данных содержит %1 субъект(а/ов)' + ,ru: 'База данных содержит %1 субъекта/ов' ,ro: 'Baza de date are %1 subiecți' ,sv: 'Databasen innehåller %1 ämnen' ,nb: 'Databasen inneholder %1 ressurser' @@ -10505,6 +10979,7 @@ function init() { ,tr: 'Veritabanı %1 konu içeriyor' ,zh_cn: '数据库包含%1个用户' ,pl: 'Baza danych zawiera %1 obiektów' + ,hu: 'Az adatbázis %1 személyt tartalmaz' } ,'Edit Subject' : { cs:'Editovat subjekt' @@ -10528,6 +11003,7 @@ function init() { ,tr: 'Konuyu düzenle' ,zh_cn: '编辑用户' ,pl: 'Edytuj obiekt' + ,hu: 'Személy szerkesztése' } ,'person, device, etc' : { cs:'osoba, zařízeni atd.' @@ -10551,6 +11027,7 @@ function init() { ,tr: 'kişi, cihaz, vb' ,zh_cn: '人、设备等' ,pl: 'osoba, urządzenie, itp' + ,hu: 'személy, berendezés, stb.' } ,'role1, role2' : { cs:'role1, role2' @@ -10574,6 +11051,7 @@ function init() { ,tr: 'rol1, rol2' ,zh_cn: '角色1、角色2' ,pl: 'rola1, rola2' + ,hu: 'szerep1, szerep2' } ,'Edit this subject' : { cs:'Editovat tento subjekt' @@ -10597,6 +11075,7 @@ function init() { ,tr: 'Bu konuyu düzenle' ,zh_cn: '编辑此用户' ,pl: 'Edytuj ten obiekt' + ,hu: 'A kiválasztott személy szerkesztése' } ,'Delete this subject' : { cs:'Smazat tento subjekt' @@ -10620,6 +11099,7 @@ function init() { ,tr: 'Bu konuyu sil' ,zh_cn: '删除此用户' ,pl: 'Usuń ten obiekt' + ,hu: 'A kiválasztott személy törlése' } ,'Roles' : { cs:'Role' @@ -10643,6 +11123,7 @@ function init() { ,tr: 'Roller' ,zh_cn: '角色' ,pl: 'Role' + ,hu: 'Szerepek' } ,'Access Token' : { cs:'Přístupový token' @@ -10666,6 +11147,7 @@ function init() { ,tr: 'Erişim Simgesi (Access Token)' ,zh_cn: '访问令牌' ,pl: 'Token dostępu' + ,hu: 'Hozzáférési token' } ,'hour ago' : { cs:'hodina zpět' @@ -10689,6 +11171,7 @@ function init() { ,tr: 'saat önce' ,zh_cn: '小时前' ,pl: 'Godzię temu' + ,hu: 'órája' } ,'hours ago' : { cs:'hodin zpět' @@ -10712,6 +11195,7 @@ function init() { ,tr: 'saat önce' ,zh_cn: '小时前' ,pl: 'Godzin temu' + ,hu: 'órája' } ,'Silence for %1 minutes' : { cs:'Ztlumit na %1 minut' @@ -10724,7 +11208,7 @@ function init() { ,sv: 'Tyst i %1 minuter' ,nb: 'Stille i %1 minutter' ,fi: 'Hiljennä %1 minuutiksi' - ,de: 'Inaktivität für %1 Minuten' + ,de: 'Ruhe für %1 Minuten' ,dk: 'Stilhed i %1 minutter' ,pt: 'Silencir por %1 minutos' ,es: 'Silenciado por %1 minutos' @@ -10736,6 +11220,7 @@ function init() { ,zh_cn: '静音%1分钟' ,zh_tw: '靜音%1分鐘' ,pl: 'Wycisz na %1 minut' + ,hul: 'Lehalkítás %1 percre' } ,'Check BG' : { cs:'Zkontrolovat glykémii' @@ -10759,6 +11244,7 @@ function init() { ,tr: 'KŞ\'ini kontrol et' ,zh_cn: '测量血糖' ,pl: 'Sprawdź glukozę z krwi' + ,hu: 'Ellenőrizd a cukorszintet' } ,'BASAL' : { cs: 'BAZÁL' @@ -10783,6 +11269,7 @@ function init() { ,zh_cn: '基础率' ,zh_tw: '基礎率' ,pl: 'BAZA' + ,hu: 'BAZÁL' } ,'Current basal' : { cs:'Současný bazál' @@ -10806,6 +11293,7 @@ function init() { ,tr: 'Geçerli Bazal' ,zh_cn: '当前基础率' ,pl: 'Dawka podstawowa' + ,hu: 'Aktuális bazál' } ,'Sensitivity' : { cs:'Citlivost (ISF)' @@ -10829,6 +11317,7 @@ function init() { ,tr: 'Duyarlılık Faktörü (ISF)' ,zh_cn: '胰岛素敏感系数' ,pl: 'Wrażliwość' + ,hu: 'Inzulin érzékenység' } ,'Current Carb Ratio' : { cs:'Sacharidový poměr (I:C)' @@ -10852,6 +11341,7 @@ function init() { ,tr: 'Geçerli Karbonhidrat oranı I/C (ICR)' ,zh_cn: '当前碳水化合物系数' ,pl: 'Obecny przelicznik węglowodanowy' + ,hu: 'Aktuális szénhidrát arány' } ,'Basal timezone' : { cs:'Časová zóna' @@ -10875,6 +11365,7 @@ function init() { ,tr: 'Bazal saat dilimi' ,zh_cn: '基础率时区' ,pl: 'Strefa czasowa dawki podstawowej' + ,hu: 'Bazál időzóna' } ,'Active profile' : { cs:'Aktivní profil' @@ -10898,6 +11389,7 @@ function init() { ,tr: 'Aktif profil' ,zh_cn: '当前配置文件' ,pl: 'Profil aktywny' + ,hu: 'Aktív profil' } ,'Active temp basal' : { cs:'Aktivní dočasný bazál' @@ -10921,6 +11413,7 @@ function init() { ,tr: 'Aktif geçici bazal oranı' ,zh_cn: '当前临时基础率' ,pl: 'Aktywa tymczasowa dawka podstawowa' + ,hu: 'Aktív átmeneti bazál' } ,'Active temp basal start' : { cs:'Začátek dočasného bazálu' @@ -10929,7 +11422,7 @@ function init() { ,dk: 'Aktiv midlertidig basal start' ,ro: 'Start bazală temporară activă' ,fr: 'Début du débit basal temporaire' - ,ru: 'Старт активного временного базала' + ,ru: 'Старт актуального временного базала' ,sk: 'Štart dočasného bazálu' ,sv: 'Aktiv tempbasal start' ,nb: 'Aktiv midlertidig basal start' @@ -10944,6 +11437,7 @@ function init() { ,tr: 'Aktif geçici bazal oranı başlangıcı' ,zh_cn: '当前临时基础率开始' ,pl: 'Start aktywnej tymczasowej dawki podstawowej' + ,hu: 'Aktív átmeneti bazál kezdete' } ,'Active temp basal duration' : { cs:'Trvání dočasného bazálu' @@ -10952,7 +11446,7 @@ function init() { ,dk: 'Aktiv midlertidig basal varighed' ,ro: 'Durata bazalei temporare active' ,fr: 'Durée du débit basal temporaire' - ,ru: 'Длительность активного временного базала' + ,ru: 'Длительность актуального временного базала' ,sk: 'Trvanie dočasného bazálu' ,sv: 'Aktiv tempbasal varaktighetstid' ,nb: 'Aktiv midlertidig basal varighet' @@ -10967,6 +11461,7 @@ function init() { ,zh_cn: '当前临时基础率期间' ,pl: 'Czas trwania aktywnej tymczasowej dawki podstawowej' ,tr: 'Aktif geçici bazal süresi' + ,hu: 'Aktív átmeneti bazál időtartalma' } ,'Active temp basal remaining' : { cs:'Zbývající dočasný bazál' @@ -10975,7 +11470,7 @@ function init() { ,dk: 'Resterende tid for aktiv midlertidig basal' ,ro: 'Rest de bazală temporară activă' ,fr: 'Durée restante de débit basal temporaire' - ,ru: 'Остаток акивного временного базала' + ,ru: 'Остается актуального временного базала' ,sk: 'Zostatok dočasného bazálu' ,sv: 'Återstående tempbasaltid' ,nb: 'Gjenstående midlertidig basal tid' @@ -10990,6 +11485,7 @@ function init() { ,zh_cn: '当前临时基础率剩余' ,pl: 'Pozostała aktywna tymczasowa dawka podstawowa' ,tr: 'Aktif geçici bazal kalan' + ,hu: 'Átmeneti bazál visszamaradó ideje' } ,'Basal profile value' : { cs: 'Základní hodnota bazálu' @@ -11013,6 +11509,7 @@ function init() { ,zh_cn: '基础率配置文件值' ,pl: 'Wartość profilu podstawowego' ,tr: 'Bazal profil değeri' + ,hu: 'Bazál profil értéke' } ,'Active combo bolus' : { cs:'Aktivní kombinovaný bolus' @@ -11036,6 +11533,7 @@ function init() { ,zh_cn: '当前双波大剂量' ,pl: 'Aktywny bolus złożony' ,tr: 'Aktive kombo bolus' + ,hu: 'Aktív kombinált bólus' } ,'Active combo bolus start' : { cs: 'Začátek kombinovaného bolusu' @@ -11044,7 +11542,7 @@ function init() { ,dk: 'Aktiv kombibolus start' ,ro: 'Start bolus combinat activ' ,fr: 'Début de Bolus Duo/Combo' - ,ru: 'Старт активного комбо болюса' + ,ru: 'Старт активного комбинир болюса' ,sv: 'Aktiv kombobolus start' ,nb: 'Kombinasjonsbolus start' ,fi: 'Aktiivisen yhdistelmäboluksen alku' @@ -11059,6 +11557,7 @@ function init() { ,zh_cn: '当前双波大剂量开始' ,pl: 'Start aktywnego bolusa złożonego' ,tr: 'Aktif gecikmeli bolus başlangıcı' + ,hu: 'Aktív kombinált bólus kezdete' } ,'Active combo bolus duration' : { cs: 'Trvání kombinovaného bolusu' @@ -11067,7 +11566,7 @@ function init() { ,dk: 'Aktiv kombibolus varighed' ,ro: 'Durată bolus combinat activ' ,fr: 'Durée du Bolus Duo/Combo' - ,ru: 'Длительность активного комбо болюса' + ,ru: 'Длительность активного комбинир болюса' ,sv: 'Aktiv kombibolus varaktighet' ,es: 'Duración del Combo-Bolo activo' ,nb: 'Kombinasjonsbolus varighet' @@ -11082,6 +11581,7 @@ function init() { ,zh_cn: '当前双波大剂量期间' ,pl: 'Czas trwania aktywnego bolusa złożonego' ,tr: 'Active combo bolus süresi' + ,hu: 'Aktív kombinált bólus időtartalma' } ,'Active combo bolus remaining' : { cs: 'Zbývající kombinovaný bolus' @@ -11090,7 +11590,7 @@ function init() { ,dk: 'Resterende aktiv kombibolus' ,ro: 'Rest de bolus combinat activ' ,fr: 'Activité restante du Bolus Duo/Combo' - ,ru: 'Остаток активного комбо болюса' + ,ru: 'Остается активного комбинир болюса' ,sv: 'Återstående aktiv kombibolus' ,es: 'Restante Combo-Bolo activo' ,nb: 'Gjenstående kombinasjonsbolus' @@ -11105,6 +11605,7 @@ function init() { ,zh_cn: '当前双波大剂量剩余' ,pl: 'Pozostały aktywny bolus złożony' ,tr: 'Aktif kombo (yayım) bolus kaldı' + ,hu: 'Aktív kombinált bólus fennmaradó idő' } ,'BG Delta' : { cs:'Změna glykémie' @@ -11120,7 +11621,7 @@ function init() { ,pt: 'Diferença de glicemia' ,es: 'Diferencia de glucemia' ,sk: 'Zmena glykémie' - ,bg: 'Изменение КЗ' + ,bg: 'Дельта ГК' ,hr: 'GUK razlika' ,ko: '혈당 차이' ,it: 'BG Delta' @@ -11129,6 +11630,7 @@ function init() { ,zh_tw: '血糖增量' ,pl: 'Zmiana glikemii' ,tr: 'KŞ farkı' + ,hu: 'Cukorszint változása' } ,'Elapsed Time' : { cs:'Dosažený čas' @@ -11153,6 +11655,7 @@ function init() { ,zh_tw: '所需時間' ,pl: 'Upłynął czas' ,tr: 'Geçen zaman' + ,hu: 'Eltelt idő' } ,'Absolute Delta' : { cs:'Absolutní rozdíl' @@ -11177,6 +11680,7 @@ function init() { ,zh_tw: '絕對增量' ,pl: 'różnica absolutna' ,tr: 'Mutlak fark' + ,hu: 'Abszolút külonbség' } ,'Interpolated' : { cs:'Interpolováno' @@ -11201,6 +11705,7 @@ function init() { ,zh_tw: '插值' ,pl: 'Interpolowany' ,tr: 'Aralıklı' + ,hu: 'Interpolált' } ,'BWP' : { // Bolus Wizard Preview cs: 'KALK' @@ -11225,6 +11730,7 @@ function init() { ,zh_tw: 'BWP' ,pl: 'Kalkulator bolusa' ,tr: 'BWP' + ,hu: 'BWP' } ,'Urgent' : { cs:'Urgentní' @@ -11250,6 +11756,7 @@ function init() { ,zh_tw: '緊急' ,pl:'Pilny' ,tr: 'Acil' + ,hu: 'Sűrgős' } ,'Warning' : { cs:'Varování' @@ -11274,6 +11781,7 @@ function init() { ,zh_tw: '警告' ,pl: 'Ostrzeżenie' ,tr: 'Uyarı' + ,hu: 'Figyelmeztetés' } ,'Info' : { cs: 'Informativní' @@ -11298,6 +11806,7 @@ function init() { ,zh_tw: '資訊' ,pl: 'Informacja' ,tr: 'Info' + ,hu: 'Információ' } ,'Lowest' : { cs: 'Nejnižší' @@ -11322,6 +11831,7 @@ function init() { ,zh_cn: '血糖极低' ,zh_tw: '血糖極低' ,pl: 'Niski' + ,hu: 'Legalacsonyabb' } ,'Snoozing high alarm since there is enough IOB' : { cs:'Vypínání alarmu vyskoké glykémie, protože je dostatek IOB' @@ -11345,6 +11855,7 @@ function init() { ,tr: 'Yeterli IOB(Aktif İnsülin) olduğundan KŞ yüksek uyarımını ertele' ,zh_cn: '有足够的IOB(活性胰岛素),暂停高血糖警报' ,pl: 'Wycisz alarm wysokiej glikemi, jest wystarczająco dużo aktywnej insuliny' + ,hu: 'Magas cukor riasztás késleltetése mivel elegendő inzulin van kiadva (IOB)' } ,'Check BG, time to bolus?' : { cs:'Zkontrolovat glykémii, čas na bolus?' @@ -11355,7 +11866,7 @@ function init() { ,fr: 'Vérifier la glycémie, bolus nécessaire ?' ,bg: 'Провери КЗ, не е ли време за болус?' ,hr: 'Provjeri GUK, vrijeme je za bolus?' - ,ru: 'Проверьте СК, дать болюс?' + ,ru: 'Проверьте ГК, дать болюс?' ,sv: 'Kontrollera BS, dags att ge bolus?' ,nb: 'Sjekk blodsukker, på tide med bolus?' ,fi: 'Tarkista VS, aika bolustaa?' @@ -11368,6 +11879,7 @@ function init() { ,tr: 'KŞine bakın, gerekirse bolus verin?' ,zh_cn: '测量血糖,该输注大剂量了?' ,pl: 'Sprawdź glikemię, czas na bolusa ?' + ,hu: 'Ellenőrizd a cukorszintet. Ideje bóluszt adni?' } ,'Notice' : { cs:'Poznámka' @@ -11391,6 +11903,7 @@ function init() { ,tr: 'Not' ,zh_cn: '提示' ,pl: 'Uwaga' + ,hu: 'Megjegyzés' } ,'required info missing' : { cs:'chybějící informace' @@ -11414,6 +11927,7 @@ function init() { ,tr: 'gerekli bilgi eksik' ,zh_cn: '所需信息不全' ,pl: 'brak wymaganych informacji' + ,hu: 'Szükséges információ hiányos' } ,'Insulin on Board' : { cs:'Aktivní inzulín' @@ -11437,6 +11951,7 @@ function init() { ,tr: '(IOB) Aktif İnsülin' ,zh_cn: '活性胰岛素(IOB)' ,pl: 'Aktywna insulina' + ,hu: 'Aktív inzulin (IOB)' } ,'Current target' : { cs:'Aktuální cílová hodnota' @@ -11460,6 +11975,7 @@ function init() { ,tr: 'Mevcut hedef' ,zh_cn: '当前目标' ,pl: 'Aktualny cel' + ,hu: 'Jelenlegi cél' } ,'Expected effect' : { cs:'Očekávaný efekt' @@ -11483,6 +11999,7 @@ function init() { ,tr: 'Beklenen etki' ,zh_cn: '预期效果' ,pl: 'Oczekiwany efekt' + ,hu: 'Elvárt efektus' } ,'Expected outcome' : { cs:'Očekávaný výsledek' @@ -11506,6 +12023,7 @@ function init() { ,tr: 'Beklenen sonuç' ,zh_cn: '预期结果' ,pl: 'Oczekowany resultat' + ,hu: 'Elvárt eredmény' } ,'Carb Equivalent' : { cs:'Ekvivalent v sacharidech' @@ -11529,6 +12047,7 @@ function init() { ,tr: 'Karbonhidrat eşdeğeri' ,zh_cn: '碳水当量' ,pl: 'Odpowiednik w węglowodanach' + ,hu: 'Szénhidrát megfelelője' } ,'Excess insulin equivalent %1U more than needed to reach low target, not accounting for carbs' : { cs:'Nadbytek inzulínu: o %1U více, než na dosažení spodní hranice cíle. Nepočítáno se sacharidy.' @@ -11545,13 +12064,14 @@ function init() { ,nb: 'Insulin tilsvarende %1U mer enn det trengs for å nå lavt mål, karbohydrater ikke medregnet' ,nl: 'Insulineoverschot van %1U om laag doel te behalen (excl. koolhydraten)' ,fi: 'Liikaa insuliinia: %1U enemmän kuin tarvitaan tavoitteeseen pääsyyn (huomioimatta hiilihydraatteja)' + , pl: 'Nadmiar insuliny, %1J więcej niż potrzeba, aby osiągnąć cel dolnej granicy, nie biorąc pod uwagę węglowodanów' ,pt: 'Excesso de insulina equivalente a %1U além do necessário para atingir a meta inferior, sem levar em conta carboidratos' ,sk: 'Nadbytok inzulínu o %1U viac ako je potrebné na dosiahnutie spodnej cieľovej hranice. Neráta sa so sacharidmi.' ,ko: '낮은 혈당 목표에 도달하기 위해 필요한 인슐린양보다 %1U의 인슐린 양이 초과 되었고 탄수화물 양이 초과되지 않았습니다.' ,it: 'L\'eccesso d\'insulina equivalente %1U più che necessari per raggiungere l\'obiettivo basso, non rappresentano i carboidrati.' ,tr: 'Fazla insülin: Karbonhidratları dikkate alınmadan, alt hedefe ulaşmak için gerekenden %1U\'den daha fazla' //??? ,zh_cn: '胰岛素超过至血糖下限目标所需剂量%1单位,不计算碳水化合物' - , pl: 'Nadmiar insuliny, %1J więcej niż potrzeba, aby osiągnąć cel dolnej granicy, nie biorąc pod uwagę węglowodanów' + ,hu: 'Felesleges inzulin megegyező %1U egységgel az alacsony cél eléréséhez, nem számolva a szénhidrátokkal' } ,'Excess insulin equivalent %1U more than needed to reach low target, MAKE SURE IOB IS COVERED BY CARBS' : { cs:'Nadbytek inzulínu: o %1U více, než na dosažení spodní hranice cíle. UJISTĚTE SE, ŽE JE TO POKRYTO SACHARIDY' @@ -11562,7 +12082,7 @@ function init() { ,fr: 'Insuline en excès: %1U de plus que nécessaire pour atteindre la cible inférieure, ASSUREZ UN APPORT SUFFISANT DE GLUCIDES' ,bg: 'Излишният инсулин %1U е повече от необходимия за достигане до долната граница, ПРОВЕРИ ДАЛИ IOB СЕ ПОКРИВА ОТ ВЪГЛЕХИДРАТИТЕ' ,hr: 'Višak inzulina je %1U više nego li je potrebno da se postigne donja ciljana granica, OBAVEZNO POKRIJTE SA UGH' - ,ru: 'Избыток инсулина, равного %1U, необходимого для достижения нижнего целевого значения, ПОКРОЙТЕ IOB ИНСУЛИН В ОРГАНИЗМЕ УГЛЕВОДАМИ' + ,ru: 'Избыток инсулина, равного %1U, необходимого для достижения нижнего целевого значения, ПОКРОЙТЕ АКТИВН IOB ИНСУЛИН УГЛЕВОДАМИ' ,sv: 'Överskott av insulin motsvarande %1U mer än nödvändigt för att nå lågt målvärde, SÄKERSTÄLL ATT IOB TÄCKS AV KOLHYDRATER' ,es: 'Exceso de insulina en %1U más de la necesaria para alcanzar objetivo inferior. ASEGÚRESE QUE LA INSULINA ACTIVA IOB ESTA CUBIERTA POR CARBOHIDRATOS' ,nb: 'Insulin tilsvarende %1U mer enn det trengs for å nå lavt mål, PASS PÅ AT AKTIVT INSULIN ER DEKKET OPP MED KARBOHYDRATER' @@ -11575,6 +12095,7 @@ function init() { ,tr: 'Fazla insülin: Alt KŞ hedefine ulaşmak için gerekenden %1 daha fazla insülin.IOB(Aktif İnsülin) Karbonhidrat tarafından karşılandığından emin olun.' ,zh_cn: '胰岛素超过至血糖下限目标所需剂量%1单位,确认IOB(活性胰岛素)被碳水化合物覆盖' ,pl: 'Nadmiar insuliny: o %1J więcej niż potrzeba, aby osiągnąć cel dolnej granicy. UPEWNIJ SIĘ, ŻE AKTYWNA INSULINA JEST POKRYTA WĘGLOWODANAMI' + ,hu: 'Felesleges inzulin megegyező %1U egységgel az alacsony cél eléréséhez. FONTOS, HOGY A IOB LEGYEN SZÉNHIDRÁTTAL TAKARVA' } ,'%1U reduction needed in active insulin to reach low target, too much basal?' : { cs:'Nutné snížení aktivního inzulínu o %1U k dosažení spodního cíle. Příliž mnoho bazálu?' @@ -11597,7 +12118,8 @@ function init() { ,it: 'Riduzione 1U% necessaria d\'insulina attiva per raggiungere l\'obiettivo basso, troppa basale?' ,tr: 'Alt KŞ hedefi için %1U aktif insülin azaltılmalı, bazal oranı çok mu yüksek?' ,zh_cn: '活性胰岛素已可至血糖下限目标,需减少%1单位,基础率过高?' - , pl: '%1J potrzebnej redukcji w aktywnej insulinie, aby osiągnąć niski cel dolnej granicy, Za duża dawka podstawowa ?' + ,pl: '%1J potrzebnej redukcji w aktywnej insulinie, aby osiągnąć niski cel dolnej granicy, Za duża dawka podstawowa ?' + ,hu: '%1U egységnyi inzulin redukció szükséges az alacsony cél eléréséhez, túl magas a bazál?' } ,'basal adjustment out of range, give carbs?' : { cs:'úprava změnou bazálu není možná. Podat sacharidy?' @@ -11608,7 +12130,7 @@ function init() { ,fr: 'ajustement de débit basal hors de limites, prenez des glucides?' ,bg: 'Корекция на базала не е възможна, добавка на въглехидрати? ' ,hr: 'prilagodba bazala je izvan raspona, dodati UGH?' - ,ru: 'Корректировка базы вне диапазона, добавить углеводов?' + ,ru: 'Корректировка базала вне диапазона, добавить углеводов?' ,sv: 'basaländring utanför gräns, ge kolhydrater?' ,es: 'ajuste basal fuera de rango, dar carbohidratos?' ,nb: 'basaljustering utenfor tillatt område, gi karbohydrater?' @@ -11621,6 +12143,7 @@ function init() { ,tr: 'Bazal oran ayarlaması limit dışı, karbonhidrat alınsın mı?' ,zh_cn: '基础率调整在范围之外,需要碳水化合物?' ,pl: 'dawka podstawowa poza zakresem, podać węglowodany?' + ,hu: 'bazál változtatása az arányokon kívül esik, szénhidrát bevitele?' } ,'basal adjustment out of range, give bolus?' : { cs:'úprava změnou bazálu není možná. Podat bolus?' @@ -11631,7 +12154,7 @@ function init() { ,fr: 'ajustement de débit basal hors de limites, prenez un bolus?' ,bg: 'Корекция на базала не е възможна, добавка на болус? ' ,hr: 'prilagodna bazala je izvan raspona, dati bolus?' - ,ru: 'Корректировка базы вне диапазона, добавить болюс?' + ,ru: 'Корректировка базала вне диапазона, добавить болюс?' ,sv: 'basaländring utanför gräns, ge bolus?' ,nb: 'basaljustering utenfor tillatt område, gi bolus?' ,fi: 'säätö liian suuri, anna bolus?' @@ -11644,6 +12167,7 @@ function init() { ,tr: 'Bazal oran ayarlaması limit dışı, bolus alınsın mı?' ,zh_cn: '基础率调整在范围之外,需要大剂量?' ,pl: 'dawka podstawowa poza zakresem, podać insulinę?' + ,hu: 'bazál változtatása az arányokon kívül esik, bólusz beadása?' } ,'above high' : { cs:'nad horním' @@ -11668,6 +12192,7 @@ function init() { ,zh_cn: '血糖过高' ,zh_tw: '血糖過高' ,pl: 'powyżej wysokiego' + ,hu: 'magas felett' } ,'below low' : { cs:'pod spodním' @@ -11692,6 +12217,7 @@ function init() { ,zh_cn: '血糖过低' ,zh_tw: '血糖過低' ,pl: 'poniżej niskiego' + ,hu: 'alacsony alatt' } ,'Projected BG %1 target' : { cs:'Předpokládaná glykémie %1 cílem' @@ -11702,7 +12228,7 @@ function init() { ,fr: 'Glycémie cible projetée %1 ' ,bg: 'Предполагаемата КЗ %1 в граници' ,hr: 'Procjena GUK %1 cilja' - ,ru: 'Расчетная гликемия %1' + ,ru: 'Расчетная целевая гликемия %1' ,sv: 'Önskat BS %1 mål' ,nb: 'Ønsket BS %1 mål' ,fi: 'Laskettu VS %1 tavoitteen' @@ -11715,6 +12241,7 @@ function init() { ,tr: 'Beklenen KŞ %1 hedefi' ,zh_cn: '预计血糖%1目标' ,pl: 'Oczekiwany poziom glikemii %1' + ,hu: 'Kiszámított BG cél %1' } ,'aiming at' : { cs:'s cílem' @@ -11738,6 +12265,7 @@ function init() { ,tr: 'istenen sonuç' ,zh_cn: '目标在' ,pl: 'pożądany wynik' + ,hu: 'cél' } ,'Bolus %1 units' : { cs:'Bolus %1 jednotek' @@ -11761,6 +12289,7 @@ function init() { ,tr: 'Bolus %1 Ünite' ,zh_cn: '大剂量%1单位' ,pl: 'Bolus %1 jednostek' + ,hu: 'Bólus %1 egységet' } ,'or adjust basal' : { cs:'nebo úprava bazálu' @@ -11771,7 +12300,7 @@ function init() { ,fr: 'ou ajuster le débit basal' ,bg: 'или корекция на базала' ,hr: 'ili prilagodba bazala' - ,ru: 'или корректировать базу' + ,ru: 'или корректировать базал' ,sv: 'eller justera basal' ,nb: 'eller justere basal' ,fi: 'tai säädä basaalia' @@ -11784,6 +12313,7 @@ function init() { ,tr: 'ya da bazal ayarlama' ,zh_cn: '或调整基础率' ,pl: 'lub dostosuj dawkę bazową' + ,hu: 'vagy a bazál változtatása' } ,'Check BG using glucometer before correcting!' : { cs:'Před korekcí zkontrolujte glukometrem glykémii!' @@ -11807,6 +12337,7 @@ function init() { ,zh_cn: '校正前请使用血糖仪测量血糖!' ,pl: 'Sprawdź glikemię z krwi przed podaniem korekty!' ,tr: 'Düzeltme bolusu öncesi glikometreyle parmaktan KŞini kontrol edin!' + ,hu: 'Ellenőrizd a cukorszintet mérővel korrekció előtt!' } ,'Basal reduction to account %1 units:' : { cs:'Úprava bazálu pro náhradu bolusu %1 U ' @@ -11830,6 +12361,7 @@ function init() { ,zh_cn: '基础率减少到%1单位' ,pl: 'Dawka bazowa zredukowana do 1% J' ,tr: '%1 birimi telafi etmek için azaltılmış Bazaloranı:' + ,hu: 'A bazál csökkentése %1 egység kiszámításához:' } ,'30m temp basal' : { cs:'30ti minutový dočasný bazál' @@ -11853,6 +12385,7 @@ function init() { ,zh_cn: '30分钟临时基础率' ,pl: '30 minut tymczasowej dawki bazowej' ,tr: '30 dk. geçici Bazal ' + ,hu: '30p általános bazál' } ,'1h temp basal' : { cs:'hodinový dočasný bazál' @@ -11876,6 +12409,7 @@ function init() { ,zh_cn: '1小时临时基础率' ,pl: '1 godzina tymczasowej dawki bazowej' ,tr: '1 sa. geçici bazal' + ,hu: '10 általános bazál' } ,'Cannula change overdue!' : { cs:'Čas na výměnu set vypršel!' @@ -11886,7 +12420,7 @@ function init() { ,bg: 'Времето за смяна на сет просрочено' ,hr: 'Prošao rok za zamjenu kanile!' ,fr: 'Dépassement de date de changement de canule!' - ,ru: 'Срок замены катетера истек' + ,ru: 'Срок замены катетера помпы истек' ,sv: 'Infusionsset, bytestid överskriden' ,nb: 'Byttetid for infusjonssett overskredet' ,fi: 'Kanyylin ikä yli määräajan!' @@ -11899,6 +12433,7 @@ function init() { ,zh_cn: '超过更换管路的时间' ,pl: 'Przekroczono czas wymiany wkłucia!' ,tr: 'Kanül değişimi gecikmiş!' + ,hu: 'Kanil cseréjének ideje elmúlt' } ,'Time to change cannula' : { cs:'Čas na výměnu setu' @@ -11909,7 +12444,7 @@ function init() { ,ro: 'Este vremea să schimbați canula' ,bg: 'Време за смяна на сет' ,hr: 'Vrijeme za zamjenu kanile' - ,ru: 'Пора заменить катетер' + ,ru: 'Пора заменить катетер помпы' ,sv: 'Dags att byta infusionsset' ,nb: 'På tide å bytte infusjonssett' ,fi: 'Aika vaihtaa kanyyli' @@ -11922,6 +12457,7 @@ function init() { ,zh_cn: '已到更换管路的时间' ,pl: 'Czas do wymiany wkłucia' ,tr: 'Kanül değiştirme zamanı' + ,hu: 'Ideje kicserélni a kanilt' } ,'Change cannula soon' : { cs:'Blíží se čas na výměnu setu' @@ -11932,7 +12468,7 @@ function init() { ,fr: 'Changement de canule bientòt' ,bg: 'Смени сета скоро' ,hr: 'Zamijena kanile uskoro' - ,ru: 'Приближается время замены катетера' + ,ru: 'Приближается время замены катетера помпы' ,sv: 'Byt infusionsset snart' ,nb: 'Bytt infusjonssett snart' ,fi: 'Vaihda kanyyli pian' @@ -11944,6 +12480,7 @@ function init() { ,zh_cn: '接近更换管路的时间' ,pl: 'Wkrótce wymiana wkłucia' ,tr: 'Yakında kanül değiştirin' + ,hu: 'Hamarosan cseréld ki a kanilt' } ,'Cannula age %1 hours' : { cs:'Stáří setu %1 hodin' @@ -11954,7 +12491,7 @@ function init() { ,ro: 'Vechimea canulei în ore: %1' ,bg: 'Сетът е на %1 часове' ,hr: 'Staros kanile %1 sati' - ,ru: 'Катетер отработал %1 час' + ,ru: 'Катетер помпы работает %1 час' ,sv: 'Infusionsset tid %1 timmar' ,nb: 'infusjonssett alder %1 timer' ,fi: 'Kanyylin ikä %1 tuntia' @@ -11967,6 +12504,7 @@ function init() { ,zh_cn: '管路已使用%1小时' ,pl: 'Czas od wymiany wkłucia %1 godzin' ,tr: 'Kanül yaşı %1 saat' + ,hu: 'Kamil életkora %1 óra' } ,'Inserted' : { cs:'Nasazený' @@ -11991,6 +12529,7 @@ function init() { ,zh_tw: '已植入' ,pl: 'Zamontowano' ,tr: 'Yerleştirilmiş' + ,hu: 'Behelyezve' } ,'CAGE' : { @@ -12002,7 +12541,7 @@ function init() { ,bg: 'ВС' ,hr: 'Starost kanile' ,fr: 'CAGE' - ,ru: 'ОтрабКат' + ,ru: 'КатПомп' ,sv: 'Nål' ,nb: 'Nål alder' ,fi: 'KIKÄ' @@ -12016,6 +12555,7 @@ function init() { ,zh_tw: '管路' ,pl: 'Wiek wkłucia' ,tr: 'CAGE' + ,hu: 'CAGE' } ,'COB' : { cs:'SACH' @@ -12026,7 +12566,7 @@ function init() { ,bg: 'АВХ' ,hr: 'Aktivni UGH' ,fr: 'COB' - ,ru: 'Активн углеводы COB' + ,ru: 'АктУгл COB' ,sv: 'COB' ,nb: 'Aktive karbohydrater' ,fi: 'AH' @@ -12039,6 +12579,7 @@ function init() { ,zh_cn: '活性碳水COB' ,pl: 'Aktywne węglowodany' ,tr: 'COB' + ,hu: 'COB' } ,'Last Carbs' : { cs:'Poslední sacharidy' @@ -12049,7 +12590,7 @@ function init() { ,fr: 'Derniers glucides' ,bg: 'Последни ВХ' ,hr: 'Posljednji UGH' - ,ru: 'Новые углеводы' + ,ru: 'Прошлые углеводы' ,sv: 'Senaste kolhydrater' ,nb: 'Siste karbohydrater' ,fi: 'Viimeisimmät hiilihydraatit' @@ -12062,6 +12603,7 @@ function init() { ,zh_cn: '上次碳水' ,pl: 'Ostatnie węglowodany' ,tr: 'Son Karbonhidrat' + ,hu: 'Utolsó szénhidrátok' } ,'IAGE' : { cs:'INZ' @@ -12086,6 +12628,7 @@ function init() { ,zh_tw: '胰島素' ,pl: 'Wiek insuliny' ,tr: 'IAGE' + ,hu: 'IAGE' } ,'Insulin reservoir change overdue!' : { cs:'Čas na výměnu zásobníku vypršel!' @@ -12109,6 +12652,7 @@ function init() { ,zh_cn: '超过更换胰岛素储液器的时间' ,pl: 'Przekroczono czas wymiany zbiornika na insulinę!' ,tr: 'İnsülin rezervuarı değişimi gecikmiş!' + ,hu: 'Inzulin tartály cseréjének ideje elmúlt' } ,'Time to change insulin reservoir' : { cs:'Čas na výměnu zásobníku' @@ -12132,6 +12676,7 @@ function init() { ,zh_cn: '已到更换胰岛素储液器的时间' ,pl: 'Czas do zmiany zbiornika na insulinę!' ,tr: 'İnsülin rezervuarını değiştirme zamanı!' + ,hu: 'Itt az ideje az inzulin tartály cseréjének' } ,'Change insulin reservoir soon' : { cs:'Blíží se čas na výměnu zásobníku' @@ -12155,6 +12700,7 @@ function init() { ,zh_cn: '接近更换胰岛素储液器的时间' ,pl: 'Wkrótce wymiana zbiornika na insulinę!' ,tr: 'Yakında insülin rezervuarını değiştirin' + ,hu: 'Hamarosan cseréld ki az inzulin tartályt' } ,'Insulin reservoir age %1 hours' : { cs:'Stáří zásobníku %1 hodin' @@ -12178,6 +12724,7 @@ function init() { ,zh_cn: '胰岛素储液器已使用%1小时' ,pl: 'Wiek zbiornika na insulinę %1 godzin' ,tr: 'İnsülin rezervuar yaşı %1 saat' + ,hu: 'Az inzulin tartály %1 órája volt cserélve' } ,'Changed' : { cs:'Vyměněno' @@ -12201,6 +12748,7 @@ function init() { ,zh_cn: '已更换' ,pl: 'Wymieniono' ,tr: 'Değişmiş' + ,hu: 'Cserélve' } ,'IOB' : { cs:'IOB' @@ -12208,7 +12756,7 @@ function init() { ,de: 'IOB' ,dk: 'IOB' ,ro: 'IOB' - ,ru: 'Активный Инсулин IOB' + ,ru: 'АктИнс IOB' ,fr: 'IOB' ,bg: 'АИ' ,hr: 'Aktivni inzulin' @@ -12224,6 +12772,7 @@ function init() { ,zh_cn: '活性胰岛素IOB' ,pl: 'Aktywna insulina' ,tr: 'IOB' + ,hu: 'IOB' } ,'Careportal IOB' : { cs:'IOB z ošetření' @@ -12231,7 +12780,7 @@ function init() { ,de: 'Careportal IOB' ,dk: 'IOB i Careportal' ,ro: 'IOB în Careportal' - ,ru: 'Активн Инс на портале назначений' + ,ru: 'АктИнс на портале лечения' ,fr: 'Careportal IOB' ,bg: 'АИ от Кеърпортал' ,hr: 'Careportal IOB' @@ -12247,6 +12796,7 @@ function init() { ,zh_cn: '服务面板IOB(活性胰岛素)' ,pl: 'Aktywna insulina z portalu' ,tr: 'Careportal IOB (Aktif İnsülin)' + ,hu: 'Careportal IOB érték' } ,'Last Bolus' : { cs:'Poslední bolus' @@ -12270,6 +12820,7 @@ function init() { ,zh_cn: '上次大剂量' ,pl: 'Ostatni bolus' ,tr: 'Son Bolus' + ,hu: 'Utolsó bólus' } ,'Basal IOB' : { cs:'IOB z bazálů' @@ -12277,7 +12828,7 @@ function init() { ,de: 'Basal IOB' ,dk: 'Basal IOB' ,ro: 'IOB bazală' - ,ru: 'Активн Базал IOB' + ,ru: 'АктуальнБазал IOB' ,fr: 'IOB du débit basal' ,bg: 'Базален АИ' ,hr: 'Bazalni aktivni inzulin' @@ -12293,6 +12844,7 @@ function init() { ,zh_cn: '基础率IOB(活性胰岛素)' ,pl: 'Aktywna insulina z dawki bazowej' ,tr: 'Bazal IOB' + ,hu: 'Bazál IOB' } ,'Source' : { cs:'Zdroj' @@ -12316,6 +12868,7 @@ function init() { ,zh_cn: '来源' ,pl: 'Źródło' ,tr: 'Kaynak' + ,hu: 'Forrás' } ,'Stale data, check rig?' : { cs:'Zastaralá data, zkontrolovat mobil?' @@ -12324,21 +12877,22 @@ function init() { ,dk: 'Gammel data, kontrollere uploader?' ,ro: 'Date învechite, verificați uploaderul!' ,fr: 'Valeurs trop anciennes, vérifier l\'uploadeur' - ,ru: 'Устаревшие данные, проверьте загрузчик' + ,ru: 'Старые данные, проверьте загрузчик' ,bg: 'Стари данни, провери телефона' ,hr: 'Nedostaju podaci, provjera opreme?' ,es: 'Datos desactualizados, controlar la subida?' ,sv: 'Gammal data, kontrollera rigg?' ,nb: 'Gamle data, sjekk rigg?' ,fi: 'Tiedot vanhoja, tarkista lähetin?' + , pl: 'Dane są nieaktualne, sprawdź urządzenie transmisyjne.' ,pt: 'Dados antigos, verificar uploader?' ,sk: 'Zastaralé dáta, skontrolujte uploader' ,ko: '오래된 데이터입니다. 확인해 보시겠습니까?' ,it: 'dati non aggiornati, controllare il telefono?' ,nl: 'Geen data, controleer uploader' ,zh_cn: '数据过期,检查一下设备?' - , pl: 'Dane są nieaktualne, sprawdź urządzenie transmisyjne.' ,tr: 'Veri güncel değil, vericiyi kontrol et?' + ,hu: 'Öreg adatok, ellenőrizd a feltöltőt' } ,'Last received:' : { cs:'Naposledy přijato:' @@ -12347,7 +12901,7 @@ function init() { ,dk: 'Senest modtaget:' ,fr: 'Dernière réception:' ,ro: 'Ultimile date:' - ,ru: 'Предыдущий полученный' + ,ru: 'Получено:' ,bg: 'Последно получени' ,hr: 'Zadnji podaci od:' ,sv: 'Senast mottagen:' @@ -12362,6 +12916,7 @@ function init() { ,zh_cn: '上次接收:' ,pl: 'Ostatnio odebrane:' ,tr: 'Son alınan:' + ,hu: 'Utóljára fogadott:' } ,'%1m ago' : { cs:'%1m zpět' @@ -12370,7 +12925,7 @@ function init() { ,dk: '%1m siden' ,ro: 'acum %1 minute' ,fr: 'il y a %1 min' - ,ru: 'мин назад' + ,ru: '% мин назад' ,bg: 'преди %1 мин.' ,hr: 'prije %1m' ,sv: '%1m sedan' @@ -12385,6 +12940,7 @@ function init() { ,zh_cn: '%1分钟前' ,pl: '%1 minut temu' ,tr: '%1 dk. önce' + ,hu: '%1p ezelőtt' } ,'%1h ago' : { cs:'%1h zpět' @@ -12393,7 +12949,7 @@ function init() { ,dk: '%1t siden' ,ro: 'acum %1 ore' ,fr: '%1 heures plus tôt' - ,ru: 'час назад' + ,ru: '% час назад' ,bg: 'преди %1 час' ,hr: 'prije %1 sati' ,sv: '%1h sedan' @@ -12408,6 +12964,7 @@ function init() { ,zh_cn: '%1小时前' ,pl: '%1 godzin temu' ,tr: '%1 sa. önce' + ,hu: '%1ó ezelőtt' } ,'%1d ago' : { cs:'%1d zpět' @@ -12416,7 +12973,7 @@ function init() { ,dk: '%1d siden' ,ro: 'acum %1 zile' ,fr: '%1 jours plus tôt' - ,ru: 'дн назад' + ,ru: '% дн назад' ,bg: 'преди %1 ден' ,hr: 'prije %1 dana' ,sv: '%1d sedan' @@ -12431,6 +12988,7 @@ function init() { ,zh_cn: '%1天前' ,pl: '%1 dni temu' ,tr: '%1 gün önce' + ,hu: '%1n ezelőtt' } ,'RETRO' : { cs:'RETRO' @@ -12454,6 +13012,7 @@ function init() { ,zh_cn: '历史数据' ,pl: 'RETRO' ,tr: 'RETRO Geçmiş' + ,hu: 'RETRO' } ,'SAGE' : { cs:'SENZ' @@ -12461,7 +13020,7 @@ function init() { ,de:'SAGE' ,dk: 'Sensoralder' ,ro: 'VS' - ,ru: 'Сенсор проработал' + ,ru: 'Сенсор работает' ,fr: 'SAGE' ,bg: 'ВС' ,hr: 'Starost senzora' @@ -12478,6 +13037,7 @@ function init() { ,zh_tw: '探頭' ,pl: 'Wiek sensora' ,tr: 'SAGE' + ,hu: 'SAGE' } ,'Sensor change/restart overdue!' : { cs:'Čas na výměnu senzoru vypršel!' @@ -12501,6 +13061,7 @@ function init() { ,zh_cn: '超过更换/重启探头的时间' ,pl: 'Przekroczono czas wymiany/restartu sensora!' ,tr: 'Sensör değişimi/yeniden başlatma gecikti!' + ,hu: 'Szenzor cseréjének / újraindításának ideje lejárt' } ,'Time to change/restart sensor' : { cs:'Čas na výměnu senzoru' @@ -12524,6 +13085,7 @@ function init() { ,zh_cn: '已到更换/重启探头的时间' ,pl: 'Czas do wymiany/restartu sensora' ,tr: 'Sensörü değiştirme/yeniden başlatma zamanı' + ,hu: 'Ideje a szenzort cserélni / újraindítani' } ,'Change/restart sensor soon' : { cs:'Blíží se čas na výměnu senzoru' @@ -12547,6 +13109,7 @@ function init() { ,zh_cn: '接近更换/重启探头的时间' ,pl: 'Wkrótce czas wymiany/restartu sensora' ,tr: 'Sensörü yakında değiştir/yeniden başlat' + ,hu: 'Hamarosan indítsd újra vagy cseréld ki a szenzort' } ,'Sensor age %1 days %2 hours' : { cs:'Stáří senzoru %1 dní %2 hodin' @@ -12555,7 +13118,7 @@ function init() { ,dk: 'Sensoralder %1 dage %2 timer' ,ro: 'Senzori vechi de %1 zile și %2 ore' ,fr: 'Âge su senseur %1 jours et %2 heures' - ,ru: 'Сенсор отработал % дн % час' + ,ru: 'Сенсор работает %1 дн %2 час' ,bg: 'Сензорът е на %1 дни %2 часа ' ,hr: 'Starost senzora %1 dana i %2 sati' ,sv: 'Sensorålder %1 dagar %2 timmar' @@ -12570,6 +13133,7 @@ function init() { ,zh_cn: '探头使用了%1天%2小时' ,pl: 'Wiek sensora: %1 dni %2 godzin' ,tr: 'Sensör yaşı %1 gün %2 saat' + ,hu: 'Szenzor ideje %1 nap és %2 óra' } ,'Sensor Insert' : { cs: 'Výměna sensoru' @@ -12578,7 +13142,7 @@ function init() { ,dk: 'Sensor isat' ,ro: 'Inserția senzorului' ,fr: 'Insertion du senseur' - ,ru: 'Установка сенсора' + ,ru: 'Сенсор установлен' ,bg: 'Поставяне на сензора' ,hr: 'Postavljanje senzora' ,sv: 'Sensor insättning' @@ -12593,6 +13157,7 @@ function init() { ,zh_cn: '植入探头' ,pl: 'Zamontuj sensor' ,tr: 'Sensor yerleştirme' + ,hu: 'Szenzor behelyezve' } ,'Sensor Start' : { cs: 'Znovuspuštění sensoru' @@ -12607,6 +13172,7 @@ function init() { ,sv: 'Sensorstart' ,nb: 'Sensorstart' ,fi: 'Sensorin Aloitus' + ,pl: 'Uruchomienie sensora' ,pt: 'Início de sensor' ,es: 'Inicio del sensor' ,sk: 'Štart senzoru' @@ -12614,8 +13180,8 @@ function init() { ,it: 'SAGE - partenza sensore' ,nl: 'Sensor start' ,zh_cn: '启动探头' - ,pl: 'Uruchom sensor' ,tr: 'Sensör başlatma' + ,hu: 'Szenzor indítása' } ,'days' : { cs: 'dní' @@ -12639,6 +13205,7 @@ function init() { ,zh_cn: '天' ,pl: 'dni' ,tr: 'Gün' + ,hu: 'napok' } ,'Insulin distribution' : { cs: 'Rozložení inzulínu' @@ -12659,6 +13226,7 @@ function init() { ,hr: 'Raspodjela inzulina' ,pl: 'podawanie insuliny' ,tr: 'İnsülin dağılımı' + ,hu: 'Inzulin disztribúció' } ,'To see this report, press SHOW while in this view' : { cs: 'Pro zobrazení toho výkazu stiskněte Zobraz na této záložce' @@ -12677,8 +13245,9 @@ function init() { ,sv: 'För att se denna rapport, klicka på "Visa"' ,bg: 'За да видите тази статистика, натиснете ПОКАЖИ' ,hr: 'Za prikaz ovog izvješća, pritisnite PRIKAŽI na ovom prozoru' - , pl: 'Aby wyświetlić ten raport, naciśnij przycisk POKAŻ w tym widoku' + ,pl: 'Aby wyświetlić ten raport, naciśnij przycisk POKAŻ w tym widoku' ,tr: 'Bu raporu görmek için bu görünümde GÖSTER düğmesine basın.' + ,hu: 'A jelentés megtekintéséhez kattints a MUTASD gombra' } ,'AR2 Forecast' : { cs: 'AR2 predikci' @@ -12699,6 +13268,7 @@ function init() { ,hr: 'AR2 procjena' ,pl: 'Prognoza AR2' ,tr: 'AR2 Tahmini' + ,hu: 'AR2 előrejelzés' } ,'OpenAPS Forecasts' : { cs: 'OpenAPS predikci' @@ -12719,6 +13289,7 @@ function init() { ,hr: 'OpenAPS prognoze' ,pl: 'Prognoza OpenAPS' ,tr: 'OpenAPS Tahminleri' + ,hu: 'OpenAPS előrejelzés' } ,'Temporary Target' : { cs: 'Dočasný cíl glykémie' @@ -12727,7 +13298,7 @@ function init() { ,dk: 'Midlertidigt mål' ,fr: 'Cible temporaire' ,ro: 'Țintă temporară' - ,ru: 'промежуточная цель' + ,ru: 'Временная цель' ,fi: 'Tilapäinen tavoite' ,es: 'Objetivo temporal' ,ko: '임시목표' @@ -12739,6 +13310,7 @@ function init() { ,hr: 'Privremeni cilj' ,pl: 'Cel tymczasowy' ,tr: 'Geçici Hedef' + ,hu: 'Átmeneti cél' } ,'Temporary Target Cancel' : { cs: 'Dočasný cíl glykémie konec' @@ -12747,7 +13319,7 @@ function init() { ,dk: 'Afslut midlertidigt mål' ,fr: 'Effacer la cible temporaire' ,ro: 'Renunțare la ținta temporară' - ,ru: 'отмена промежуточной цели' + ,ru: 'Отмена временной цели' ,fi: 'Peruuta tilapäinen tavoite' ,es: 'Objetivo temporal cancelado' ,ko: '임시목표취소' @@ -12759,6 +13331,7 @@ function init() { ,hr: 'Otkaz privremenog cilja' ,pl: 'Zel tymczasowy anulowany' ,tr: 'Geçici Hedef İptal' + ,hu: 'Átmeneti cél törlése' } ,'OpenAPS Offline' : { cs: 'OpenAPS vypnuto' @@ -12779,6 +13352,7 @@ function init() { ,hr: 'OpenAPS odspojen' ,pl: 'OpenAPS nieaktywny' ,tr: 'OpenAPS Offline (çevrimdışı)' + ,hu: 'OpenAPS nem elérhető (offline)' } ,'Profiles' : { cs: 'Profily' @@ -12787,7 +13361,7 @@ function init() { ,dk: 'Profiler' ,fr: 'Profils' ,ro: 'Profile' - ,ru: 'профили' + ,ru: 'Профили' ,fi: 'Profiilit' ,ko: '프로파일' ,it: 'Profili' @@ -12799,6 +13373,7 @@ function init() { ,hr: 'Profili' ,pl: 'Profile' ,tr: 'Profiller' + ,hu: 'Profilok' } ,'Time in fluctuation' : { cs: 'Doba měnící se glykémie' @@ -12809,7 +13384,7 @@ function init() { ,it: 'Tempo in fluttuazione' ,ro: 'Timp în fluctuație' ,es: 'Tiempo fluctuando' - ,ru: 'время флуктуаций' + ,ru: 'Время флуктуаций' ,nl: 'Tijd met fluctuaties' ,zh_cn: '波动时间' ,sv: 'Tid i fluktation' @@ -12819,6 +13394,7 @@ function init() { ,hr: 'Vrijeme u fluktuaciji' ,pl: 'Czas fluaktacji (odchyleń)' ,tr: 'Dalgalanmada geçen süre' + ,hu: 'Kilengésben töltött idő' } ,'Time in rapid fluctuation' : { cs: 'Doba rychle se měnící glykémie' @@ -12829,7 +13405,7 @@ function init() { ,it: 'Tempo in rapida fluttuazione' ,ro: 'Timp în fluctuație rapidă' ,es: 'Tiempo fluctuando rápido' - ,ru: 'время быстрых флуктуаций' + ,ru: 'Время быстрых флуктуаций' ,nl: 'Tijd met grote fluctuaties' ,zh_cn: '快速波动时间' ,sv: 'Tid i snabb fluktation' @@ -12839,6 +13415,7 @@ function init() { ,hr: 'Vrijeme u brzoj fluktuaciji' ,pl: 'Czas szybkich fluaktacji (odchyleń)' ,tr: 'Hızlı dalgalanmalarda geçen süre' + ,hu: 'Magas kilengésekben töltött idő' } ,'This is only a rough estimation that can be very inaccurate and does not replace actual blood testing. The formula used is taken from:' : { cs: 'Toto je pouze hrubý odhad, který může být nepřesný a nenahrazuje kontrolu z krve. Vzorec je převzatý z:' @@ -12859,6 +13436,7 @@ function init() { ,hr: 'Ovo je samo gruba procjena koja može biti neprecizna i ne mijenja testiranje iz krvi. Formula je uzeta iz:' ,pl: 'To tylko przybliżona ocena, która może być bardzo niedokładna i nie może zastąpić faktycznego poziomu cukru we krwi. Zastosowano formułę:' ,tr: 'Bu bir kaba tahmindir ve çok hata içerebilir gerçek kan şekeri testlerinin yerini tutmayacaktır. Kullanılan formülde buradandır:' + ,hu: 'Ez egy nagyon durva számítás ami nem pontos és nem helyettesíti a cukorszint mérését. A képlet a következő helyről lett véve:' } , 'Filter by hours' : { cs: ' Filtr podle hodin' @@ -12868,7 +13446,7 @@ function init() { ,fr: 'Filtrer par heures' ,ro: 'Filtrare pe ore' ,es: 'Filtrar por horas' - ,ru: 'почасовой фильтр' + ,ru: 'Почасовая фильтрация' ,nl: 'Filter op uren' ,zh_cn: '按小时过滤' ,sv: 'Filtrera per timme' @@ -12878,6 +13456,7 @@ function init() { ,hr: 'Filter po satima' ,pl: 'Filtruj po godzinach' ,tr: 'Saatlere göre filtrele' + ,hu: 'Megszűrni órák alapján' } , 'Time in fluctuation and Time in rapid fluctuation measure the % of time during the examined period, during which the blood glucose has been changing relatively fast or rapidly. Lower values are better.' : { cs: 'Doba měnící se glykémie a rapidně se měnící glykémie měří % času ve zkoumaném období, během kterého se glykémie měnila relativně rychle nebo rapidně. Nižší hodnota je lepší.' @@ -12887,7 +13466,7 @@ function init() { ,it: 'Tempo in fluttuazione e Tempo in rapida fluttuazione misurano la % di tempo durante il periodo esaminato, durante il quale la glicemia stà variando velocemente o rapidamente. Bassi valori sono migliori.' ,ro: 'Timpul în fluctuație și timpul în fluctuație rapidă măsoară procentul de timp, din perioada examinată, în care glicemia din sânge a avut o variație relativ rapidă sau rapidă. Valorile mici sunt de preferat.' ,es: 'Tiempo en fluctuación y Tiempo en fluctuación rápida miden el % de tiempo del período exáminado, durante la cual la glucosa en sangre ha estado cambiando relativamente rápido o rápidamente. Valores más bajos son mejores.' - ,ru: 'время флуктуаций и время быстрых флуктуаций означает % времени в рассматриваемый период в течение которого СК менялся относительно быстро или просто быстро. Более низкие значения предпочтительней' + ,ru: 'Время флуктуаций и время быстрых флуктуаций означает % времени в рассматриваемый период в течение которого ГК менялась относительно быстро или просто быстро. Более низкие значения предпочтительней' ,nl: 'Tijd met fluctuaties of grote fluctuaties in % van de geevalueerde periode, waarbij de bloed glucose relatief snel wijzigde.Lagere waarden zijn beter.' ,zh_cn: '在检查期间血糖波动时间和快速波动时间占的时间百分比,在此期间血糖相对快速或快速地变化。百分比值越低越好。' ,sv: 'Tid i fluktuation och tid i snabb fluktuation mäter% av tiden under den undersökta perioden, under vilken blodsockret har förändrats relativt snabbt eller snabbt. Lägre värden är bättre' @@ -12897,6 +13476,7 @@ function init() { ,hr: 'Vrijeme u fluktuaciji i vrijeme u brzoj fluktuaciji mjere % vremena u gledanom periodu, tijekom kojeg se GUK mijenja relativno brzo ili brzo. Niže vrijednosti su bolje.' ,pl: 'Czas fluktuacji i szybki czas fluktuacji mierzą % czasu w badanym okresie, w którym poziom glukozy we krwi zmieniał się szybko lub bardzo szybko. Preferowane są wolniejsze zmiany' ,tr: 'Dalgalanmadaki zaman ve Hızlı dalgalanmadaki zaman, kan şekerinin nispeten hızlı veya çok hızlı bir şekilde değiştiği, incelenen dönemdeki zamanın %\'sini ölçer. Düşük değerler daha iyidir.' + ,hu: 'A sima és magas kilengésnél mért idő százalékban kifelyezve, ahol a cukorszint aránylag nagyokat változott. A kisebb értékek jobbak ebben az esetben' } , 'Mean Total Daily Change is a sum of the absolute value of all glucose excursions for the examined period, divided by the number of days. Lower is better.' : { cs: 'Průměrná celková denní změna je součet absolutních hodnoty všech glykémií za sledované období, děleno počtem dní. Nižší hodnota je lepší.' @@ -12905,7 +13485,7 @@ function init() { ,ko: '전체 일일 변동 평균은 조사된 기간동안 전체 혈당 절대값의 합을 전체 일수로 나눈 값입니다. 낮을수록 좋습니다.' ,it: 'Media Totale Giornaliera Variazioni è la somma dei valori assoluti di tutte le escursioni glicemiche per il periodo esaminato, diviso per il numero di giorni. Bassi valori sono migliori.' ,ro: 'Schimbarea medie totală zilnică este suma valorilor absolute ale tuturor excursiilor glicemice din perioada examinată, împărțite la numărul de zile. Valorile mici sunt de preferat.' - ,ru: 'усредненное ежедневное изменение это сумма абсолютных величин всех отклонений СК в рассматриваемый период, деленное на количество дней. Меньшая величина предпочтительней' + ,ru: 'Усредненное ежедневное изменение это сумма абсолютных величин всех отклонений ГК в рассматриваемый период, деленная на количество дней. Меньшая величина предпочтительней' ,es: 'El cambio medio diario total es la suma de los valores absolutos de todas las glucémias en el período examinado, dividido por el número de días. Mejor valores bajos.' ,nl: 'Gemiddelde veranderingen per dag is een som van alle waardes die uitschieten over de bekeken periode, gedeeld door het aantal dagen in deze periode. Lager is beter.' ,zh_cn: '平均每日总变化是检查期间所有血糖偏移的绝对值之和除以天数。越低越好' @@ -12916,6 +13496,7 @@ function init() { ,hr: 'Srednja ukupna dnevna promjena je suma apsolutnih vrijednosti svih pomaka u gledanom periodu, podijeljeno s brojem dana. Niže vrijednosti su bolje.' ,pl: 'Sednia całkowita dziennych zmian jest sumą wszystkich zmian glikemii w badanym okresie, podzielonym przez liczbę dni. Mniejsze są lepsze' ,tr: 'Toplam Günlük Değişim, incelenen süre için, gün sayısına bölünen tüm glukoz değerlerinin mutlak değerinin toplamıdır. Düşük değer daha iyidir.' + ,hu: 'Az átlagos napi változás az abszolút értékek összege elosztva a napok számával. A kisebb érték jobb ebben az esetben.' } , 'Mean Hourly Change is a sum of the absolute value of all glucose excursions for the examined period, divided by the number of hours in the period. Lower is better.' : { cs: 'Průměrná hodinová změna je součet absolutní hodnoty všech glykémií za sledované období, dělených počtem hodin v daném období. Nižší hodnota je lepší.' @@ -12924,7 +13505,7 @@ function init() { ,ko: '시간당 변동 평균은 조사된 기간 동안 전체 혈당 절대값의 합을 기간의 시간으로 나눈 값입니다.낮을수록 좋습니다.' ,it: 'Media Oraria Variazioni è la somma del valore assoluto di tutte le escursioni glicemiche per il periodo esaminato, diviso per il numero di ore. Bassi valori sono migliori.' ,ro: 'Variația media orară este suma valorilor absolute ale tuturor excursiilor glicemice din perioada examinată, împărțite la numărul de ore din aceeași perioadă. Valorile mici sunt de preferat.' - ,ru: 'усредненное часовое изменение это сумма абсолютных величин всех отклонений СК в рассматриваемый период, деленное на количество часов в этот период. Более низкое предпочтительней' + ,ru: 'Усредненное часовое изменение это сумма абсолютных величин всех отклонений ГК в рассматриваемый период, деленная на количество часов в этот период. Более низкое предпочтительней' ,es: 'El cambio medio por hora, es la suma del valor absoluto de todas las glucemias para el período examinado, dividido por el número de horas en el período. Más bajo es mejor.' ,nl: 'Gemiddelde veranderingen per uur is een som van alle waardes die uitschieten over de bekeken periode, gedeeld door het aantal uur in deze periode. Lager is beter.' ,zh_cn: '平均每小时变化是检查期间所有血糖偏移的绝对值之和除以该期间的小时数。 越低越好' @@ -12935,6 +13516,7 @@ function init() { ,hr: 'Srednja ukupna promjena po satu je suma apsolutnih vrijednosti svih pomaka u gledanom periodu, podijeljeno s brojem sati. Niže vrijednosti su bolje.' ,pl: 'Sednia całkowita godzinnych zmian jest sumą wszystkich zmian glikemii w badanym okresie, podzielonym przez liczbę godzin. Mniejsze są lepsze' ,tr: 'Saat başına ortalama değişim, gözlem periyodu üzerindeki tüm glikoz değişikliklerinin mutlak değerlerinin saat sayısına bölünmesiyle elde edilen toplam değerdir. Düşük değerler daha iyidir.' + ,hu: 'Az átlagos óránkénti változás az abszút értékek összege elosztva a napok számával. A kisebb érték jobb ebben az esetben.' } , 'GVI (Glycemic Variability Index) and PGS (Patient Glycemic Status) are measures developed by Dexcom, detailed can be found here.' : { cs: '">zde.' @@ -12975,6 +13558,7 @@ function init() { ,hr: '">ovdje.' ,pl: '">tutaj.' ,tr: '">buradan.' + ,hu: '">itt találhatóak.' } , 'Mean Total Daily Change' : { cs: 'Průměrná celková denní změna' @@ -12984,7 +13568,7 @@ function init() { ,ko: '전체 일일 변동 평균' ,it: 'Media Totale Giornaliera Variazioni' ,ro: 'Variația medie totală zilnică' - ,ru: 'усредненное изменение за день' + ,ru: 'Усредненное изменение за день' ,es: 'Variación media total diaria' ,nl: 'Gemiddelde veranderingen per dag' ,zh_cn: '平均每日总变化' @@ -12995,6 +13579,7 @@ function init() { ,hr: 'Srednja ukupna dnevna promjena' ,pl: 'Średnia całkowita dziennych zmian' ,tr: 'Günde toplam ortalama değişim' + ,hu: 'Áltagos napi változás' } , 'Mean Hourly Change' : { cs: 'Průměrná hodinová změna' @@ -13005,7 +13590,7 @@ function init() { ,it: 'Media Oraria Variazioni' ,ro: 'Variația medie orară' ,es: 'Variación media total por horas' - ,ru: 'усредненное изменение за час' + ,ru: 'Усредненное изменение за час' ,nl: 'Gemiddelde veranderingen per uur' ,zh_cn: '平均每小时变化' ,sv: 'Medelvärde per timme' @@ -13015,6 +13600,7 @@ function init() { ,hr: 'Srednja ukupna promjena po satu' ,pl: 'Średnia całkowita godzinnych zmian' ,tr: 'Saatte ortalama değişim' + ,hu: 'Átlagos óránkénti változás' } , 'FortyFiveDown': { bg: 'slightly dropping' @@ -13041,6 +13627,7 @@ function init() { , tr: 'biraz düşen' , zh_cn: '缓慢下降' , zh_tw: 'slightly dropping' + , hu: 'lassan csökken' }, 'FortyFiveUp': { @@ -13068,6 +13655,7 @@ function init() { , tr: 'biraz yükselen' , zh_cn: '缓慢上升' , zh_tw: 'slightly rising' + , hu: 'lassan növekszik' }, 'Flat': { bg: 'holding' @@ -13094,6 +13682,7 @@ function init() { , tr: 'sabit' , zh_cn: '平' , zh_tw: 'holding' + , hu: 'stabil' }, 'SingleUp': { bg: 'rising' @@ -13120,6 +13709,7 @@ function init() { , tr: 'yükseliyor' , zh_cn: '上升' , zh_tw: 'rising' + , hu: 'emelkedik' }, 'SingleDown': { bg: 'dropping' @@ -13146,6 +13736,7 @@ function init() { , tr: 'düşüyor' , zh_cn: '下降' , zh_tw: 'dropping' + , hu: 'csökken' }, 'DoubleDown': { bg: 'rapidly dropping' @@ -13172,6 +13763,7 @@ function init() { , tr: 'hızlı düşen' , zh_cn: '快速下降' , zh_tw: 'rapidly dropping' + , hu: 'gyorsan csökken' }, 'DoubleUp': { bg: 'rapidly rising' @@ -13198,11 +13790,12 @@ function init() { , tr: 'hızla yükselen' , zh_cn: '快速上升' , zh_tw: 'rapidly rising' + , hu: 'gyorsan emelkedik' }, 'virtAsstUnknown': { bg: 'That value is unknown at the moment. Please see your Nightscout site for more details.' , cs: 'That value is unknown at the moment. Please see your Nightscout site for more details.' - , de: 'That value is unknown at the moment. Please see your Nightscout site for more details.' + , de: 'Dieser Wert ist momentan unbekannt. Prüfe deine Nightscout-Webseite für weitere Details!' , dk: 'That value is unknown at the moment. Please see your Nightscout site for more details.' , el: 'That value is unknown at the moment. Please see your Nightscout site for more details.' , en: 'That value is unknown at the moment. Please see your Nightscout site for more details.' @@ -13218,17 +13811,18 @@ function init() { , pt: 'That value is unknown at the moment. Please see your Nightscout site for more details.' , ro: 'That value is unknown at the moment. Please see your Nightscout site for more details.' , nl: 'That value is unknown at the moment. Please see your Nightscout site for more details.' - , ru: 'That value is unknown at the moment. Please see your Nightscout site for more details.' + , ru: 'В настоящий момент величина неизвестна. Зайдите на сайт Nightscout.' , sk: 'That value is unknown at the moment. Please see your Nightscout site for more details.' , sv: 'That value is unknown at the moment. Please see your Nightscout site for more details.' , tr: 'That value is unknown at the moment. Please see your Nightscout site for more details.' , zh_cn: 'That value is unknown at the moment. Please see your Nightscout site for more details.' , zh_tw: 'That value is unknown at the moment. Please see your Nightscout site for more details.' + , hu: 'Az adat ismeretlen. Kérem nézd meg a Nightscout oldalt részletekért' }, 'virtAsstTitleAR2Forecast': { bg: 'AR2 Forecast' , cs: 'AR2 Forecast' - , de: 'AR2 Forecast' + , de: 'AR2-Vorhersage' , dk: 'AR2 Forecast' , el: 'AR2 Forecast' , en: 'AR2 Forecast' @@ -13244,17 +13838,18 @@ function init() { , pt: 'AR2 Forecast' , ro: 'AR2 Forecast' , nl: 'AR2 Forecast' - , ru: 'AR2 Forecast' + , ru: 'Прогноз AR2' , sk: 'AR2 Forecast' , sv: 'AR2 Forecast' , tr: 'AR2 Forecast' , zh_cn: 'AR2 Forecast' , zh_tw: 'AR2 Forecast' + , hu: 'AR2 Előrejelzés' }, 'virtAsstTitleCurrentBasal': { bg: 'Current Basal' , cs: 'Current Basal' - , de: 'Current Basal' + , de: 'Aktuelles Basalinsulin' , dk: 'Current Basal' , el: 'Current Basal' , en: 'Current Basal' @@ -13270,17 +13865,18 @@ function init() { , pt: 'Current Basal' , ro: 'Current Basal' , nl: 'Current Basal' - , ru: 'Current Basal' + , ru: 'Актуальный Базал' , sk: 'Current Basal' , sv: 'Current Basal' , tr: 'Current Basal' , zh_cn: 'Current Basal' , zh_tw: 'Current Basal' + , hu: 'Jelenlegi Bazál' }, 'virtAsstTitleCurrentCOB': { bg: 'Current COB' , cs: 'Current COB' - , de: 'Current COB' + , de: 'Aktuelle Kohlenhydrate' , dk: 'Current COB' , el: 'Current COB' , en: 'Current COB' @@ -13296,17 +13892,18 @@ function init() { , pt: 'Current COB' , ro: 'Current COB' , nl: 'Current COB' - , ru: 'Current COB' + , ru: 'АктивнУгл COB' , sk: 'Current COB' , sv: 'Current COB' , tr: 'Current COB' , zh_cn: 'Current COB' , zh_tw: 'Current COB' + , hu: 'Jelenlegi COB' }, 'virtAsstTitleCurrentIOB': { bg: 'Current IOB' , cs: 'Current IOB' - , de: 'Current IOB' + , de: 'Aktuelles Restinsulin' , dk: 'Current IOB' , el: 'Current IOB' , en: 'Current IOB' @@ -13322,17 +13919,45 @@ function init() { , pt: 'Current IOB' , ro: 'Current IOB' , nl: 'Current IOB' - , ru: 'Current IOB' + , ru: 'АктИнс IOB' , sk: 'Current IOB' , sv: 'Current IOB' , tr: 'Current IOB' , zh_cn: 'Current IOB' , zh_tw: 'Current IOB' + , hu: 'Jelenlegi IOB' + }, + 'virtAsstTitleLaunch': { + bg: 'Welcome to Nightscout' + , cs: 'Welcome to Nightscout' + , de: 'Willkommen bei Nightscout' + , dk: 'Welcome to Nightscout' + , el: 'Welcome to Nightscout' + , en: 'Welcome to Nightscout' + , es: 'Welcome to Nightscout' + , fi: 'Welcome to Nightscout' + , fr: 'Welcome to Nightscout' + , he: 'Welcome to Nightscout' + , hr: 'Welcome to Nightscout' + , it: 'Welcome to Nightscout' + , ko: 'Welcome to Nightscout' + , nb: 'Welcome to Nightscout' + , pl: 'Welcome to Nightscout' + , pt: 'Welcome to Nightscout' + , ro: 'Welcome to Nightscout' + , nl: 'Welcome to Nightscout' + , ru: 'Добро пожаловать в Nightscout' + , sk: 'Welcome to Nightscout' + , sv: 'Welcome to Nightscout' + , tr: 'Welcome to Nightscout' + , zh_cn: 'Welcome to Nightscout' + , zh_tw: 'Welcome to Nightscout' + , hu: 'Üdvözöllek a Nightscouton' }, 'virtAsstTitleLoopForecast': { bg: 'Loop Forecast' , cs: 'Loop Forecast' - , de: 'Loop Forecast' + , de: 'Loop-Vorhersage' , dk: 'Loop Forecast' , el: 'Loop Forecast' , en: 'Loop Forecast' @@ -13348,17 +13973,18 @@ function init() { , pt: 'Loop Forecast' , ro: 'Loop Forecast' , nl: 'Loop Forecast' - , ru: 'Loop Forecast' + , ru: 'Прогноз Loop' , sk: 'Loop Forecast' , sv: 'Loop Forecast' , tr: 'Loop Forecast' , zh_cn: 'Loop Forecast' , zh_tw: 'Loop Forecast' + , hu: 'Loop Előrejelzés' }, 'virtAsstTitleLastLoop': { bg: 'Last Loop' , cs: 'Last Loop' - , de: 'Last Loop' + , de: 'Letzter Loop' , dk: 'Last Loop' , el: 'Last Loop' , en: 'Last Loop' @@ -13374,17 +14000,18 @@ function init() { , pt: 'Last Loop' , ro: 'Last Loop' , nl: 'Last Loop' - , ru: 'Last Loop' + , ru: 'Прошлый Loop' , sk: 'Last Loop' , sv: 'Last Loop' , tr: 'Last Loop' , zh_cn: 'Last Loop' , zh_tw: 'Last Loop' + , hu: 'Utolsó Loop' }, 'virtAsstTitleOpenAPSForecast': { bg: 'OpenAPS Forecast' , cs: 'OpenAPS Forecast' - , de: 'OpenAPS Forecast' + , de: 'OpenAPS-Vorhersage' , dk: 'OpenAPS Forecast' , el: 'OpenAPS Forecast' , en: 'OpenAPS Forecast' @@ -13400,17 +14027,18 @@ function init() { , pt: 'OpenAPS Forecast' , ro: 'OpenAPS Forecast' , nl: 'OpenAPS Forecast' - , ru: 'OpenAPS Forecast' + , ru: 'Прогноз OpenAPS' , sk: 'OpenAPS Forecast' , sv: 'OpenAPS Forecast' , tr: 'OpenAPS Forecast' , zh_cn: 'OpenAPS Forecast' , zh_tw: 'OpenAPS Forecast' + , hu: 'OpenAPS Előrejelzés' }, 'virtAsstTitlePumpReservoir': { bg: 'Insulin Remaining' , cs: 'Insulin Remaining' - , de: 'Insulin Remaining' + , de: 'Verbleibendes Insulin' , dk: 'Insulin Remaining' , el: 'Insulin Remaining' , en: 'Insulin Remaining' @@ -13426,17 +14054,18 @@ function init() { , pt: 'Insulin Remaining' , ro: 'Insulin Remaining' , nl: 'Insulin Remaining' - , ru: 'Insulin Remaining' + , ru: 'Осталось Инсулина' , sk: 'Insulin Remaining' , sv: 'Insulin Remaining' , tr: 'Insulin Remaining' , zh_cn: 'Insulin Remaining' , zh_tw: 'Insulin Remaining' + , hu: 'Fennmaradó inzulin' }, 'virtAsstTitlePumpBattery': { bg: 'Pump Battery' , cs: 'Pump Battery' - , de: 'Pump Battery' + , de: 'Pumpenbatterie' , dk: 'Pump Battery' , el: 'Pump Battery' , en: 'Pump Battery' @@ -13452,17 +14081,18 @@ function init() { , pt: 'Pump Battery' , ro: 'Pump Battery' , nl: 'Pump Battery' - , ru: 'Pump Battery' + , ru: 'Батарея помпы' , sk: 'Pump Battery' , sv: 'Pump Battery' , tr: 'Pump Battery' , zh_cn: 'Pump Battery' , zh_tw: 'Pump Battery' + , hu: 'Pumpa töltöttsége' }, 'virtAsstTitleRawBG': { bg: 'Current Raw BG' , cs: 'Current Raw BG' - , de: 'Current Raw BG' + , de: 'Aktueller Blutzucker-Rohwert' , dk: 'Current Raw BG' , el: 'Current Raw BG' , en: 'Current Raw BG' @@ -13478,17 +14108,18 @@ function init() { , pt: 'Current Raw BG' , ro: 'Current Raw BG' , nl: 'Current Raw BG' - , ru: 'Current Raw BG' + , ru: 'Актуальн RAW ГК ' , sk: 'Current Raw BG' , sv: 'Current Raw BG' , tr: 'Current Raw BG' , zh_cn: 'Current Raw BG' , zh_tw: 'Current Raw BG' + , hu: 'Jelenlegi nyers cukorszint' }, 'virtAsstTitleUploaderBattery': { bg: 'Uploader Battery' , cs: 'Uploader Battery' - , de: 'Uploader Battery' + , de: 'Uploader Batterie' , dk: 'Uploader Battery' , el: 'Uploader Battery' , en: 'Uploader Battery' @@ -13504,17 +14135,18 @@ function init() { , pt: 'Uploader Battery' , ro: 'Uploader Battery' , nl: 'Uploader Battery' - , ru: 'Uploader Battery' + , ru: 'Батарея загрузчика' , sk: 'Uploader Battery' , sv: 'Uploader Battery' , tr: 'Uploader Battery' , zh_cn: 'Uploader Battery' - , zh_tw: 'Uploader Battery' + , zh_tw: 'Current Raw BG' + , hu: 'Feltöltő töltöttsége' }, 'virtAsstTitleCurrentBG': { bg: 'Current BG' , cs: 'Current BG' - , de: 'Current BG' + , de: 'Aktueller Blutzucker' , dk: 'Current BG' , el: 'Current BG' , en: 'Current BG' @@ -13530,17 +14162,18 @@ function init() { , pt: 'Current BG' , ro: 'Current BG' , nl: 'Current BG' - , ru: 'Current BG' + , ru: 'Актуальная ГК' , sk: 'Current BG' , sv: 'Current BG' , tr: 'Current BG' , zh_cn: 'Current BG' , zh_tw: 'Current BG' + , hu: 'Jelenlegi Cukorszint' }, 'virtAsstTitleFullStatus': { bg: 'Full Status' , cs: 'Full Status' - , de: 'Full Status' + , de: 'Gesamtstatus' , dk: 'Full Status' , el: 'Full Status' , en: 'Full Status' @@ -13556,12 +14189,201 @@ function init() { , pt: 'Full Status' , ro: 'Full Status' , nl: 'Full Status' - , ru: 'Full Status' + , ru: 'Полная информация о статусе' , sk: 'Full Status' , sv: 'Full Status' , tr: 'Full Status' , zh_cn: 'Full Status' , zh_tw: 'Full Status' + , hu: 'Teljes Státusz' + }, + 'virtAsstTitleCGMMode': { + bg: 'CGM Mode' + , cs: 'CGM Mode' + , de: 'CGM Mode' + , dk: 'CGM Mode' + , el: 'CGM Mode' + , en: 'CGM Mode' + , es: 'CGM Mode' + , fi: 'CGM Mode' + , fr: 'CGM Mode' + , he: 'CGM Mode' + , hr: 'CGM Mode' + , it: 'CGM Mode' + , ko: 'CGM Mode' + , nb: 'CGM Mode' + , pl: 'CGM Mode' + , pt: 'CGM Mode' + , ro: 'CGM Mode' + , nl: 'CGM Mode' + , ru: 'CGM Mode' + , sk: 'CGM Mode' + , sv: 'CGM Mode' + , tr: 'CGM Mode' + , zh_cn: 'CGM Mode' + , zh_tw: 'CGM Mode' + , hu: 'CGM Mód' + }, + 'virtAsstTitleCGMStatus': { + bg: 'CGM Status' + , cs: 'CGM Status' + , de: 'CGM Status' + , dk: 'CGM Status' + , el: 'CGM Status' + , en: 'CGM Status' + , es: 'CGM Status' + , fi: 'CGM Status' + , fr: 'CGM Status' + , he: 'CGM Status' + , hr: 'CGM Status' + , it: 'CGM Status' + , ko: 'CGM Status' + , nb: 'CGM Status' + , pl: 'CGM Status' + , pt: 'CGM Status' + , ro: 'CGM Status' + , nl: 'CGM Status' + , ru: 'CGM Status' + , sk: 'CGM Status' + , sv: 'CGM Status' + , tr: 'CGM Status' + , zh_cn: 'CGM Status' + , zh_tw: 'CGM Status' + , hu: 'CGM Státusz' + }, + 'virtAsstTitleCGMSessionAge': { + bg: 'CGM Session Age' + , cs: 'CGM Session Age' + , de: 'CGM Session Age' + , dk: 'CGM Session Age' + , el: 'CGM Session Age' + , en: 'CGM Session Age' + , es: 'CGM Session Age' + , fi: 'CGM Session Age' + , fr: 'CGM Session Age' + , he: 'CGM Session Age' + , hr: 'CGM Session Age' + , it: 'CGM Session Age' + , ko: 'CGM Session Age' + , nb: 'CGM Session Age' + , pl: 'CGM Session Age' + , pt: 'CGM Session Age' + , ro: 'CGM Session Age' + , nl: 'CGM Session Age' + , ru: 'CGM Session Age' + , sk: 'CGM Session Age' + , sv: 'CGM Session Age' + , tr: 'CGM Session Age' + , zh_cn: 'CGM Session Age' + , zh_tw: 'CGM Session Age' + , hu: 'CGM életkora' + }, + 'virtAsstTitleCGMTxStatus': { + bg: 'CGM Transmitter Status' + , cs: 'CGM Transmitter Status' + , de: 'CGM Transmitter Status' + , dk: 'CGM Transmitter Status' + , el: 'CGM Transmitter Status' + , en: 'CGM Transmitter Status' + , es: 'CGM Transmitter Status' + , fi: 'CGM Transmitter Status' + , fr: 'CGM Transmitter Status' + , he: 'CGM Transmitter Status' + , hr: 'CGM Transmitter Status' + , it: 'CGM Transmitter Status' + , ko: 'CGM Transmitter Status' + , nb: 'CGM Transmitter Status' + , pl: 'CGM Transmitter Status' + , pt: 'CGM Transmitter Status' + , ro: 'CGM Transmitter Status' + , nl: 'CGM Transmitter Status' + , ru: 'CGM Transmitter Status' + , sk: 'CGM Transmitter Status' + , sv: 'CGM Transmitter Status' + , tr: 'CGM Transmitter Status' + , zh_cn: 'CGM Transmitter Status' + , zh_tw: 'CGM Transmitter Status' + , hu: 'CGM kapcsolat státusza' + }, + 'virtAsstTitleCGMTxAge': { + bg: 'CGM Transmitter Age' + , cs: 'CGM Transmitter Age' + , de: 'CGM Transmitter Age' + , dk: 'CGM Transmitter Age' + , el: 'CGM Transmitter Age' + , en: 'CGM Transmitter Age' + , es: 'CGM Transmitter Age' + , fi: 'CGM Transmitter Age' + , fr: 'CGM Transmitter Age' + , he: 'CGM Transmitter Age' + , hr: 'CGM Transmitter Age' + , it: 'CGM Transmitter Age' + , ko: 'CGM Transmitter Age' + , nb: 'CGM Transmitter Age' + , pl: 'CGM Transmitter Age' + , pt: 'CGM Transmitter Age' + , ro: 'CGM Transmitter Age' + , nl: 'CGM Transmitter Age' + , ru: 'CGM Transmitter Age' + , sk: 'CGM Transmitter Age' + , sv: 'CGM Transmitter Age' + , tr: 'CGM Transmitter Age' + , zh_cn: 'CGM Transmitter Age' + , zh_tw: 'CGM Transmitter Age' + }, + 'virtAsstTitleCGMNoise': { + bg: 'CGM Noise' + , cs: 'CGM Noise' + , de: 'CGM Noise' + , dk: 'CGM Noise' + , el: 'CGM Noise' + , en: 'CGM Noise' + , es: 'CGM Noise' + , fi: 'CGM Noise' + , fr: 'CGM Noise' + , he: 'CGM Noise' + , hr: 'CGM Noise' + , it: 'CGM Noise' + , ko: 'CGM Noise' + , nb: 'CGM Noise' + , pl: 'CGM Noise' + , pt: 'CGM Noise' + , ro: 'CGM Noise' + , nl: 'CGM Noise' + , ru: 'CGM Noise' + , sk: 'CGM Noise' + , sv: 'CGM Noise' + , tr: 'CGM Noise' + , zh_cn: 'CGM Noise' + , zh_tw: 'CGM Noise' + , hu: 'CGM Zaj' + }, + 'virtAsstTitleDelta': { + bg: 'Blood Glucose Delta' + , cs: 'Blood Glucose Delta' + , de: 'Blutzucker-Delta' + , dk: 'Blood Glucose Delta' + , el: 'Blood Glucose Delta' + , en: 'Blood Glucose Delta' + , es: 'Blood Glucose Delta' + , fi: 'Blood Glucose Delta' + , fr: 'Blood Glucose Delta' + , he: 'Blood Glucose Delta' + , hr: 'Blood Glucose Delta' + , it: 'Blood Glucose Delta' + , ko: 'Blood Glucose Delta' + , nb: 'Blood Glucose Delta' + , pl: 'Blood Glucose Delta' + , pt: 'Blood Glucose Delta' + , ro: 'Blood Glucose Delta' + , nl: 'Blood Glucose Delta' + , ru: 'Дельта ГК' + , sk: 'Blood Glucose Delta' + , sv: 'Blood Glucose Delta' + , tr: 'Blood Glucose Delta' + , zh_cn: 'Blood Glucose Delta' + , zh_tw: 'Blood Glucose Delta' + , hu: 'Csukoszint delta' }, 'virtAsstStatus': { bg: '%1 and %2 as of %3.' @@ -13588,6 +14410,7 @@ function init() { , tr: '%1 ve %2 e kadar %3.' , zh_cn: '%1 和 %2 到 %3.' , zh_tw: '%1 and %2 as of %3.' + , hu: '%1 es %2 %3-tól.' }, 'virtAsstBasal': { bg: '%1 současný bazál je %2 jednotek za hodinu' @@ -13614,6 +14437,7 @@ function init() { , tr: '%1 geçerli bazal oranı saatte %2 ünite' , zh_cn: '%1 当前基础率是 %2 U/小时' , zh_tw: '%1 current basal is %2 units per hour' + , hu: '%1 a jelenlegi bazál %2 egység óránként' }, 'virtAsstBasalTemp': { bg: '%1 dočasný bazál %2 jednotek za hodinu skončí %3' @@ -13640,6 +14464,7 @@ function init() { , tr: '%1 geçici bazal %2 ünite %3 sona eriyor' , zh_cn: '%1 临时基础率 %2 U/小时将会在 %3结束' , zh_tw: '%1 temp basal of %2 units per hour will end %3' + , hu: '%1 átmeneti bazál %2 egység óránként ami %3 -kor jár le' }, 'virtAsstIob': { bg: 'a máte %1 jednotek aktivního inzulínu.' @@ -13666,6 +14491,7 @@ function init() { , tr: 've Sizde %1 aktif insulin var' , zh_cn: '并且你有 %1 的活性胰岛素.' , zh_tw: 'and you have %1 insulin on board.' + , hu: 'és neked %1 inzulin van a testedben.' }, 'virtAsstIobIntent': { bg: 'Máte %1 jednotek aktivního inzulínu' @@ -13692,6 +14518,7 @@ function init() { , tr: 'Sizde %1 aktif insülin var' , zh_cn: '你有 %1 的活性胰岛素' , zh_tw: 'You have %1 insulin on board' + , hu: 'Neked %1 inzulin van a testedben' }, 'virtAsstIobUnits': { bg: '%1 units of' @@ -13718,6 +14545,34 @@ function init() { , tr: 'hala %1 birim' , zh_cn: '%1 单位' , zh_tw: '%1 units of' + , hu: '%1 egység' + }, + 'virtAsstLaunch': { + bg: 'What would you like to check on Nightscout?' + , cs: 'What would you like to check on Nightscout?' + , de: 'Was möchtest du von Nightscout wissen?' + , dk: 'What would you like to check on Nightscout?' + , el: 'What would you like to check on Nightscout?' + , en: 'What would you like to check on Nightscout?' + , es: 'What would you like to check on Nightscout?' + , fi: 'What would you like to check on Nightscout?' + , fr: 'What would you like to check on Nightscout?' + , he: 'What would you like to check on Nightscout?' + , hr: 'What would you like to check on Nightscout?' + , it: 'What would you like to check on Nightscout?' + , ko: 'What would you like to check on Nightscout?' + , nb: 'What would you like to check on Nightscout?' + , pl: 'What would you like to check on Nightscout?' + , pt: 'What would you like to check on Nightscout?' + , ro: 'What would you like to check on Nightscout?' + , nl: 'What would you like to check on Nightscout?' + , ru: 'Что проверить в Nightscout?' + , sk: 'What would you like to check on Nightscout?' + , sv: 'What would you like to check on Nightscout?' + , tr: 'What would you like to check on Nightscout?' + , zh_cn: 'What would you like to check on Nightscout?' + , zh_tw: 'What would you like to check on Nightscout?' + , hu: 'Mit szeretnél ellenőrizni a Nightscout oldalon?' }, 'virtAsstPreamble': { bg: 'Your' @@ -13744,6 +14599,7 @@ function init() { , tr: 'Senin' , zh_cn: '你的' , zh_tw: 'Your' + , hu: 'A tied' }, 'virtAsstPreamble3person': { bg: '%1 has a ' @@ -13770,6 +14626,7 @@ function init() { , tr: '%1 bir tane var' , zh_cn: '%1 有一个 ' , zh_tw: '%1 has a ' + , hu: '%1 -nak van ' }, 'virtAsstNoInsulin': { bg: 'no' @@ -13796,13 +14653,14 @@ function init() { , tr: 'yok' , zh_cn: '否' , zh_tw: 'no' + , hu: 'semmilyen' }, 'virtAsstUploadBattery': { bg: 'Your uploader battery is at %1' , cs: 'Baterie mobilu má %1' , en: 'Your uploader battery is at %1' , hr: 'Your uploader battery is at %1' - , de: 'Der Akku deines Uploader Handys ist bei %1' + , de: 'Der Akku deines Uploader-Handys ist bei %1' , dk: 'Din uploaders batteri er %1' , ko: 'Your uploader battery is at %1' , nl: 'De batterij van je mobiel is bij %l' @@ -13813,6 +14671,7 @@ function init() { , pl: 'Twoja bateria ma %1' , ru: 'батарея загрузчика %1' , tr: 'Yükleyici piliniz %1' + , hu: 'A felöltőd töltöttsége %1' }, 'virtAsstReservoir': { bg: 'You have %1 units remaining' @@ -13830,6 +14689,7 @@ function init() { , pl: 'W zbiorniku pozostało %1 jednostek' , ru: 'остается %1 ед' , tr: '%1 birim kaldı' + , hu: '%1 egység maradt hátra' }, 'virtAsstPumpBattery': { bg: 'Your pump battery is at %1 %2' @@ -13847,13 +14707,14 @@ function init() { , pl: 'Bateria pompy jest w %1 %2' , ru: 'батарея помпы %1 %2' , tr: 'Pompa piliniz %1 %2' + , hu: 'A pumpád töltöttsége %1 %2' }, 'virtAsstUploaderBattery': { bg: 'Your uploader battery is at %1' , cs: 'Your uploader battery is at %1' , en: 'Your uploader battery is at %1' , hr: 'Your uploader battery is at %1' - , de: 'Your uploader battery is at %1' + , de: 'Der Akku deines Uploader-Handys ist bei %1' , dk: 'Your uploader battery is at %1' , ko: 'Your uploader battery is at %1' , nl: 'Your uploader battery is at %1' @@ -13862,8 +14723,9 @@ function init() { , fi: 'Your uploader battery is at %1' , ro: 'Your uploader battery is at %1' , pl: 'Your uploader battery is at %1' - , ru: 'Your uploader battery is at %1' + , ru: 'Батарея загрузчика %1' , tr: 'Your uploader battery is at %1' + , hu: 'A feltöltőd töltöttsége %1' }, 'virtAsstLastLoop': { bg: 'The last successful loop was %1' @@ -13881,13 +14743,14 @@ function init() { , pl: 'Ostatnia pomyślna pętla była %1' , ru: 'недавний успешный цикл был %1' , tr: 'Son başarılı döngü %1 oldu' + , hu: 'Az utolsó sikeres loop %1-kor volt' }, 'virtAsstLoopNotAvailable': { bg: 'Loop plugin does not seem to be enabled' , cs: 'Plugin smyčka není patrně povolený' , en: 'Loop plugin does not seem to be enabled' , hr: 'Loop plugin does not seem to be enabled' - , de: 'Das Loop Plugin scheint nicht aktiviert zu sein' + , de: 'Das Loop-Plugin scheint nicht aktiviert zu sein' , dk: 'Loop plugin lader ikke til at være slået til' , ko: 'Loop plugin does not seem to be enabled' , nl: 'De Loop plugin is niet geactiveerd' @@ -13896,15 +14759,16 @@ function init() { , fi: 'Loop plugin ei ole aktivoitu' , ro: 'Extensia loop pare a fi dezactivată' , pl: 'Plugin Loop prawdopodobnie nie jest włączona' - , ru: 'плагин ЗЦ Loop не активирован' + , ru: 'Расширение ЗЦ Loop не активировано' , tr: 'Döngü eklentisi etkin görünmüyor' + , hu: 'A loop kiegészítés valószínűleg nincs bekapcsolva' }, 'virtAsstLoopForecastAround': { bg: 'According to the loop forecast you are expected to be around %1 over the next %2' , cs: 'Podle přepovědi smyčky je očekávána glykémie around %1 během následujících %2' , en: 'According to the loop forecast you are expected to be around %1 over the next %2' , hr: 'According to the loop forecast you are expected to be around %1 over the next %2' - , de: 'Entsprechend der Loop Vorhersage landest du bei around %1 während der nächsten %2' + , de: 'Entsprechend der Loop-Vorhersage landest in den nächsten %2 bei %1' , dk: 'Ifølge Loops forudsigelse forventes du at blive around %1 i den næste %2' , ko: 'According to the loop forecast you are expected to be around %1 over the next %2' , nl: 'Volgens de Loop voorspelling is je waarde around %1 over de volgnede %2' @@ -13913,15 +14777,16 @@ function init() { , fi: 'Ennusteen mukaan olet around %1 seuraavan %2 ajan' , ro: 'Potrivit previziunii date de loop se estiemază around %1 pentru următoarele %2' , pl: 'Zgodnie z prognozą pętli, glikemia around %1 będzie podczas następnego %2' - , ru: 'по прогнозу алгоритма ЗЦ ожидается around %1 за последующие %2' + , ru: 'по прогнозу алгоритма ЗЦ ожидается около %1 за последующие %2' , tr: 'Döngü tahminine göre sonraki %2 ye göre around %1 olması bekleniyor' + , hu: 'A loop előrejelzése alapján a követlező %2 időszakban körülbelül %1 lesz' }, 'virtAsstLoopForecastBetween': { bg: 'According to the loop forecast you are expected to be between %1 and %2 over the next %3' , cs: 'Podle přepovědi smyčky je očekávána glykémie between %1 and %2 během následujících %3' , en: 'According to the loop forecast you are expected to be between %1 and %2 over the next %3' , hr: 'According to the loop forecast you are expected to be between %1 and %2 over the next %3' - , de: 'Entsprechend der Loop Vorhersage landest du bei between %1 and %2 während der nächsten %3' + , de: 'Entsprechend der Loop-Vorhersage landest du zwischen %1 und %2 während der nächsten %3' , dk: 'Ifølge Loops forudsigelse forventes du at blive between %1 and %2 i den næste %3' , ko: 'According to the loop forecast you are expected to be between %1 and %2 over the next %3' , nl: 'Volgens de Loop voorspelling is je waarde between %1 and %2 over de volgnede %3' @@ -13930,15 +14795,16 @@ function init() { , fi: 'Ennusteen mukaan olet between %1 and %2 seuraavan %3 ajan' , ro: 'Potrivit previziunii date de loop se estiemază between %1 and %2 pentru următoarele %3' , pl: 'Zgodnie z prognozą pętli, glikemia between %1 and %2 będzie podczas następnego %3' - , ru: 'по прогнозу алгоритма ЗЦ ожидается between %1 and %2 за последующие %3' + , ru: 'по прогнозу алгоритма ЗЦ ожидается между %1 и %2 за последующие %3' , tr: 'Döngü tahminine göre sonraki %3 ye göre between %1 and %2 olması bekleniyor' + , hu: 'A loop előrejelzése alapján a követlező %3 időszakban %1 és %2 között leszel' }, 'virtAsstAR2ForecastAround': { bg: 'According to the AR2 forecast you are expected to be around %1 over the next %2' , cs: 'According to the AR2 forecast you are expected to be around %1 over the next %2' , en: 'According to the AR2 forecast you are expected to be around %1 over the next %2' , hr: 'According to the AR2 forecast you are expected to be around %1 over the next %2' - , de: 'According to the AR2 forecast you are expected to be around %1 over the next %2' + , de: 'Entsprechend der AR2-Vorhersage landest du in %2 bei %1' , dk: 'According to the AR2 forecast you are expected to be around %1 over the next %2' , ko: 'According to the AR2 forecast you are expected to be around %1 over the next %2' , nl: 'According to the AR2 forecast you are expected to be around %1 over the next %2' @@ -13947,15 +14813,16 @@ function init() { , fi: 'According to the AR2 forecast you are expected to be around %1 over the next %2' , ro: 'According to the AR2 forecast you are expected to be around %1 over the next %2' , pl: 'According to the AR2 forecast you are expected to be around %1 over the next %2' - , ru: 'According to the AR2 forecast you are expected to be around %1 over the next %2' + , ru: 'По прогнозу AR2 ожидается около %1 в следующие %2' , tr: 'According to the AR2 forecast you are expected to be around %1 over the next %2' + , hu: 'Az AR2ües előrejelzés alapján a követlező %2 időszakban körülbelül %1 lesz' }, 'virtAsstAR2ForecastBetween': { bg: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' , cs: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' , en: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' , hr: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' - , de: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' + , de: 'Entsprechend der AR2-Vorhersage landest du in %3 zwischen %1 and %2' , dk: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' , ko: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' , nl: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' @@ -13964,15 +14831,16 @@ function init() { , fi: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' , ro: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' , pl: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' - , ru: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' + , ru: 'По прогнозу AR2 ожидается между %1 и %2 в следующие %3' , tr: 'According to the AR2 forecast you are expected to be between %1 and %2 over the next %3' + , hu: 'Az AR2 előrejelzése alapján a követlező %3 időszakban %1 és %2 között leszel' }, 'virtAsstForecastUnavailable': { bg: 'Unable to forecast with the data that is available' , cs: 'S dostupnými daty přepověď není možná' , en: 'Unable to forecast with the data that is available' , hr: 'Unable to forecast with the data that is available' - , de: 'Mit den verfügbaren Daten ist eine Loop Vorhersage nicht möglich' + , de: 'Mit den verfügbaren Daten ist eine Loop-Vorhersage nicht möglich' , dk: 'Det er ikke muligt at forudsige md de tilgængelige data' , ko: 'Unable to forecast with the data that is available' , nl: 'Niet mogelijk om een voorspelling te doen met de data die beschikbaar is' @@ -13983,6 +14851,7 @@ function init() { , pl: 'Prognoza pętli nie jest możliwa, z dostępnymi danymi.' , ru: 'прогноз при таких данных невозможен' , tr: 'Mevcut verilerle tahmin edilemedi' + , hu: 'Nem tudok előrejelzést készíteni hiányos adatokból' }, 'virtAsstRawBG': { en: 'Your raw bg is %1' @@ -14000,6 +14869,7 @@ function init() { , pl: 'Glikemia RAW wynosi %1' , ru: 'ваши необработанные данные RAW %1' , tr: 'Ham kan şekeriniz %1' + , hu: 'A nyers cukorszinted %1' }, 'virtAsstOpenAPSForecast': { en: 'The OpenAPS Eventual BG is %1' @@ -14017,37 +14887,39 @@ function init() { , pl: 'Glikemia prognozowana przez OpenAPS wynosi %1' , ru: 'OpenAPS прогнозирует ваш СК как %1 ' , tr: 'OpenAPS tarafından tahmin edilen kan şekeri %1' + , hu: 'Az OpenAPS cukorszinted %1' }, 'virtAsstCob3person': { - bg: '%1 has $2 carbohydrates on board' - , cs: '%1 has $2 carbohydrates on board' - , de: '%1 has $2 carbohydrates on board' - , dk: '%1 has $2 carbohydrates on board' - , el: '%1 has $2 carbohydrates on board' - , en: '%1 has $2 carbohydrates on board' - , es: '%1 has $2 carbohydrates on board' - , fi: '%1 has $2 carbohydrates on board' - , fr: '%1 has $2 carbohydrates on board' - , he: '%1 has $2 carbohydrates on board' - , hr: '%1 has $2 carbohydrates on board' - , it: '%1 has $2 carbohydrates on board' - , ko: '%1 has $2 carbohydrates on board' - , nb: '%1 has $2 carbohydrates on board' - , nl: '%1 has $2 carbohydrates on board' - , pl: '%1 has $2 carbohydrates on board' - , pt: '%1 has $2 carbohydrates on board' - , ro: '%1 has $2 carbohydrates on board' - , ru: '%1 has $2 carbohydrates on board' - , sk: '%1 has $2 carbohydrates on board' - , sv: '%1 has $2 carbohydrates on board' - , tr: '%1 has $2 carbohydrates on board' - , zh_cn: '%1 has $2 carbohydrates on board' - , zh_tw: '%1 has $2 carbohydrates on board' + bg: '%1 has %2 carbohydrates on board' + , cs: '%1 has %2 carbohydrates on board' + , de: '%1 hat %2 Kohlenhydrate wirkend' + , dk: '%1 has %2 carbohydrates on board' + , el: '%1 has %2 carbohydrates on board' + , en: '%1 has %2 carbohydrates on board' + , es: '%1 has %2 carbohydrates on board' + , fi: '%1 has %2 carbohydrates on board' + , fr: '%1 has %2 carbohydrates on board' + , he: '%1 has %2 carbohydrates on board' + , hr: '%1 has %2 carbohydrates on board' + , it: '%1 has %2 carbohydrates on board' + , ko: '%1 has %2 carbohydrates on board' + , nb: '%1 has %2 carbohydrates on board' + , nl: '%1 has %2 carbohydrates on board' + , pl: '%1 has %2 carbohydrates on board' + , pt: '%1 has %2 carbohydrates on board' + , ro: '%1 has %2 carbohydrates on board' + , ru: '%1 имеет %2 активных углеводов' + , sk: '%1 has %2 carbohydrates on board' + , sv: '%1 has %2 carbohydrates on board' + , tr: '%1 has %2 carbohydrates on board' + , zh_cn: '%1 has %2 carbohydrates on board' + , zh_tw: '%1 has %2 carbohydrates on board' + , hu: '%1 -nak %2 szénhodrátja van a testében' }, 'virtAsstCob': { bg: 'You have %1 carbohydrates on board' , cs: 'You have %1 carbohydrates on board' - , de: 'You have %1 carbohydrates on board' + , de: 'Du hast noch %1 Kohlenhydrate wirkend.' , dk: 'You have %1 carbohydrates on board' , el: 'You have %1 carbohydrates on board' , en: 'You have %1 carbohydrates on board' @@ -14063,17 +14935,288 @@ function init() { , pl: 'You have %1 carbohydrates on board' , pt: 'You have %1 carbohydrates on board' , ro: 'You have %1 carbohydrates on board' - , ru: 'You have %1 carbohydrates on board' + , ru: 'У вас %1 активных углеводов' , sk: 'You have %1 carbohydrates on board' , sv: 'You have %1 carbohydrates on board' , tr: 'You have %1 carbohydrates on board' , zh_cn: 'You have %1 carbohydrates on board' , zh_tw: 'You have %1 carbohydrates on board' + , hu: 'Neked %1 szénhidrát van a testedben' + }, + 'virtAsstCGMMode': { + bg: 'Your CGM mode was %1 as of %2.' + , cs: 'Your CGM mode was %1 as of %2.' + , de: 'Your CGM mode was %1 as of %2.' + , dk: 'Your CGM mode was %1 as of %2.' + , el: 'Your CGM mode was %1 as of %2.' + , en: 'Your CGM mode was %1 as of %2.' + , es: 'Your CGM mode was %1 as of %2.' + , fi: 'Your CGM mode was %1 as of %2.' + , fr: 'Your CGM mode was %1 as of %2.' + , he: 'Your CGM mode was %1 as of %2.' + , hr: 'Your CGM mode was %1 as of %2.' + , it: 'Your CGM mode was %1 as of %2.' + , ko: 'Your CGM mode was %1 as of %2.' + , nb: 'Your CGM mode was %1 as of %2.' + , nl: 'Your CGM mode was %1 as of %2.' + , pl: 'Your CGM mode was %1 as of %2.' + , pt: 'Your CGM mode was %1 as of %2.' + , ro: 'Your CGM mode was %1 as of %2.' + , ru: 'Your CGM mode was %1 as of %2.' + , sk: 'Your CGM mode was %1 as of %2.' + , sv: 'Your CGM mode was %1 as of %2.' + , tr: 'Your CGM mode was %1 as of %2.' + , zh_cn: 'Your CGM mode was %1 as of %2.' + , zh_tw: 'Your CGM mode was %1 as of %2.' + , hu: 'A CGM módod %1 volt %2 -kor.' + }, + 'virtAsstCGMStatus': { + bg: 'Your CGM status was %1 as of %2.' + , cs: 'Your CGM status was %1 as of %2.' + , de: 'Your CGM status was %1 as of %2.' + , dk: 'Your CGM status was %1 as of %2.' + , el: 'Your CGM status was %1 as of %2.' + , en: 'Your CGM status was %1 as of %2.' + , es: 'Your CGM status was %1 as of %2.' + , fi: 'Your CGM status was %1 as of %2.' + , fr: 'Your CGM status was %1 as of %2.' + , he: 'Your CGM status was %1 as of %2.' + , hr: 'Your CGM status was %1 as of %2.' + , it: 'Your CGM status was %1 as of %2.' + , ko: 'Your CGM status was %1 as of %2.' + , nb: 'Your CGM status was %1 as of %2.' + , nl: 'Your CGM status was %1 as of %2.' + , pl: 'Your CGM status was %1 as of %2.' + , pt: 'Your CGM status was %1 as of %2.' + , ro: 'Your CGM status was %1 as of %2.' + , ru: 'Your CGM status was %1 as of %2.' + , sk: 'Your CGM status was %1 as of %2.' + , sv: 'Your CGM status was %1 as of %2.' + , tr: 'Your CGM status was %1 as of %2.' + , zh_cn: 'Your CGM status was %1 as of %2.' + , zh_tw: 'Your CGM status was %1 as of %2.' + , hu: 'A CGM státuszod %1 volt %2 -kor.' + }, + 'virtAsstCGMSessAge': { + bg: 'Your CGM session has been active for %1 days and %2 hours.' + , cs: 'Your CGM session has been active for %1 days and %2 hours.' + , de: 'Your CGM session has been active for %1 days and %2 hours.' + , dk: 'Your CGM session has been active for %1 days and %2 hours.' + , el: 'Your CGM session has been active for %1 days and %2 hours.' + , en: 'Your CGM session has been active for %1 days and %2 hours.' + , es: 'Your CGM session has been active for %1 days and %2 hours.' + , fi: 'Your CGM session has been active for %1 days and %2 hours.' + , fr: 'Your CGM session has been active for %1 days and %2 hours.' + , he: 'Your CGM session has been active for %1 days and %2 hours.' + , hr: 'Your CGM session has been active for %1 days and %2 hours.' + , it: 'Your CGM session has been active for %1 days and %2 hours.' + , ko: 'Your CGM session has been active for %1 days and %2 hours.' + , nb: 'Your CGM session has been active for %1 days and %2 hours.' + , nl: 'Your CGM session has been active for %1 days and %2 hours.' + , pl: 'Your CGM session has been active for %1 days and %2 hours.' + , pt: 'Your CGM session has been active for %1 days and %2 hours.' + , ro: 'Your CGM session has been active for %1 days and %2 hours.' + , ru: 'Your CGM session has been active for %1 days and %2 hours.' + , sk: 'Your CGM session has been active for %1 days and %2 hours.' + , sv: 'Your CGM session has been active for %1 days and %2 hours.' + , tr: 'Your CGM session has been active for %1 days and %2 hours.' + , zh_cn: 'Your CGM session has been active for %1 days and %2 hours.' + , zh_tw: 'Your CGM session has been active for %1 days and %2 hours.' + , hu: 'A CGM kapcsolatod %1 napja és %2 órája aktív' + }, + 'virtAsstCGMSessNotStarted': { + bg: 'There is no active CGM session at the moment.' + , cs: 'There is no active CGM session at the moment.' + , de: 'There is no active CGM session at the moment.' + , dk: 'There is no active CGM session at the moment.' + , el: 'There is no active CGM session at the moment.' + , en: 'There is no active CGM session at the moment.' + , es: 'There is no active CGM session at the moment.' + , fi: 'There is no active CGM session at the moment.' + , fr: 'There is no active CGM session at the moment.' + , he: 'There is no active CGM session at the moment.' + , hr: 'There is no active CGM session at the moment.' + , it: 'There is no active CGM session at the moment.' + , ko: 'There is no active CGM session at the moment.' + , nb: 'There is no active CGM session at the moment.' + , nl: 'There is no active CGM session at the moment.' + , pl: 'There is no active CGM session at the moment.' + , pt: 'There is no active CGM session at the moment.' + , ro: 'There is no active CGM session at the moment.' + , ru: 'There is no active CGM session at the moment.' + , sk: 'There is no active CGM session at the moment.' + , sv: 'There is no active CGM session at the moment.' + , tr: 'There is no active CGM session at the moment.' + , zh_cn: 'There is no active CGM session at the moment.' + , zh_tw: 'There is no active CGM session at the moment.' + , hu: 'Jelenleg nincs aktív CGM kapcsolatod' + }, + 'virtAsstCGMTxStatus': { + bg: 'Your CGM transmitter status was %1 as of %2.' + , cs: 'Your CGM transmitter status was %1 as of %2.' + , de: 'Your CGM transmitter status was %1 as of %2.' + , dk: 'Your CGM transmitter status was %1 as of %2.' + , el: 'Your CGM transmitter status was %1 as of %2.' + , en: 'Your CGM transmitter status was %1 as of %2.' + , es: 'Your CGM transmitter status was %1 as of %2.' + , fi: 'Your CGM transmitter status was %1 as of %2.' + , fr: 'Your CGM transmitter status was %1 as of %2.' + , he: 'Your CGM transmitter status was %1 as of %2.' + , hr: 'Your CGM transmitter status was %1 as of %2.' + , it: 'Your CGM transmitter status was %1 as of %2.' + , ko: 'Your CGM transmitter status was %1 as of %2.' + , nb: 'Your CGM transmitter status was %1 as of %2.' + , nl: 'Your CGM transmitter status was %1 as of %2.' + , pl: 'Your CGM transmitter status was %1 as of %2.' + , pt: 'Your CGM transmitter status was %1 as of %2.' + , ro: 'Your CGM transmitter status was %1 as of %2.' + , ru: 'Your CGM transmitter status was %1 as of %2.' + , sk: 'Your CGM transmitter status was %1 as of %2.' + , sv: 'Your CGM transmitter status was %1 as of %2.' + , tr: 'Your CGM transmitter status was %1 as of %2.' + , zh_cn: 'Your CGM transmitter status was %1 as of %2.' + , zh_tw: 'Your CGM transmitter status was %1 as of %2.' + , hu: 'A CGM jeladód státusza %1 volt %2-kor' + }, + 'virtAsstCGMTxAge': { + bg: 'Your CGM transmitter is %1 days old.' + , cs: 'Your CGM transmitter is %1 days old.' + , de: 'Your CGM transmitter is %1 days old.' + , dk: 'Your CGM transmitter is %1 days old.' + , el: 'Your CGM transmitter is %1 days old.' + , en: 'Your CGM transmitter is %1 days old.' + , es: 'Your CGM transmitter is %1 days old.' + , fi: 'Your CGM transmitter is %1 days old.' + , fr: 'Your CGM transmitter is %1 days old.' + , he: 'Your CGM transmitter is %1 days old.' + , hr: 'Your CGM transmitter is %1 days old.' + , it: 'Your CGM transmitter is %1 days old.' + , ko: 'Your CGM transmitter is %1 days old.' + , nb: 'Your CGM transmitter is %1 days old.' + , nl: 'Your CGM transmitter is %1 days old.' + , pl: 'Your CGM transmitter is %1 days old.' + , pt: 'Your CGM transmitter is %1 days old.' + , ro: 'Your CGM transmitter is %1 days old.' + , ru: 'Your CGM transmitter is %1 days old.' + , sk: 'Your CGM transmitter is %1 days old.' + , sv: 'Your CGM transmitter is %1 days old.' + , tr: 'Your CGM transmitter is %1 days old.' + , zh_cn: 'Your CGM transmitter is %1 days old.' + , zh_tw: 'Your CGM transmitter is %1 days old.' + , hu: 'A CGM jeladód %1 napos.' + }, + 'virtAsstCGMNoise': { + bg: 'Your CGM noise was %1 as of %2.' + , cs: 'Your CGM noise was %1 as of %2.' + , de: 'Your CGM noise was %1 as of %2.' + , dk: 'Your CGM noise was %1 as of %2.' + , el: 'Your CGM noise was %1 as of %2.' + , en: 'Your CGM noise was %1 as of %2.' + , es: 'Your CGM noise was %1 as of %2.' + , fi: 'Your CGM noise was %1 as of %2.' + , fr: 'Your CGM noise was %1 as of %2.' + , he: 'Your CGM noise was %1 as of %2.' + , hr: 'Your CGM noise was %1 as of %2.' + , it: 'Your CGM noise was %1 as of %2.' + , ko: 'Your CGM noise was %1 as of %2.' + , nb: 'Your CGM noise was %1 as of %2.' + , nl: 'Your CGM noise was %1 as of %2.' + , pl: 'Your CGM noise was %1 as of %2.' + , pt: 'Your CGM noise was %1 as of %2.' + , ro: 'Your CGM noise was %1 as of %2.' + , ru: 'Your CGM noise was %1 as of %2.' + , sk: 'Your CGM noise was %1 as of %2.' + , sv: 'Your CGM noise was %1 as of %2.' + , tr: 'Your CGM noise was %1 as of %2.' + , zh_cn: 'Your CGM noise was %1 as of %2.' + , zh_tw: 'Your CGM noise was %1 as of %2.' + , hu: 'A CGM jeladó zaja %1 volt %2-kor' + }, + 'virtAsstCGMBattOne': { + bg: 'Your CGM battery was %1 volts as of %2.' + , cs: 'Your CGM battery was %1 volts as of %2.' + , de: 'Your CGM battery was %1 volts as of %2.' + , dk: 'Your CGM battery was %1 volts as of %2.' + , el: 'Your CGM battery was %1 volts as of %2.' + , en: 'Your CGM battery was %1 volts as of %2.' + , es: 'Your CGM battery was %1 volts as of %2.' + , fi: 'Your CGM battery was %1 volts as of %2.' + , fr: 'Your CGM battery was %1 volts as of %2.' + , he: 'Your CGM battery was %1 volts as of %2.' + , hr: 'Your CGM battery was %1 volts as of %2.' + , it: 'Your CGM battery was %1 volts as of %2.' + , ko: 'Your CGM battery was %1 volts as of %2.' + , nb: 'Your CGM battery was %1 volts as of %2.' + , nl: 'Your CGM battery was %1 volts as of %2.' + , pl: 'Your CGM battery was %1 volts as of %2.' + , pt: 'Your CGM battery was %1 volts as of %2.' + , ro: 'Your CGM battery was %1 volts as of %2.' + , ru: 'Your CGM battery was %1 volts as of %2.' + , sk: 'Your CGM battery was %1 volts as of %2.' + , sv: 'Your CGM battery was %1 volts as of %2.' + , tr: 'Your CGM battery was %1 volts as of %2.' + , zh_cn: 'Your CGM battery was %1 volts as of %2.' + , zh_tw: 'Your CGM battery was %1 volts as of %2.' + , hu: 'A CGM töltöttsége %1 VOLT volt %2-kor' + }, + 'virtAsstCGMBattTwo': { + bg: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , cs: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , de: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , dk: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , el: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , en: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , es: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , fi: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , fr: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , he: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , hr: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , it: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , ko: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , nb: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , nl: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , pl: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , pt: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , ro: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , ru: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , sk: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , sv: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , tr: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , zh_cn: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , zh_tw: 'Your CGM battery levels were %1 volts and %2 volts as of %3.' + , hu: 'A CGM töltöttsége %1 és %2 VOLT volt %3-kor' + }, + 'virtAsstDelta': { + bg: 'Your delta was %1 between %2 and %3.' + , cs: 'Your delta was %1 between %2 and %3.' + , de: 'Dein Delta war %1 zwischen %2 und %3.' + , dk: 'Your delta was %1 between %2 and %3.' + , el: 'Your delta was %1 between %2 and %3.' + , en: 'Your delta was %1 between %2 and %3.' + , es: 'Your delta was %1 between %2 and %3.' + , fi: 'Your delta was %1 between %2 and %3.' + , fr: 'Your delta was %1 between %2 and %3.' + , he: 'Your delta was %1 between %2 and %3.' + , hr: 'Your delta was %1 between %2 and %3.' + , it: 'Your delta was %1 between %2 and %3.' + , ko: 'Your delta was %1 between %2 and %3.' + , nb: 'Your delta was %1 between %2 and %3.' + , nl: 'Your delta was %1 between %2 and %3.' + , pl: 'Your delta was %1 between %2 and %3.' + , pt: 'Your delta was %1 between %2 and %3.' + , ro: 'Your delta was %1 between %2 and %3.' + , ru: 'Дельта была %1 между %2 и %3.' + , sk: 'Your delta was %1 between %2 and %3.' + , sv: 'Your delta was %1 between %2 and %3.' + , tr: 'Your delta was %1 between %2 and %3.' + , zh_cn: 'Your delta was %1 between %2 and %3.' + , zh_tw: 'Your delta was %1 between %2 and %3.' + , hu: 'A deltád %1 volt %2 és %3 között' }, 'virtAsstUnknownIntentTitle': { en: 'Unknown Intent' , cs: 'Unknown Intent' - , de: 'Unknown Intent' + , de: 'Unbekannte Absicht' , dk: 'Unknown Intent' , ko: 'Unknown Intent' , nl: 'Unknown Intent' @@ -14084,13 +15227,13 @@ function init() { , bg: 'Unknown Intent' , hr: 'Unknown Intent' , pl: 'Unknown Intent' - , ru: 'Unknown Intent' - , tr: 'Unknown Intent' + , ru: 'Неизвестное намерение' + , tr: 'Ismeretlen szándék' }, 'virtAsstUnknownIntentText': { en: 'I\'m sorry, I don\'t know what you\'re asking for.' , cs: 'I\'m sorry, I don\'t know what you\'re asking for.' - , de: 'I\'m sorry, I don\'t know what you\'re asking for.' + , de: 'Tut mir leid, ich hab deine Frage nicht verstanden.' , dk: 'I\'m sorry, I don\'t know what you\'re asking for.' , ko: 'I\'m sorry, I don\'t know what you\'re asking for.' , nl: 'I\'m sorry, I don\'t know what you\'re asking for.' @@ -14101,8 +15244,9 @@ function init() { , bg: 'I\'m sorry, I don\'t know what you\'re asking for.' , hr: 'I\'m sorry, I don\'t know what you\'re asking for.' , pl: 'I\'m sorry, I don\'t know what you\'re asking for.' - , ru: 'I\'m sorry, I don\'t know what you\'re asking for.' + , ru: 'Ваш запрос непонятен' , tr: 'I\'m sorry, I don\'t know what you\'re asking for.' + , hu: 'Sajnálom, nem tudom mit szeretnél tőlem.' }, 'Fat [g]': { cs: 'Tuk [g]' @@ -14123,6 +15267,7 @@ function init() { ,pl: 'Tłuszcz [g]' ,tr: 'Yağ [g]' ,he: '[g] שמן' + ,hu: 'Zsír [g]' }, 'Protein [g]': { cs: 'Proteiny [g]' @@ -14143,6 +15288,7 @@ function init() { ,pl: 'Białko [g]' ,tr: 'Protein [g]' ,he: '[g] חלבון' + ,hu: 'Protein [g]' }, 'Energy [kJ]': { cs: 'Energie [kJ]' @@ -14163,6 +15309,7 @@ function init() { ,pl: 'Energia [kJ}' ,tr: 'Enerji [kJ]' ,he: '[kJ] אנרגיה' + ,hu: 'Energia [kJ]' }, 'Clock Views:': { cs: 'Hodiny:' @@ -14183,6 +15330,7 @@ function init() { ,pl: 'Widoki zegarów' ,tr: 'Saat Görünümü' ,he: 'צגים השעון' + ,hu: 'Óra:' }, 'Clock': { cs: 'Hodiny' @@ -14202,6 +15350,7 @@ function init() { ,ru: 'часы' ,tr: 'Saat' ,he: 'שעון' + ,hu: 'Óra:' }, 'Color': { cs: 'Barva' @@ -14221,6 +15370,7 @@ function init() { ,ru: 'цвет' ,tr: 'Renk' ,he: 'צבע' + ,hu: 'Szinek' }, 'Simple': { cs: 'Jednoduchý' @@ -14240,6 +15390,7 @@ function init() { ,ru: 'простой' ,tr: 'Basit' ,he: 'פשוט' + ,hu: 'Csak cukor' }, 'TDD average': { cs: 'Průměrná denní dávka' @@ -14257,6 +15408,7 @@ function init() { , pl: 'Średnia dawka dzienna' , ru: 'средняя суточная доза инсулина' , tr: 'Ortalama günlük Toplam Doz (TDD)' + , hu: 'Átlagos napi adag (TDD)' }, 'Carbs average': { cs: 'Průměrné množství sacharidů' @@ -14274,7 +15426,8 @@ function init() { , pl: 'Średnia ilość węglowodanów' , ru: 'среднее кол-во углеводов за сутки' , tr: 'Günde ortalama karbonhidrat' - ,he: 'פחמימות ממוצע' + , he: 'פחמימות ממוצע' + , hu: 'Szenhidrát átlag' }, 'Eating Soon': { cs: 'Blížící se jídlo' @@ -14290,9 +15443,10 @@ function init() { , bg: 'Преди хранене' , hr: 'Uskoro obrok' , pl: 'Przed jedzeniem' - , ru: 'скоро прием пищи' + , ru: 'Ожидаемый прием пищи' , tr: 'Yakında Yenecek' , he: 'אוכל בקרוב' + , hu: 'Hamarosan evés' }, 'Last entry {0} minutes ago': { cs: 'Poslední hodnota {0} minut zpět' @@ -14310,6 +15464,7 @@ function init() { , pl: 'Ostatni wpis przed {0} minutami' , ru: 'предыдущая запись {0} минут назад' , tr: 'Son giriş {0} dakika önce' + , hu: 'Utolsó bejegyzés {0} volt' }, 'change': { cs: 'změna' @@ -14328,6 +15483,7 @@ function init() { , ru: 'замена' , tr: 'değişiklik' , he: 'שינוי' + , hu: 'változás' }, 'Speech': { cs: 'Hlas' @@ -14346,6 +15502,7 @@ function init() { , ru: 'речь' , tr: 'Konuş' , he: 'דיבור' + , hu: 'Beszéd' }, 'Target Top': { cs: 'Horní cíl' @@ -14364,6 +15521,7 @@ function init() { , de: 'Oberes Ziel' , tr: 'Hedef Üst' , he: 'ראש היעד' + , hu: 'Felsó cél' }, 'Target Bottom': { cs: 'Dolní cíl' @@ -14382,6 +15540,7 @@ function init() { , de: 'Unteres Ziel' , tr: 'Hedef Alt' , he: 'תחתית היעד' + , hu: 'Alsó cél' }, 'Canceled': { cs: 'Zrušený' @@ -14400,6 +15559,7 @@ function init() { , de: 'Abgebrochen' , tr: 'İptal edildi' , he: 'מבוטל' + , hu: 'Megszüntetett' }, 'Meter BG': { cs: 'Hodnota z glukoměru' @@ -14418,6 +15578,7 @@ function init() { , de: 'Wert Blutzuckermessgerät' , tr: 'Glikometre KŞ' , he: 'סוכר הדם של מד' + , hu: 'Cukorszint a mérőből' }, 'predicted': { cs: 'přepověď' @@ -14436,6 +15597,7 @@ function init() { , de: 'vorhergesagt' , tr: 'tahmin' , he: 'חזה' + , hu: 'előrejelzés' }, 'future': { cs: 'budoucnost' @@ -14454,6 +15616,7 @@ function init() { , de: 'Zukunft' , tr: 'gelecek' , he: 'עתיד' + , hu: 'jövő' }, 'ago': { cs: 'zpět' @@ -14471,6 +15634,7 @@ function init() { , de: 'vor' , tr: 'önce' , he: 'לפני' + , hu: 'ezelött' }, 'Last data received': { cs: 'Poslední data přiajata' @@ -14485,10 +15649,11 @@ function init() { , bg: 'Последни данни преди' , hr: 'Podaci posljednji puta primljeni' , pl: 'Ostatnie otrzymane dane' - , ru: 'последние данные получены' + , ru: 'прошлые данные получены' , de: 'Zuletzt Daten empfangen' , tr: 'Son veri alındı' , he: 'הנתונים המקבל אחרונים' + , hu: 'Utólsó adatok fogadva' }, 'Clock View': { cs: 'Hodiny' @@ -14509,63 +15674,135 @@ function init() { ,pl: 'Widok zegara' ,tr: 'Saat Görünümü' ,he: 'צג השעון' + ,hu: 'Idő' }, 'Protein': { fi: 'Proteiini' ,de: 'Protein' ,tr: 'Protein' ,hr: 'Proteini' + , pl: 'Białko' ,ru: 'Белки' ,he: 'חלבון' + ,nl: 'Eiwit' + ,hu: 'Protein' }, 'Fat': { fi: 'Rasva' ,de: 'Fett' ,tr: 'Yağ' ,hr: 'Masti' + , pl: 'Tłuszcz' ,ru: 'Жиры' ,he: 'שמן' + ,nl: 'Vet' + ,hu: 'Zsír' }, 'Protein average': { fi: 'Proteiini keskiarvo' ,de: 'Proteine Durchschnitt' ,tr: 'Protein Ortalaması' ,hr: 'Prosjek proteina' + , pl: 'Średnia białka' ,ru: 'Средний белок' ,he: 'חלבון ממוצע' + ,nl: 'eiwitgemiddelde' + ,hu: 'Protein átlag' }, 'Fat average': { fi: 'Rasva keskiarvo' ,de: 'Fett Durchschnitt' ,tr: 'Yağ Ortalaması' ,hr: 'Prosjek masti' + , pl: 'Średnia tłuszczu' ,ru: 'Средний жир' ,he: 'שמן ממוצע' + ,nl: 'Vetgemiddelde' + ,hu: 'Zsír átlag' }, 'Total carbs': { fi: 'Hiilihydraatit yhteensä' , de: 'Kohlenhydrate gesamt' ,tr: 'Toplam Karbonhidrat' ,hr: 'Ukupno ugh' + , pl: 'Węglowodany ogółem' ,ru: 'Всего углеводов' ,he: 'כל פחמימות' + ,nl: 'Totaal koolhydraten' + ,hu: 'Összes szénhidrát' }, 'Total protein': { fi: 'Proteiini yhteensä' , de: 'Protein gesamt' ,tr: 'Toplam Protein' ,hr: 'Ukupno proteini' + , pl: 'Białko ogółem' ,ru: 'Всего белков' ,he: 'כל חלבונים' + ,nl: 'Totaal eiwitten' + ,hu: 'Összes protein' }, 'Total fat': { fi: 'Rasva yhteensä' , de: 'Fett gesamt' ,tr: 'Toplam Yağ' ,hr: 'Ukupno masti' + , pl: 'Tłuszcz ogółem' ,ru: 'Всего жиров' ,he: 'כל שומנים' - } + ,nl: 'Totaal vetten' + ,hu: 'Összes zsír' + }, + 'Database Size': { + pl: 'Rozmiar Bazy Danych' + ,nl: 'Grootte database' + ,de: 'Datenbankgröße' + ,hu: 'Adatbázis mérete' + }, + 'Database Size near its limits!': { + pl: 'Rozmiar bazy danych zbliża się do limitu!' + ,nl: 'Database grootte nadert limiet!' + ,de: 'Datenbank fast voll!' + ,hu: 'Az adatbázis majdnem megtelt!' + }, + 'Database size is %1 MiB out of %2 MiB. Please backup and clean up database!': { + pl: 'Baza danych zajmuje %1 MiB z dozwolonych %2 MiB. Proszę zrób kopię zapasową i oczyść bazę danych!' + ,nl: 'Database grootte is %1 MiB van de %2 MiB. Maak een backup en verwijder oude data' + ,de: 'Die Datenbankgröße beträgt %1 MiB von %2 MiB. Bitte sichere deine Daten und bereinige die Datenbank!' + ,hu: 'Az adatbázis mérete %1 MiB a rendelkezésre álló %2 MiB-ból. Készítsen biztonsági másolatot!' + }, + 'Database file size': { + pl: 'Rozmiar pliku bazy danych' + ,nl: 'Database bestandsgrootte' + ,de: 'Datenbank-Dateigröße' + ,hu: 'Adatbázis file mérete' + }, + '%1 MiB of %2 MiB (%3%)': { + pl: '%1 MiB z %2 MiB (%3%)' + ,nl: '%1 MiB van de %2 MiB (%3%)' + ,de: '%1 MiB von %2 MiB (%3%)' + ,hu: '%1 MiB %2 MiB-ból (%3%)' + }, + 'Data size': { + pl: 'Rozmiar danych' + ,nl: 'Datagrootte' + ,de: 'Datengröße' + ,hu: 'Adatok mérete' + }, + 'virtAsstDatabaseSize': { + en: '%1 MiB. That is %2% of available database space.' + ,pl: '%1 MiB co stanowi %2% przestrzeni dostępnej dla bazy danych' + ,nl: '%1 MiB dat is %2% van de beschikbaare database ruimte' + ,de: '%1 MiB. Das sind %2% des verfügbaren Datenbank-Speicherplatzes.' + ,hu: '%1 MiB ami %2% a rendelkezésre álló méretből' + }, + 'virtAsstTitleDatabaseSize': { + en: 'Database file size' + ,pl: 'Rozmiar pliku bazy danych' + ,nl: 'Database bestandsgrootte' + ,de: 'Datenbank-Dateigröße' + ,hu: 'Adatbázis file méret' + } }; language.translations = translations; diff --git a/lib/middleware/express-extension-to-accept.js b/lib/middleware/express-extension-to-accept.js index 8f357e869a1..cdfe9a269fe 100644 --- a/lib/middleware/express-extension-to-accept.js +++ b/lib/middleware/express-extension-to-accept.js @@ -16,7 +16,7 @@ module.exports = function (formats) { throw new Error('Invalid format.') }) - var regexp = new RegExp('\.(' + formats.join('|') + ')$', 'i') + var regexp = new RegExp('\\.(' + formats.join('|') + ')$', 'i') return function (req, res, next) { var match = req.path.match(regexp) diff --git a/lib/middleware/index.js b/lib/middleware/index.js index c20eede6351..deb4fd5fb41 100644 --- a/lib/middleware/index.js +++ b/lib/middleware/index.js @@ -10,7 +10,7 @@ function extensions (list) { return require('./express-extension-to-accept')(list); } -function configure (env) { +function configure () { return { sendJSONStatus: wares.sendJSONStatus( ), bodyParser: wares.bodyParser, diff --git a/lib/notifications.js b/lib/notifications.js index 1a03ab87244..b4a8767afbe 100644 --- a/lib/notifications.js +++ b/lib/notifications.js @@ -108,8 +108,7 @@ function init (env, ctx) { }; notifications.requestNotify = function requestNotify (notify) { - // eslint-disable-next-line no-prototype-builtins - if (!notify.hasOwnProperty('level') || !notify.title || !notify.message || !notify.plugin) { + if (!Object.prototype.hasOwnProperty.call(notify, 'level') || !notify.title || !notify.message || !notify.plugin) { console.error(new Error('Unable to request notification, since the notify isn\'t complete: ' + JSON.stringify(notify))); return; } diff --git a/lib/plugins/alexa.js b/lib/plugins/alexa.js index da7bbdca2f1..25b13d0596d 100644 --- a/lib/plugins/alexa.js +++ b/lib/plugins/alexa.js @@ -1,7 +1,7 @@ var _ = require('lodash'); var async = require('async'); -function init (env, ctx) { +function init () { console.log('Configuring Alexa...'); function alexa() { return alexa; diff --git a/lib/plugins/ar2.js b/lib/plugins/ar2.js index 52aec073759..5232feb0245 100644 --- a/lib/plugins/ar2.js +++ b/lib/plugins/ar2.js @@ -15,7 +15,6 @@ var AR = [-0.723, 1.716]; //TODO: move this to css var AR2_COLOR = 'cyan'; -// eslint-disable-next-line no-unused-vars function init (ctx) { var translate = ctx.language.translate; @@ -68,8 +67,8 @@ function init (ctx) { var prop = sbx.properties.ar2; - if (prop) { - sbx.notifications.requestNotify({ + if (prop && prop.level) { + const notify = { level: prop.level , title: buildTitle(prop, sbx) , message: sbx.buildDefaultMessage() @@ -77,7 +76,8 @@ function init (ctx) { , pushoverSound: pushoverSound(prop, sbx.levels) , plugin: ar2 , debug: buildDebug(prop, sbx) - }); + }; + sbx.notifications.requestNotify(notify); } }; @@ -148,8 +148,9 @@ function init (ctx) { }; function virtAsstAr2Handler (next, slots, sbx) { - if (sbx.properties.ar2.forecast.predicted) { - var forecast = sbx.properties.ar2.forecast.predicted; + var predicted = _.get(sbx, 'properties.ar2.forecast.predicted'); + if (predicted) { + var forecast = predicted; var max = forecast[0].mgdl; var min = forecast[0].mgdl; var maxForecastMills = forecast[0].mills; @@ -224,9 +225,9 @@ function selectEventType (prop, sbx) { var eventName = ''; if (in20mins !== undefined) { - if (in20mins > sbx.scaleMgdl(sbx.settings.thresholds.bgTargetTop)) { + if (sbx.settings.alarmHigh && in20mins > sbx.scaleMgdl(sbx.settings.thresholds.bgTargetTop)) { eventName = 'high'; - } else if (in20mins < sbx.scaleMgdl(sbx.settings.thresholds.bgTargetBottom)) { + } else if (sbx.settings.alarmLow && in20mins < sbx.scaleMgdl(sbx.settings.thresholds.bgTargetBottom)) { eventName = 'low'; } } diff --git a/lib/plugins/basalprofile.js b/lib/plugins/basalprofile.js index 4347a7005ec..806dde5859d 100644 --- a/lib/plugins/basalprofile.js +++ b/lib/plugins/basalprofile.js @@ -2,6 +2,7 @@ var times = require('../times'); var moment = require('moment'); var consts = require('../constants'); +var _ = require('lodash'); function init (ctx) { @@ -114,13 +115,13 @@ function init (ctx) { function basalMessage(slots, sbx) { var basalValue = sbx.data.profile.getTempBasal(sbx.time); var response = translate('virtAsstUnknown'); - var preamble = ''; + var pwd = _.get(slots, 'pwd.value'); + var preamble = pwd ? translate('virtAsstPreamble3person', { + params: [ + pwd + ] + }) : translate('virtAsstPreamble'); if (basalValue.treatment) { - preamble = (slots && slots.pwd && slots.pwd.value) ? translate('virtAsstPreamble3person', { - params: [ - slots.pwd.value - ] - }) : translate('virtAsstPreamble'); var minutesLeft = moment(basalValue.treatment.endmills).from(moment(sbx.time)); response = translate('virtAsstBasalTemp', { params: [ @@ -130,11 +131,6 @@ function init (ctx) { ] }); } else { - preamble = (slots && slots.pwd && slots.pwd.value) ? translate('virtAsstPreamble3person', { - params: [ - slots.pwd.value - ] - }) : translate('virtAsstPreamble'); response = translate('virtAsstBasal', { params: [ preamble, diff --git a/lib/plugins/bgnow.js b/lib/plugins/bgnow.js index 512a23805c2..f3d835788bf 100644 --- a/lib/plugins/bgnow.js +++ b/lib/plugins/bgnow.js @@ -146,12 +146,12 @@ function init (ctx) { bgnow.calcDelta = function calcDelta (recent, previous, sbx) { if (_.isEmpty(recent)) { - console.info('all buckets are empty'); + //console.info('No recent CGM data is available'); return null; } if (_.isEmpty(previous)) { - console.info('previous bucket not found, not calculating delta'); + //console.info('previous bucket not found, not calculating delta'); return null; } diff --git a/lib/plugins/bridge.js b/lib/plugins/bridge.js index bf3c67e88da..50851e6df74 100644 --- a/lib/plugins/bridge.js +++ b/lib/plugins/bridge.js @@ -5,9 +5,9 @@ var engine = require('share2nightscout-bridge'); // Track the most recently seen record var mostRecentRecord; -function init (env) { +function init (env, bus) { if (env.extendedSettings.bridge && env.extendedSettings.bridge.userName && env.extendedSettings.bridge.password) { - return create(env); + return create(env, bus); } else { console.info('Dexcom bridge not enabled'); } @@ -64,26 +64,32 @@ function options (env) { }; } -function create (env) { +function create (env, bus) { var bridge = { }; var opts = options(env); var interval = opts.interval; - mostRecentRecord = new Date().getTime() - opts.fetch.minutes * 60000 + mostRecentRecord = new Date().getTime() - opts.fetch.minutes * 60000; bridge.startEngine = function startEngine (entries) { opts.callback = bridged(entries); - setInterval(function () { + let timer = setInterval(function () { opts.fetch.minutes = parseInt((new Date() - mostRecentRecord) / 60000); opts.fetch.maxCount = parseInt((opts.fetch.minutes / 5) + 1); - opts.firstFetchCount = opts.fetch.maxCount + opts.firstFetchCount = opts.fetch.maxCount; console.log("Fetching Share Data: ", 'minutes', opts.fetch.minutes, 'maxCount', opts.fetch.maxCount); engine(opts); }, interval); + + if (bus) { + bus.on('teardown', function serverTeardown () { + clearInterval(timer); + }); + } }; return bridge; diff --git a/lib/plugins/careportal.js b/lib/plugins/careportal.js index 2d65e1c9e9c..90f9bbd992a 100644 --- a/lib/plugins/careportal.js +++ b/lib/plugins/careportal.js @@ -8,8 +8,7 @@ function init() { , pluginType: 'drawer' }; - // eslint-disable-next-line no-unused-vars - careportal.getEventTypes = function getEventTypes (sbx) { + careportal.getEventTypes = function getEventTypes () { //TODO: use sbx and new CAREPORTAL_EVENTTYPE_GROUPS="core temps combo dad sensor site etc" diff --git a/lib/plugins/cob.js b/lib/plugins/cob.js index c6d4c4fdf8f..250614ecfd6 100644 --- a/lib/plugins/cob.js +++ b/lib/plugins/cob.js @@ -293,11 +293,13 @@ function init (ctx) { function virtAsstCOBHandler (next, slots, sbx) { var response = ''; - var value = (sbx.properties.cob && sbx.properties.cob.cob) ? sbx.properties.cob.cob : 0; - if (slots && slots.pwd && slots.pwd.value) { + var cob = _.get(sbx, 'properties.cob.cob'); + var pwd = _.get(slots, 'pwd.value'); + var value = cob ? cob : 0; + if (pwd) { response = translate('virtAsstCob3person', { params: [ - slots.pwd.value.replace('\'s', '') + pwd.replace('\'s', '') , value ] }); diff --git a/lib/plugins/dbsize.js b/lib/plugins/dbsize.js new file mode 100644 index 00000000000..1b6b43da8ed --- /dev/null +++ b/lib/plugins/dbsize.js @@ -0,0 +1,151 @@ +'use strict'; + +var levels = require('../levels'); +var _ = require('lodash'); + +function init (ctx) { + var translate = ctx.language.translate; + + var dbsize = { + name: 'dbsize' + , label: translate('Database Size') + , pluginType: 'pill-status' + , pillFlip: true + }; + + dbsize.getPrefs = function getPrefs (sbx) { + return { + warnPercentage: sbx.extendedSettings.warnPercentage ? sbx.extendedSettings.warnPercentage : 60 + , urgentPercentage: sbx.extendedSettings.urgentPercentage ? sbx.extendedSettings.urgentPercentage : 75 + , max: sbx.extendedSettings.max ? sbx.extendedSettings.max : 496 + , enableAlerts: sbx.extendedSettings.enableAlerts + , inMib: sbx.extendedSettings.inMib + }; + }; + + dbsize.setProperties = function setProperties (sbx) { + sbx.offerProperty('dbsize', function setDbsize () { + return dbsize.analyzeData(sbx); + }); + }; + + dbsize.analyzeData = function analyzeData (sbx) { + + var prefs = dbsize.getPrefs(sbx); + + var recentData = sbx.data.dbstats; + + var result = { + level: undefined + , display: prefs.inMib ? '?MiB' : '?%' + , status: undefined + }; + + var maxSize = (prefs.max > 0) ? prefs.max : 100 * 1024; + var totalDataSize = (recentData && recentData.dataSize) ? recentData.dataSize : 0; + totalDataSize += (recentData && recentData.indexSize) ? recentData.indexSize : 0; + totalDataSize /= 1024 * 1024; + + var dataPercentage = Math.floor((totalDataSize * 100.0) / maxSize); + + result.totalDataSize = totalDataSize; + result.dataPercentage = dataPercentage; + result.notificationLevel = levels.INFO; + result.details = { + maxSize: parseFloat(maxSize.toFixed(2)) + , dataSize: parseFloat(totalDataSize.toFixed(2)) + }; + + // failsafe to have percentage in 0..100 range + var boundWarnPercentage = Math.max(0, Math.min(100, parseInt(prefs.warnPercentage))); + var boundUrgentPercentage = Math.max(0, Math.min(100, parseInt(prefs.urgentPercentage))); + + var warnSize = Math.floor((boundWarnPercentage/100) * maxSize); + var urgentSize = Math.floor((boundUrgentPercentage/100) * maxSize); + + if ((totalDataSize >= urgentSize)&&(boundUrgentPercentage > 0)) { + result.notificationLevel = levels.URGENT; + } else if ((totalDataSize >= warnSize)&&(boundWarnPercentage > 0)) { + result.notificationLevel = levels.WARN; + } + + result.display = prefs.inMib ? parseFloat(totalDataSize.toFixed(0)) + 'MiB' : dataPercentage + '%'; + result.status = levels.toStatusClass(result.notificationLevel); + + return result; + }; + + dbsize.checkNotifications = function checkNotifications (sbx) { + var prefs = dbsize.getPrefs(sbx); + + if (!prefs.enableAlerts) { return; } + + var prop = sbx.properties.dbsize; + + if (prop.dataPercentage && prop.notificationLevel && prop.notificationLevel >= levels.WARN) { + sbx.notifications.requestNotify({ + level: prop.notificationLevel + , title: levels.toDisplay(prop.notificationLevel) + ' ' + translate('Database Size near its limits!') + , message: translate('Database size is %1 MiB out of %2 MiB. Please backup and clean up database!', { + params: [prop.details.dataSize, prop.details.maxSize] + }) + , pushoverSound: 'echo' + , group: 'Database Size' + , plugin: dbsize + , debug: prop + }); + } + }; + + dbsize.updateVisualisation = function updateVisualisation (sbx) { + var prop = sbx.properties.dbsize; + + var infos = [{ + label: translate('Data size') + , value: translate('%1 MiB of %2 MiB (%3%)', { + params: [prop.details.dataSize, prop.details.maxSize, prop.dataPercentage] + }) + } + ]; + + sbx.pluginBase.updatePillText(dbsize, { + value: prop && prop.display + , labelClass: 'plugicon-database' + , pillClass: prop && prop.status + , info: infos + , hide: !(prop && prop.totalDataSize && prop.totalDataSize >= 0) + }); + }; + + function virtAsstDatabaseSizeHandler (next, slots, sbx) { + var display = _.get(sbx, 'properties.dbsize.display'); + if (display) { + var dataSize = _.get(sbx, 'properties.dbsize.details.dataSize'); + var dataPercentage = _.get(sbx, 'properties.dbsize.dataPercentage'); + var response = translate('virtAsstDatabaseSize', { + params: [ + dataSize + , dataPercentage + ] + }); + next(translate('virtAsstTitleDatabaseSize'), response); + } else { + next(translate('virtAsstTitleDatabaseSize'), translate('virtAsstUnknown')); + } + } + + dbsize.virtAsst = { + intentHandlers: [ + { + intent: 'MetricNow' + , metrics: ['db size'] + , intentHandler: virtAsstDatabaseSizeHandler + } + ] + }; + + return dbsize; + +} + +module.exports = init; diff --git a/lib/plugins/googlehome.js b/lib/plugins/googlehome.js index 8e8181512c8..6b6d7b098f2 100644 --- a/lib/plugins/googlehome.js +++ b/lib/plugins/googlehome.js @@ -1,7 +1,7 @@ var _ = require('lodash'); var async = require('async'); -function init (env, ctx) { +function init () { console.log('Configuring Google Home...'); function googleHome() { return googleHome; diff --git a/lib/plugins/index.js b/lib/plugins/index.js index 2568b634afd..d6bae73bdbc 100644 --- a/lib/plugins/index.js +++ b/lib/plugins/index.js @@ -49,6 +49,7 @@ function init (ctx) { , require('./boluscalc')(ctx) // fake plugin to show/hide , require('./profile')(ctx) // fake plugin to hold extended settings , require('./speech')(ctx) + , require('./dbsize')(ctx) ]; var serverDefaultPlugins = [ @@ -73,6 +74,8 @@ function init (ctx) { , require('./treatmentnotify')(ctx) , require('./timeago')(ctx) , require('./basalprofile')(ctx) + , require('./dbsize')(ctx) + , require('./runtimestate')(ctx) ]; plugins.registerServerDefaults = function registerServerDefaults () { diff --git a/lib/plugins/iob.js b/lib/plugins/iob.js index 96bea03b3ff..cdcc15706e3 100644 --- a/lib/plugins/iob.js +++ b/lib/plugins/iob.js @@ -262,10 +262,11 @@ function init(ctx) { } function getIob(sbx) { - if (sbx.properties.iob && sbx.properties.iob.iob !== 0) { + var iob = _.get(sbx, 'properties.iob.iob'); + if (iob !== 0) { return translate('virtAsstIobUnits', { params: [ - utils.toFixed(sbx.properties.iob.iob) + utils.toFixed(iob) ] }); } diff --git a/lib/plugins/loop.js b/lib/plugins/loop.js index 9b099dd188c..e7d3ae91c93 100644 --- a/lib/plugins/loop.js +++ b/lib/plugins/loop.js @@ -214,6 +214,8 @@ function init (ctx) { }); } + // TODO: add OTP entry + return [ { val: 'Temporary Override' @@ -229,6 +231,7 @@ function init (ctx) { , split: false , targets: false , reasons: reasonconf + , otp: true , submitHook: postLoopNotification }, { @@ -245,10 +248,28 @@ function init (ctx) { , split: false , targets: false , submitHook: postLoopNotification + }, + { + val: 'Remote Carbs Entry' + , name: 'Remote Carbs Entry' + , remoteCarbs: true + , remoteAbsorption: true + , otp: true + , submitHook: postLoopNotification + }, + { + val: 'Remote Bolus Entry' + , name: 'Remote Bolus Entry' + , remoteBolus: true + , otp: true + , submitHook: postLoopNotification } ]; }; + // TODO: Add event listener to customize labels + + loop.updateVisualisation = function updateVisualisation (sbx) { var prop = sbx.properties.loop; @@ -508,13 +529,14 @@ function init (ctx) { }; function virtAsstForecastHandler (next, slots, sbx) { - if (sbx.properties.loop.lastLoop.predicted) { - var forecast = sbx.properties.loop.lastLoop.predicted.values; + var predicted = _.get(sbx, 'properties.loop.lastLoop.predicted'); + if (predicted) { + var forecast = predicted.values; var max = forecast[0]; var min = forecast[0]; var maxForecastIndex = Math.min(6, forecast.length); - var startPrediction = moment(sbx.properties.loop.lastLoop.predicted.startDate); + var startPrediction = moment(predicted.startDate); var endPrediction = startPrediction.clone().add(maxForecastIndex * 5, 'minutes'); if (endPrediction.valueOf() < sbx.time) { next(translate('virtAsstTitleLoopForecast'), translate('virtAsstForecastUnavailable')); @@ -552,8 +574,9 @@ function init (ctx) { } function virtAsstLastLoopHandler (next, slots, sbx) { - if (sbx.properties.loop.lastLoop) { - console.log(JSON.stringify(sbx.properties.loop.lastLoop)); + var lastLoop = _.get(sbx, 'properties.loop.lastLoop') + if (lastLoop) { + console.log(JSON.stringify(lastLoop)); var response = translate('virtAsstLastLoop', { params: [ moment(sbx.properties.loop.lastOkMoment).from(moment(sbx.time)) diff --git a/lib/plugins/mmconnect.js b/lib/plugins/mmconnect.js index 342c68ef2ea..c6321e9f7f3 100644 --- a/lib/plugins/mmconnect.js +++ b/lib/plugins/mmconnect.js @@ -4,16 +4,16 @@ var _ = require('lodash'), connect = require('minimed-connect-to-nightscout'); -function init (env, entries, devicestatus) { +function init (env, entries, devicestatus, bus) { if (env.extendedSettings.mmconnect && env.extendedSettings.mmconnect.userName && env.extendedSettings.mmconnect.password) { - return {run: makeRunner(env, entries, devicestatus)}; + return {run: makeRunner(env, entries, devicestatus, bus)}; } else { console.info('MiniMed Connect not enabled'); return null; } } -function makeRunner (env, entries, devicestatus) { +function makeRunner (env, entries, devicestatus, bus) { var options = getOptions(env); var client = connect.carelink.Client(options); @@ -22,9 +22,15 @@ function makeRunner (env, entries, devicestatus) { var handleData = makeHandler_(entries, devicestatus, options.sgvLimit, options.storeRawData); return function run () { - setInterval(function() { + let timer = setInterval(function() { client.fetch(handleData); }, options.interval); + + if (bus) { + bus.on('teardown', function serverTeardown () { + clearInterval(timer); + }); + } }; } diff --git a/lib/plugins/openaps.js b/lib/plugins/openaps.js index 59af42c0e61..cf5e240ce99 100644 --- a/lib/plugins/openaps.js +++ b/lib/plugins/openaps.js @@ -123,12 +123,42 @@ function init (ctx) { } function toMoments (status) { + var enacted = false; + var notEnacted = false; + if (status.openaps.enacted && status.openaps.enacted.timestamp && (status.openaps.enacted.recieved || status.openaps.enacted.received)) { + if (status.openaps.enacted.mills) { + enacted = moment(status.openaps.enacted.mills); + } else { + enacted = moment(status.openaps.enacted.timestamp); + } + } else if (status.openaps.enacted && status.openaps.enacted.timestamp && !(status.openaps.enacted.recieved || status.openaps.enacted.received)) { + if (status.openaps.enacted.mills) { + notEnacted = moment(status.openaps.enacted.mills) + } else { + notEnacted = moment(status.openaps.enacted.timestamp) + } + } + + var suggested = false; + if (status.openaps.suggested && status.openaps.suggested.mills) { + suggested = moment(status.openaps.suggested.mills); + } else if (status.openaps.suggested && status.openaps.suggested.timestamp) { + suggested = moment(status.openaps.suggested.timestamp); + } + + var iob = false; + if (status.openaps.iob && status.openaps.iob.mills) { + iob = moment(status.openaps.iob.mills); + } else if (status.openaps.iob && status.openaps.iob.timestamp) { + iob = moment(status.openaps.iob.timestamp); + } + return { when: moment(status.mills) - , enacted: status.openaps.enacted && status.openaps.enacted.timestamp && (status.openaps.enacted.recieved || status.openaps.enacted.received) && moment(status.openaps.enacted.timestamp) - , notEnacted: status.openaps.enacted && status.openaps.enacted.timestamp && !(status.openaps.enacted.recieved || status.openaps.enacted.received) && moment(status.openaps.enacted.timestamp) - , suggested: status.openaps.suggested && status.openaps.suggested.timestamp && moment(status.openaps.suggested.timestamp) - , iob: status.openaps.iob && status.openaps.iob.timestamp && moment(status.openaps.iob.timestamp) + , enacted + , notEnacted + , suggested + , iob }; } @@ -175,7 +205,11 @@ function init (ctx) { var enacted = status.openaps && status.openaps.enacted; if (enacted && moments.enacted && (!result.lastEnacted || moments.enacted.isAfter(result.lastEnacted.moment))) { - enacted.moment = moment(enacted.timestamp); + if (enacted.mills) { + enacted.moment = moment(enacted.mills); + } else { + enacted.moment = moment(enacted.timestamp); + } result.lastEnacted = enacted; if (enacted.predBGs && (!result.lastPredBGs || enacted.moment.isAfter(result.lastPredBGs.moment))) { result.lastPredBGs = _.isArray(enacted.predBGs) ? { values: enacted.predBGs } : enacted.predBGs; @@ -184,13 +218,21 @@ function init (ctx) { } if (enacted && moments.notEnacted && (!result.lastNotEnacted || moments.notEnacted.isAfter(result.lastNotEnacted.moment))) { - enacted.moment = moment(enacted.timestamp); + if (enacted.mills) { + enacted.moment = moment(enacted.mills); + } else { + enacted.moment = moment(enacted.timestamp); + } result.lastNotEnacted = enacted; } var suggested = status.openaps && status.openaps.suggested; if (suggested && moments.suggested && (!result.lastSuggested || moments.suggested.isAfter(result.lastSuggested.moment))) { - suggested.moment = moment(suggested.timestamp); + if (suggested.mills) { + suggested.moment = moment(suggested.mills); + } else { + suggested.moment = moment(suggested.timestamp); + } result.lastSuggested = suggested; if (suggested.predBGs && (!result.lastPredBGs || suggested.moment.isAfter(result.lastPredBGs.moment))) { result.lastPredBGs = _.isArray(suggested.predBGs) ? { values: suggested.predBGs } : suggested.predBGs; @@ -518,10 +560,11 @@ function init (ctx) { }; function virtAsstForecastHandler (next, slots, sbx) { - if (sbx.properties.openaps && sbx.properties.openaps.lastEventualBG) { + var lastEventualBG = _.get(sbx, 'properties.openaps.lastEventualBG'); + if (lastEventualBG) { var response = translate('virtAsstOpenAPSForecast', { params: [ - sbx.properties.openaps.lastEventualBG + lastEventualBG ] }); next(translate('virtAsstTitleOpenAPSForecast'), response); @@ -531,11 +574,11 @@ function init (ctx) { } function virtAsstLastLoopHandler (next, slots, sbx) { - if (sbx.properties.openaps.lastLoopMoment) { - console.log(JSON.stringify(sbx.properties.openaps.lastLoopMoment)); + var lastLoopMoment = _.get(sbx, 'properties.openaps.lastLoopMoment'); + if (lastLoopMoment) { var response = translate('virtAsstLastLoop', { params: [ - moment(sbx.properties.openaps.lastLoopMoment).from(moment(sbx.time)) + moment(lastLoopMoment).from(moment(sbx.time)) ] }); next(translate('virtAsstTitleLastLoop'), response); diff --git a/lib/plugins/pump.js b/lib/plugins/pump.js index 7e71c21e1b1..52dc7ade769 100644 --- a/lib/plugins/pump.js +++ b/lib/plugins/pump.js @@ -136,7 +136,7 @@ function init (ctx) { }; function virtAsstReservoirHandler (next, slots, sbx) { - var reservoir = sbx.properties.pump.pump.reservoir; + var reservoir = _.get(sbx, 'properties.pump.pump.reservoir'); if (reservoir || reservoir === 0) { var response = translate('virtAsstReservoir', { params: [ diff --git a/lib/plugins/pushover.js b/lib/plugins/pushover.js index 99fc22697a4..8c63a905e00 100644 --- a/lib/plugins/pushover.js +++ b/lib/plugins/pushover.js @@ -127,7 +127,10 @@ function setupPushover (env) { if (apiToken && (userKeys.length > 0 || alarmKeys.length > 0 || announcementKeys.length > 0)) { var pushoverAPI = new Pushover({ - token: apiToken + token: apiToken, + onerror: function(error) { + console.error('Pushover error', error); + } }); pushoverAPI.apiToken = apiToken; diff --git a/lib/plugins/rawbg.js b/lib/plugins/rawbg.js index 3248126b046..a784f49363f 100644 --- a/lib/plugins/rawbg.js +++ b/lib/plugins/rawbg.js @@ -107,10 +107,11 @@ function init (ctx) { }; function virtAsstRawBGHandler (next, slots, sbx) { - if (sbx.properties.rawbg.mgdl) { + var rawBg = _.get(sbx, 'properties.rawbg.mgdl'); + if (rawBg) { var response = translate('virtAsstRawBG', { params: [ - sbx.properties.rawbg.mgdl + rawBg ] }); next(translate('virtAsstTitleRawBG'), response); diff --git a/lib/plugins/runtimestate.js b/lib/plugins/runtimestate.js new file mode 100644 index 00000000000..0447da0cc00 --- /dev/null +++ b/lib/plugins/runtimestate.js @@ -0,0 +1,23 @@ +'use strict'; + +function init() { + + var runtime = { + name: 'runtimestate' + , label: 'Runtime state' + , pluginType: 'fake' + }; + + runtime.setProperties = function setProperties(sbx) { + sbx.offerProperty('runtimestate', function setProp ( ) { + return { + state: sbx.runtimeState + }; + }); + }; + + return runtime; + +} + +module.exports = init; \ No newline at end of file diff --git a/lib/plugins/simplealarms.js b/lib/plugins/simplealarms.js index 9b975dddebe..17529eabee8 100644 --- a/lib/plugins/simplealarms.js +++ b/lib/plugins/simplealarms.js @@ -12,6 +12,7 @@ function init() { }; simplealarms.checkNotifications = function checkNotifications(sbx) { + var lastSGVEntry = sbx.lastSGVEntry() , scaledSGV = sbx.scaleEntry(lastSGVEntry) ; @@ -37,27 +38,31 @@ function init() { simplealarms.compareBGToTresholds = function compareBGToTresholds(scaledSGV, sbx) { var result = { level: levels.INFO }; - if (scaledSGV > sbx.scaleMgdl(sbx.settings.thresholds.bgHigh)) { + if (sbx.settings.alarmUrgentHigh && scaledSGV > sbx.scaleMgdl(sbx.settings.thresholds.bgHigh)) { result.level = levels.URGENT; result.title = levels.toDisplay(levels.URGENT) + ' HIGH'; result.pushoverSound = 'persistent'; result.eventName = 'high'; - } else if (scaledSGV > sbx.scaleMgdl(sbx.settings.thresholds.bgTargetTop)) { - result.level = levels.WARN; - result.title = levels.toDisplay(levels.WARN) + ' HIGH'; - result.pushoverSound = 'climb'; - result.eventName = 'high'; - } else if (scaledSGV < sbx.scaleMgdl(sbx.settings.thresholds.bgLow)) { + } else + if (sbx.settings.alarmHigh && scaledSGV > sbx.scaleMgdl(sbx.settings.thresholds.bgTargetTop)) { + result.level = levels.WARN; + result.title = levels.toDisplay(levels.WARN) + ' HIGH'; + result.pushoverSound = 'climb'; + result.eventName = 'high'; + } + + if (sbx.settings.alarmUrgentLow && scaledSGV < sbx.scaleMgdl(sbx.settings.thresholds.bgLow)) { result.level = levels.URGENT; result.title = levels.toDisplay(levels.URGENT) + ' LOW'; result.pushoverSound = 'persistent'; result.eventName = 'low'; - } else if (scaledSGV < sbx.scaleMgdl(sbx.settings.thresholds.bgTargetBottom)) { + } else if (sbx.settings.alarmLow && scaledSGV < sbx.scaleMgdl(sbx.settings.thresholds.bgTargetBottom)) { result.level = levels.WARN; result.title = levels.toDisplay(levels.WARN) + ' LOW'; result.pushoverSound = 'falling'; result.eventName = 'low'; } + return result; }; diff --git a/lib/plugins/timeago.js b/lib/plugins/timeago.js index 4b176764d45..4b713a60217 100644 --- a/lib/plugins/timeago.js +++ b/lib/plugins/timeago.js @@ -3,11 +3,10 @@ var levels = require('../levels'); var times = require('../times'); var lastChecked = new Date(); -var lastSuspendTime = new Date("1900-01-01"); +var lastRecoveryTimeFromSuspend = new Date("1900-01-01"); function init(ctx) { var translate = ctx.language.translate; - var heartbeatMs = ctx.settings.heartbeat * 1000; var timeago = { name: 'timeago', @@ -72,19 +71,16 @@ function init(ctx) { function isHibernationDetected() { if (sbx.runtimeEnvironment === 'client') { - if (delta > 15 * 1000) { // Looks like we've been hibernating - lastSuspendTime = now; + if (delta > 20 * 1000) { // Looks like we've been hibernating + lastRecoveryTimeFromSuspend = now; } + var timeSinceLastRecovered = now.getTime() - lastRecoveryTimeFromSuspend.getTime(); + return timeSinceLastRecovered < (10 * 1000); + } - var timeSinceLastSuspended = now.getTime() - lastSuspendTime.getTime(); + // Assume server never hibernates, or if it does, it's alarm-worthy + return false; - return timeSinceLastSuspended < (10 * 1000); - } else if (sbx.runtimeEnvironment === 'server') { - return delta > 2 * heartbeatMs; - } else { - console.error('Cannot detect hibernation, because runtimeEnvironment is not detected from sbx.runtimeEnvironment:', sbx.runtimeEnvironment); - return false; - } } if (isHibernationDetected()) { diff --git a/lib/plugins/upbat.js b/lib/plugins/upbat.js index dc603054ecb..71547eca6a2 100644 --- a/lib/plugins/upbat.js +++ b/lib/plugins/upbat.js @@ -223,10 +223,11 @@ function init(ctx) { }; function virtAsstUploaderBatteryHandler (next, slots, sbx) { - if (sbx.properties.upbat.display) { + var upBat = _.get(sbx, 'properties.upbat.display'); + if (upBat) { var response = translate('virtAsstUploaderBattery', { params: [ - sbx.properties.upbat.display + upBat ] }); next(translate('virtAsstTitleUploaderBattery'), response); diff --git a/lib/plugins/virtAsstBase.js b/lib/plugins/virtAsstBase.js new file mode 100644 index 00000000000..781f56969cf --- /dev/null +++ b/lib/plugins/virtAsstBase.js @@ -0,0 +1,111 @@ +'use strict'; + +var moment = require('moment'); +var _each = require('lodash/each'); + +function init(env, ctx) { + function virtAsstBase() { + return virtAsstBase; + } + + var entries = ctx.entries; + var translate = ctx.language.translate; + + virtAsstBase.setupMutualIntents = function (configuredPlugin) { + // full status + configuredPlugin.addToRollup('Status', function (slots, sbx, callback) { + entries.list({count: 1}, function (err, records) { + var direction; + if (translate(records[0].direction)) { + direction = translate(records[0].direction); + } else { + direction = records[0].direction; + } + var status = translate('virtAsstStatus', { + params: [ + sbx.scaleMgdl(records[0].sgv), + direction, + moment(records[0].date).from(moment(sbx.time)) + ] + }); + + callback(null, {results: status, priority: -1}); + }); + }, 'BG Status'); + + configuredPlugin.configureIntentHandler('NSStatus', function (callback, slots, sbx, locale) { + configuredPlugin.getRollup('Status', sbx, slots, locale, function (status) { + callback(translate('virtAsstTitleFullStatus'), status); + }); + }); + + // blood sugar and direction + configuredPlugin.configureIntentHandler('MetricNow', function (callback, slots, sbx) { + entries.list({count: 1}, function(err, records) { + var direction; + if(translate(records[0].direction)){ + direction = translate(records[0].direction); + } else { + direction = records[0].direction; + } + var status = translate('virtAsstStatus', { + params: [ + sbx.scaleMgdl(records[0].sgv), + direction, + moment(records[0].date).from(moment(sbx.time))] + }); + + callback(translate('virtAsstTitleCurrentBG'), status); + }); + }, ['bg', 'blood glucose', 'number']); + + // blood sugar delta + configuredPlugin.configureIntentHandler('MetricNow', function (callback, slots, sbx) { + if (sbx.properties.delta && sbx.properties.delta.display) { + entries.list({count: 2}, function(err, records) { + callback( + translate('virtAsstTitleDelta'), + translate('virtAsstDelta', { + params: [ + sbx.properties.delta.display == '+0' ? '0' : sbx.properties.delta.display, + moment(records[0].date).from(moment(sbx.time)), + moment(records[1].date).from(moment(sbx.time)) + ] + }) + ); + }); + } else { + callback(translate('virtAsstTitleDelta'), translate('virtAsstUnknown')); + } + }, ['delta']); + }; + + virtAsstBase.setupVirtAsstHandlers = function (configuredPlugin) { + ctx.plugins.eachEnabledPlugin(function (plugin) { + if (plugin.virtAsst) { + if (plugin.virtAsst.intentHandlers) { + console.log('Plugin "' + plugin.name + '" supports Virtual Assistants'); + _each(plugin.virtAsst.intentHandlers, function (route) { + if (route) { + configuredPlugin.configureIntentHandler(route.intent, route.intentHandler, route.metrics); + } + }); + } + if (plugin.virtAsst.rollupHandlers) { + console.log('Plugin "' + plugin.name + '" supports rollups for Virtual Assistants'); + _each(plugin.virtAsst.rollupHandlers, function (route) { + if (route) { + configuredPlugin.addToRollup(route.rollupGroup, route.rollupHandler, route.rollupName); + } + }); + } + } else { + console.log('Plugin "' + plugin.name + '" does not support Virtual Assistants'); + } + }); + }; + + return virtAsstBase; +} + +module.exports = init; diff --git a/lib/plugins/xdripjs.js b/lib/plugins/xdripjs.js index a36a42de2e0..dd5b55eb816 100644 --- a/lib/plugins/xdripjs.js +++ b/lib/plugins/xdripjs.js @@ -9,6 +9,7 @@ function init(ctx) { var utils = require('../utils')(ctx); var firstPrefs = true; var lastStateNotification = null; + var translate = ctx.language.translate; var sensorState = { name: 'xdripjs' @@ -321,6 +322,120 @@ function init(ctx) { } }; + function virtAsstGenericCGMHandler(translateItem, field, next, sbx) { + var response; + var state = _.get(sbx, 'properties.sensorState.'+field); + if (state) { + response = translate('virtAsstCGM'+translateItem, { + params:[ + state + , moment(sbx.properties.sensorState.lastStateTime).from(moment(sbx.time)) + ] + }); + } else { + response = translate('virtAsstUnknown'); + } + + next(translate('virtAsstTitleCGM'+translateItem), response); + } + + sensorState.virtAsst = { + intentHandlers: [ + { + intent: 'MetricNow' + , metrics: ['cgm mode'] + , intentHandler: function(next, slots, sbx){virtAsstGenericCGMHandler('Mode', 'lastMode', next, sbx);} + } + , { + intent: 'MetricNow' + , metrics: ['cgm status'] + , intentHandler: function(next, slots, sbx){virtAsstGenericCGMHandler('Status', 'lastStateString', next, sbx);} + } + , { + intent: 'MetricNow' + , metrics: ['cgm session age'] + , intentHandler: function(next, slots, sbx){ + var response; + var lastSessionStart = _.get(sbx, 'properties.sensorState.lastSessionStart'); + // session start is only valid if in a session + if (lastSessionStart) { + if (_.get(sbx, 'properties.sensorState.lastState') != 0x1) { + var duration = moment.duration(moment().diff(moment(lastSessionStart))); + response = translate('virtAsstCGMSessAge', { + params: [ + duration.days(), + duration.hours() + ] + }); + } else { + response = translate('virtAsstCGMSessNotStarted'); + } + } else { + response = translate('virtAsstUnknown'); + } + + next(translate('virtAsstTitleCGMSessAge'), response); + } + } + , { + intent: 'MetricNow' + , metrics: ['cgm tx status'] + , intentHandler: function(next, slots, sbx){virtAsstGenericCGMHandler('TxStatus', 'lastTxStatusString', next, sbx);} + } + , { + intent: 'MetricNow' + , metrics: ['cgm tx age'] + , intentHandler: function(next, slots, sbx){ + var lastTxActivation = _.get(sbx, 'properties.sensorState.lastTxActivation'); + next( + translate('virtAsstTitleCGMTxAge'), + lastTxActivation + ? translate('virtAsstCGMTxAge', {params:[moment().diff(moment(lastTxActivation), 'days')]}) + : translate('virtAsstUnknown') + ); + } + } + , { + intent: 'MetricNow' + , metrics: ['cgm noise'] + , intentHandler: function(next, slots, sbx){virtAsstGenericCGMHandler('Noise', 'lastNoiseString', next, sbx);} + } + , { + intent: 'MetricNow' + , metrics: ['cgm battery'] + , intentHandler: function(next, slots, sbx){ + var response; + var lastVoltageA = _.get(sbx, 'properties.sensorState.lastVoltageA'); + var lastVoltageB = _.get(sbx, 'properties.sensorState.lastVoltageB'); + var lastBatteryTimestamp = _.get(sbx, 'properties.sensorState.lastBatteryTimestamp'); + if (lastVoltageA || lastVoltageB) { + if (lastVoltageA && lastVoltageB) { + response = translate('virtAsstCGMBattTwo', { + params:[ + (lastVoltageA / 100) + , (lastVoltageB / 100) + , moment(lastBatteryTimestamp).from(moment(sbx.time)) + ] + }); + } else { + var finalValue = lastVoltageA ? lastVoltageA : lastVoltageB; + response = translate('virtAsstCGMBattOne', { + params:[ + (finalValue / 100) + , moment(lastBatteryTimestamp).from(moment(sbx.time)) + ] + }); + } + } else { + response = translate('virtAsstUnknown'); + } + + next(translate('virtAsstTitleCGMBatt'), response); + } + } + ] + }; + return sensorState; } diff --git a/lib/profilefunctions.js b/lib/profilefunctions.js index 5826e6108b4..9fac4984949 100644 --- a/lib/profilefunctions.js +++ b/lib/profilefunctions.js @@ -61,6 +61,9 @@ function init (profileData) { // preprocess the timestamps to seconds for a couple orders of magnitude faster operation profile.preprocessProfileOnLoad = function preprocessProfileOnLoad (container) { _.each(container, function eachValue (value) { + + if (value === null) return; + if (Object.prototype.toString.call(value) === '[object Array]') { profile.preprocessProfileOnLoad(value); } @@ -152,18 +155,20 @@ function init (profileData) { return returnValue; } - var data = profile.hasData() ? profile.data[0] : null; - var timeprofile = spec_profile || profile.activeProfileToTime(time); + var pdataActive = profile.profileFromTime(time); + var data = profile.hasData() ? pdataActive : null; + var timeprofile = profile.activeProfileToTime(time); returnValue = data && data.store[timeprofile] ? data.store[timeprofile] : {}; cache.put(cacheKey, returnValue, cacheTTL); return returnValue; + }; profile.getUnits = function getUnits (spec_profile) { var pu = profile.getCurrentProfile(null, spec_profile)['units'] + ' '; if (pu.toLowerCase().includes('mmol')) return 'mmol'; - return 'mgdl'; + return 'mg/dl'; }; profile.getTimezone = function getTimezone (spec_profile) { @@ -225,10 +230,13 @@ function init (profileData) { profile.activeProfileToTime = function activeProfileToTime (time) { if (profile.hasData()) { - var timeprofile = profile.data[0].defaultProfile; time = Number(time) || new Date().getTime(); + + var pdataActive = profile.profileFromTime(time); + var timeprofile = pdataActive.defaultProfile; var treatment = profile.activeProfileTreatmentToTime(time); - if (treatment && profile.data[0].store && profile.data[0].store[treatment.profile]) { + + if (treatment && pdataActive.store && pdataActive.store[treatment.profile]) { timeprofile = treatment.profile; } return timeprofile; @@ -248,30 +256,31 @@ function init (profileData) { var treatment = null; if (profile.hasData()) { - profile.profiletreatments.forEach(function eachTreatment (t) { - if (time >= t.mills && t.mills >= profile.data[0].mills) { - var duration = times.mins(t.duration || 0).msecs; - if (duration != 0 && time < t.mills + duration) { - treatment = t; - // if profile switch contains json of profile inject it in to store to be findable by profile name - if (treatment.profileJson && !profile.data[0].store[treatment.profile]) { - if (treatment.profile.indexOf("@@@@@") < 0) - treatment.profile += "@@@@@" + treatment.mills; - let json = JSON.parse(treatment.profileJson); - profile.data[0].store[treatment.profile] = json; - } - } - if (duration == 0) { - treatment = t; - // if profile switch contains json of profile inject it in to store to be findable by profile name - if (treatment.profileJson && !profile.data[0].store[treatment.profile]) { - if (treatment.profile.indexOf("@@@@@") < 0) - treatment.profile += "@@@@@" + treatment.mills; - let json = JSON.parse(treatment.profileJson); - profile.data[0].store[treatment.profile] = json; - } + var pdataActive = profile.profileFromTime(time); + profile.profiletreatments.forEach(function eachTreatment(t) { + if (time >= t.mills && t.mills >= pdataActive.mills) { + var duration = times.mins(t.duration || 0).msecs; + if (duration != 0 && time < t.mills + duration) { + treatment = t; + // if profile switch contains json of profile inject it in to store to be findable by profile name + if (treatment.profileJson && !pdataActive.store[treatment.profile]) { + if (treatment.profile.indexOf("@@@@@") < 0) + treatment.profile += "@@@@@" + treatment.mills; + let json = JSON.parse(treatment.profileJson); + pdataActive.store[treatment.profile] = json; + } + } + if (duration == 0) { + treatment = t; + // if profile switch contains json of profile inject it in to store to be findable by profile name + if (treatment.profileJson && !pdataActive.store[treatment.profile]) { + if (treatment.profile.indexOf("@@@@@") < 0) + treatment.profile += "@@@@@" + treatment.mills; + let json = JSON.parse(treatment.profileJson); + pdataActive.store[treatment.profile] = json; + } + } } - } }); } @@ -286,6 +295,23 @@ function init (profileData) { else return name.substring(0, index); } + profile.profileFromTime = function profileFromTime (time) { + var profileData = null; + + if (profile.hasData()) { + profileData = profile.data[0]; + for (var i = 0; i < profile.data.length; i++) + { + if (Number(time) >= Number(profile.data[i].mills)) { + profileData = profile.data[i]; + break; + } + } + } + + return profileData; + } + profile.tempBasalTreatment = function tempBasalTreatment (time) { // Most queries for the data in reporting will match the latest found value, caching that hugely improves performance diff --git a/lib/report/predictions.js b/lib/report/predictions.js new file mode 100644 index 00000000000..8e341d0b666 --- /dev/null +++ b/lib/report/predictions.js @@ -0,0 +1,33 @@ +var predictions = { + offset: 0, + backward: function () { + this.offset -= 5; + this.updateOffsetHtml(); + }, + forward: function () { + this.offset += 5; + this.updateOffsetHtml(); + }, + moreBackward: function () { + this.offset -= 30; + this.updateOffsetHtml(); + }, + moreForward: function () { + this.offset += 30; + this.updateOffsetHtml(); + }, + reset: function () { + this.offset = 0; + this.updateOffsetHtml(); + }, + updateOffsetHtml: function () { + $('#rp_predictedOffset').html(this.offset); + } +}; + +$(document).on('change', '#rp_optionspredicted', function() { + $('#rp_predictedSettings').toggle(this.checked); + predictions.reset(); +}); + +module.exports = predictions; diff --git a/lib/report_plugins/daytoday.js b/lib/report_plugins/daytoday.js index f4b5da7cf45..47c16cf71a8 100644 --- a/lib/report_plugins/daytoday.js +++ b/lib/report_plugins/daytoday.js @@ -23,17 +23,17 @@ daytoday.html = function html (client) { '

' + translate('Day to day') + '

' + '' + translate('To see this report, press SHOW while in this view') + '
' + translate('Display') + ': ' + - '' + translate('Insulin') + '' + - '' + translate('Carbs') + '' + - '' + translate('Basal rate') + '' + - '' + translate('Notes') + - '' + translate('Food') + - '' + translate('Raw') + '' + - '' + translate('IOB') + '' + - '' + translate('COB') + '' + - '' + translate('Predictions') + '' + - '' + translate('OpenAPS') + '' + - '' + translate('Insulin distribution') + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + ' ' + translate('Size') + ' ' + '
' + translate('Scale') + ': ' + - '' + - translate('Linear') + - '' + - translate('Logarithmic') + + '' + + '' + '' + '
' + '
' + @@ -362,16 +362,14 @@ daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, optio for (var treatmentsIndex = 0; treatmentsIndex < treatmentsTimestamps.length; treatmentsIndex++) { var timestamp = treatmentsTimestamps[treatmentsIndex]; // TODO refactor code so this is set here - now set as global in file loaded by the browser - // eslint-disable-next-line no-undef - var predictedIndex = findPredicted(predictions, timestamp, predictedOffset); // Find predictions offset before or after timestamp + var predictedIndex = findPredicted(predictions, timestamp, Nightscout.predictions.offset); // Find predictions offset before or after timestamp if (predictedIndex != null) { entry = predictions[predictedIndex]; // Start entry var d = moment(entry.startDate); var end = moment().endOf('day'); if (options.predictedTruncate) { - // eslint-disable-next-line no-undef - if (predictedOffset >= 0) { + if (Nightscout.predictions.offset >= 0) { // If we are looking forward we want to stop at the next treatment if (treatmentsIndex < treatmentsTimestamps.length - 1) { end = moment(treatmentsTimestamps[treatmentsIndex + 1]); @@ -454,6 +452,8 @@ daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, optio data.netBasalNegative[hour] = 0; }); + profile.loadData(datastorage.profiles); + profile.updateTreatments(datastorage.profileSwitchTreatments, datastorage.tempbasalTreatments, datastorage.combobolusTreatments); var bolusInsulin = 0; @@ -739,6 +739,8 @@ daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, optio if (treatment.carbs && options.carbs) { var label = ' ' + treatment.carbs + ' g'; + label += treatment.foodType ? ' ' + treatment.foodType : '' + label += treatment.absorptionTime ? ' ' + (Math.round(treatment.absorptionTime / 60.0 * 10) / 10) + 'h' : '' if (treatment.protein) label += ' / ' + treatment.protein + ' g'; if (treatment.fat) label += ' / ' + treatment.fat + ' g'; @@ -850,6 +852,26 @@ daytoday.report = function report_daytoday (datastorage, sorteddaystoshow, optio .attr('y', yScale2(client.utils.scaleMgdl(306)) + padding.top) .attr('x', xScale2(treatment.mills + times.mins(treatment.duration).msecs / 2) + padding.left) .text(treatment.notes); + } else if (treatment.eventType === 'Temporary Override' && treatment.duration ) { + // Loop Overrides with duration + context.append('rect') + .attr('x', xScale2(treatment.mills) + padding.left) + .attr('y', yScale2(client.utils.scaleMgdl(432)) + padding.top) + .attr('width', xScale2(treatment.mills + times.mins(treatment.duration).msecs) - xScale2(treatment.mills)) + .attr('height', yScale2(client.utils.scaleMgdl(396)) - yScale2(client.utils.scaleMgdl(432))) + .attr('stroke-width', 1) + .attr('opacity', .2) + .attr('stroke', 'white') + .attr('fill', 'black'); + context.append('text') + .style('font-size', '12px') + .style('font-weight', 'bold') + .attr('fill', 'black') + .attr('text-anchor', 'middle') + .attr('dy', '.35em') + .attr('y', yScale2(client.utils.scaleMgdl(414)) + padding.top) + .attr('x', xScale2(treatment.mills + times.mins(treatment.duration).msecs / 2) + padding.left) + .text(treatment.reason); } else if (!treatment.duration) { // other treatments without duration context.append('circle') diff --git a/lib/report_plugins/glucosedistribution.js b/lib/report_plugins/glucosedistribution.js index f97bd034765..21d5213e9c9 100644 --- a/lib/report_plugins/glucosedistribution.js +++ b/lib/report_plugins/glucosedistribution.js @@ -19,9 +19,9 @@ glucosedistribution.html = function html (client) { var ret = '

' + translate('Glucose distribution') + - ' (' + - ' ' + - ' )' + + ' (' + + '' + + ')' + '

' + '' + '' + @@ -122,7 +122,11 @@ glucosedistribution.report = function report_glucosedistribution (datastorage, s var data = datastorage.allstatsrecords; var days = datastorage.alldays; - $('#glucosedistribution-days').text(days + ' ' + translate('days total')); + var reportPlugins = Nightscout.report_plugins; + var firstDay = reportPlugins.utils.localeDate(sorteddaystoshow[sorteddaystoshow.length - 1]); + var lastDay = reportPlugins.utils.localeDate(sorteddaystoshow[0]); + + $('#glucosedistribution-days').text(days + ' ' + translate('days total') + ', ' + firstDay + ' - ' + lastDay); for (var i = 0; i < 24; i++) { $('#glucosedistribution-' + i).unbind('click').click(onClick); diff --git a/lib/report_plugins/loopalyzer.js b/lib/report_plugins/loopalyzer.js index 2d53fa251a3..c37c58f635f 100644 --- a/lib/report_plugins/loopalyzer.js +++ b/lib/report_plugins/loopalyzer.js @@ -318,10 +318,12 @@ loopalyzer.fillNanWithTreatments = function(array, treatments) { var stop = index; // Now move left and right until we find real numbers, so not NaN - // eslint-disable-next-line no-empty - while (start-- >= 0 && isNaN(array[start])) {} - // eslint-disable-next-line no-empty - while (stop++ < array.length && isNaN(array[stop])) {} + while (start >= 0 && isNaN(array[start])) { + start--; + } + while (stop < array.length && isNaN(array[stop])) { + stop++; + } // var gap = stop - start; // if (isNaN(array[start]) || isNaN(array[stop]) || gap > interpolationGap || (gap < interpolationGap && array[start]= interpolationGap || array[start]==0)) ) { @@ -732,8 +734,7 @@ loopalyzer.renderProfilesTable = function(datastoreProfiles, daysToShow, client) if (store) { for (var key in store) { if (laDebug) console.log('profile ' + key); - // eslint-disable-next-line no-prototype-builtins - if (store.hasOwnProperty(key)) { + if (Object.prototype.hasOwnProperty.call(store, key)) { var defaultProfile = store[key]; newEntry.profileName = key; if (defaultProfile.basal) newEntry.basal = defaultProfile.basal; diff --git a/lib/report_plugins/percentile.js b/lib/report_plugins/percentile.js index 803860d5e47..9694fd51faf 100644 --- a/lib/report_plugins/percentile.js +++ b/lib/report_plugins/percentile.js @@ -15,11 +15,17 @@ module.exports = init; percentile.html = function html(client) { var translate = client.translate; var ret = - '

' + translate('Glucose Percentile report') + '

' - + '
' - + '
' - + '
' - ; + '

' + + translate('Glucose Percentile report') + + ' (' + + '' + + ')' + + '

' + + '
' + + '
' + + '
' + ; + return ret; }; @@ -36,16 +42,23 @@ percentile.report = function report_percentile(datastorage, sorteddaystoshow, op var translate = client.translate; var ss = require('simple-statistics'); - var minutewindow = 30; //minute-window should be a divisor of 60 - + var minutewindow = 30; //minute-window should be a divisor of 60 + var data = datastorage.allstatsrecords; - + var bins = []; var filterFunc = function withinWindow(record) { var recdate = new Date(record.displayTime); return recdate.getHours() === hour && recdate.getMinutes() >= minute && recdate.getMinutes() < minute + minutewindow; }; - + + var reportPlugins = Nightscout.report_plugins; + var firstDay = reportPlugins.utils.localeDate(sorteddaystoshow[sorteddaystoshow.length - 1]); + var lastDay = reportPlugins.utils.localeDate(sorteddaystoshow[0]); + var countDays = sorteddaystoshow.length; + + $('#percentile-days').text(countDays + ' ' + translate('days total') + ', ' + firstDay + ' - ' + lastDay); + for (var hour = 0; hour < 24; hour++) { for (var minute = 0; minute < 60; minute = minute + minutewindow) { var date = new Date(); diff --git a/lib/report_plugins/profiles.js b/lib/report_plugins/profiles.js index 580367891de..49c41d30aa9 100644 --- a/lib/report_plugins/profiles.js +++ b/lib/report_plugins/profiles.js @@ -30,8 +30,7 @@ profiles.css = ' height: 100%;' + '}'; -// eslint-disable-next-line no-unused-vars -profiles.report = function report_profiles (datastorage, sorteddaystoshow, options) { +profiles.report = function report_profiles (datastorage) { var Nightscout = window.Nightscout; var client = Nightscout.client; var translate = client.translate; @@ -91,10 +90,16 @@ profiles.report = function report_profiles (datastorage, sorteddaystoshow, optio function displayRanges (array, array2) { var text = ''; - for (var i = 0; i < array.length; i++) { - text += array[i].time + ' : ' + array[i].value + (array2 ? ' - ' + array2[i].value : '') + '
'; - } + if (array && array2) { + for (let i = 0; i < array.length; i++) { + text += array[i].time + ' : ' + array[i].value + (array2 ? ' - ' + array2[i].value : '') + '
'; + } + } else { + for (let i = 0; i < array.length; i++) { + text += array[i].time + ' : ' + array[i].value + '
'; + } + } return text; } }; diff --git a/lib/report_plugins/treatments.js b/lib/report_plugins/treatments.js index c0215b59b4a..f07c84ad322 100644 --- a/lib/report_plugins/treatments.js +++ b/lib/report_plugins/treatments.js @@ -293,7 +293,7 @@ treatments.report = function report_treatments(datastorage, sorteddaystoshow, op .append($('
').should.be.greaterThan(-1); //dailystats - //TODO FIXME result.indexOf('td class="tdborder" style="background-color:#8f8">Normal: ').should.be.greaterThan(-1); // distribution + result.indexOf('').should.be.greaterThan(-1); // distribution result.indexOf('').should.be.greaterThan(-1); // hourlystats result.indexOf('
').should.be.greaterThan(-1); //success result.indexOf('CAL: Scale: 1.10 Intercept: 31102 Slope: 776.91').should.be.greaterThan(-1); //calibrations diff --git a/tests/security.test.js b/tests/security.test.js index 6b612f1bc6e..1f182970019 100644 --- a/tests/security.test.js +++ b/tests/security.test.js @@ -2,14 +2,14 @@ var request = require('supertest'); var should = require('should'); -var load = require('./fixtures/load'); var language = require('../lib/language')(); describe('API_SECRET', function ( ) { - var api = require('../lib/api/'); - + var api; var scope = this; + function setup_app (env, fn) { + api = require('../lib/api/'); require('../lib/server/bootevent')(env, language).boot(function booted (ctx) { ctx.app = api(env, ctx); scope.app = ctx.app; @@ -18,21 +18,6 @@ describe('API_SECRET', function ( ) { }); } - it('should work fine absent', function (done) { - delete process.env.API_SECRET; - var env = require('../env')( ); - should.not.exist(env.api_secret); - setup_app(env, function (ctx) { - - ctx.app.enabled('api').should.equal(false); - ping_status(ctx.app, again); - function again ( ) { - ping_authorized_endpoint(ctx.app, 404, done); - } - }); - }); - - it('should work fail set unauthorized', function (done) { var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1'; delete process.env.API_SECRET; diff --git a/tests/settings.test.js b/tests/settings.test.js index 3e591cfac27..9c12b5bf483 100644 --- a/tests/settings.test.js +++ b/tests/settings.test.js @@ -28,7 +28,7 @@ describe('settings', function ( ) { settings.alarmTimeagoUrgent.should.equal(true); settings.alarmTimeagoUrgentMins.should.equal(30); settings.language.should.equal('en'); - settings.showPlugins.should.equal(''); + settings.showPlugins.should.equal('dbsize'); settings.insecureUseHttp.should.equal(false); settings.secureHstsHeader.should.equal(true); settings.secureCsp.should.equal(false); diff --git a/tests/timeago.test.js b/tests/timeago.test.js index c0c88b8a1b1..66306a3d154 100644 --- a/tests/timeago.test.js +++ b/tests/timeago.test.js @@ -43,33 +43,6 @@ describe('timeago', function() { done(); }); - it('should suspend alarms due to hibernation when 2 heartbeats are skipped on server', function() { - ctx.ddata.sgvs = [{ mills: Date.now() - times.mins(16).msecs, mgdl: 100, type: 'sgv' }]; - - var sbx = freshSBX() - var status = timeago.checkStatus(sbx); - // By default (no hibernation detected) a warning should be given - // we force no hibernation by checking status twice - status = timeago.checkStatus(sbx); - should.equal(status, 'warn'); - - // 10ms more than suspend-threshold to prevent flapping tests - var timeoutMs = 2 * ctx.settings.heartbeat * 1000 + 100; - return new Promise(function(resolve, reject) { - setTimeout(function() { - status = timeago.checkStatus(sbx); - // Because hibernation should now be detected, no warning should be given - should.equal(status, 'current'); - - // We immediately ask status again, so hibernation should not be detected anymore, - // and we should receive a warning again - status = timeago.checkStatus(sbx); - should.equal(status, 'warn'); - - resolve() - }, timeoutMs) - }) - }); it('should trigger a warning when data older than 15m', function(done) { ctx.notifications.initRequests(); @@ -80,9 +53,6 @@ describe('timeago', function() { var currentTime = new Date().getTime(); - // eslint-disable-next-line no-empty - while (currentTime + 500 >= new Date().getTime()) {} - var highest = ctx.notifications.findHighestAlarm('Time Ago'); highest.level.should.equal(levels.WARN); highest.message.should.equal('Last received: 16 mins ago\nBG Now: 100 mg/dl'); diff --git a/tests/units.test.js b/tests/units.test.js index b6e8a9faa8f..2fbef0c4d3e 100644 --- a/tests/units.test.js +++ b/tests/units.test.js @@ -13,4 +13,20 @@ describe('units', function ( ) { units.mgdlToMMOL(180).should.equal('10.0'); }); + it('should convert 5.5 to 99', function () { + units.mmolToMgdl(5.5).should.equal(99); + }); + + it('should convert 10.0 to 180', function () { + units.mmolToMgdl(10.0).should.equal(180); + }); + + it('should convert 5.5 mmol and then convert back to 5.5 mmol', function () { + units.mgdlToMMOL(units.mmolToMgdl(5.5)).should.equal('5.5'); + }); + + it('should convert 99 mgdl and then convert back to 99 mgdl', function () { + units.mmolToMgdl(units.mgdlToMMOL(99)).should.equal(99); + }); + }); diff --git a/views/adminindex.html b/views/adminindex.html index 6108d1b3978..9b4ff750d2e 100644 --- a/views/adminindex.html +++ b/views/adminindex.html @@ -26,32 +26,21 @@ - + - + <% include preloadCSS %> - - -
X
- -
-

Nightscout

-
- -
-

Admin Tools

-
+ + <%- include('partials/toolbar') %>
- -
- Authentication status: - - - - + <%- include('partials/authentication-status') %> + + + + diff --git a/views/clockviews/bgclock.css b/views/clockviews/bgclock.css deleted file mode 100644 index 3e2cbef246f..00000000000 --- a/views/clockviews/bgclock.css +++ /dev/null @@ -1,28 +0,0 @@ -.inner { - -webkit-transform: translateY(-2%); -} - -#bgnow, #arrowDiv { - display: flex; - flex-grow: 0; - font-weight: 700; - font-size: 30vmin; - padding: 0 20px; - margin: 0; -} - -img#arrow { - height: 18vmin; - filter: brightness(50%); - -webkit-transform: translateY(5%); -} - -#clock { - font-weight: 700; - font-size: 25vmin; - display: inline; -} - -.stale { - text-decoration: line-through; -} \ No newline at end of file diff --git a/views/clockviews/clock-color.css b/views/clockviews/clock-color.css deleted file mode 100644 index 6a6796ef823..00000000000 --- a/views/clockviews/clock-color.css +++ /dev/null @@ -1,32 +0,0 @@ -body { - color: white; -} - -#trend { - -webkit-transform: translateX(1%); - -webkit-flex-direction: column; - flex-direction: column; -} - -#bgnow { - display: inline-block; - vertical-align: middle; -} - -#delta { - font-size: 16vmin; - vertical-align: middle; -} - -#innerTrend { - word-spacing: 2em; -} - -#arrowDiv { - flex-grow: 1; - text-align: center; -} - -img#arrow { - height: 30vmin; -} \ No newline at end of file diff --git a/views/clockviews/clock-config.css b/views/clockviews/clock-config.css new file mode 100644 index 00000000000..0d5f2b8b912 --- /dev/null +++ b/views/clockviews/clock-config.css @@ -0,0 +1,39 @@ +#config-form { + position: fixed; + top: 10px; + left: 10px; + width: 250px; + min-width: 220px; + background: white; + color: black; + opacity: 0.8; + padding: 1%; + font-size: 10px; +} +#config-form p { + margin: 15px; + text-align: left; +} +input.elmt { + width: 120px; +} +select { + width: 100%; +} +#facename { + font-size: 7px; +} +#clocklink { + font-size: 18px; +} +#clocklink:link, #clocklink:visited { + background-color: #f44336; + color: white; + padding: 14px 25px; + text-align: center; + text-decoration: none; + display: inline-block; +} +#clocklink:hover, #clocklink:active { + background-color: red; +} \ No newline at end of file diff --git a/views/clockviews/clock-config.html b/views/clockviews/clock-config.html new file mode 100644 index 00000000000..fff92bb65cb --- /dev/null +++ b/views/clockviews/clock-config.html @@ -0,0 +1,65 @@ +
+

Clock view configurator

+ +

+ + +

+

+ + +

+

SGV age threshold: minutes

+

+

Size:

+

Size:

+

Size:

+

Size:

+

Size:

+

+ Open my clock view! +
cy10
+ +
+ \ No newline at end of file diff --git a/views/clockviews/clock-shared.css b/views/clockviews/clock-shared.css index 83328fe4114..fc624a52c00 100644 --- a/views/clockviews/clock-shared.css +++ b/views/clockviews/clock-shared.css @@ -3,57 +3,50 @@ body { margin: 0 0; padding: 0; overflow: hidden; - font-family: 'Open Sans'; + font-family: 'Open Sans', Arial, Helvetica, sans-serif; color: grey; background-color: black; } main { + height: 100vh; +} + +#inner { display: -webkit-box; display: -ms-flexbox; display: -webkit-flex; display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - -webkit-align-items: center; align-items: center; - height: 100vh; -} - -.inner { + justify-content: center; + align-content: center; + flex-flow: wrap; + height: 100%; width: 100%; - -webkit-transform: translateY(-5%); } -#bgnow { - font-weight: 700; - font-size: 40vmin; +#inner div { + margin-right: 2vmin; + margin-left: 2vmin; + line-height: 1em; } -#trend { - display: -ms-flexbox; - display: -webkit-flex; - display: flex; - -ms-flex-align: center; - -webkit-align-items: center; - align-items: center; - justify-content: center; - -webkit-flex-direction: row; - flex-direction: row; +#inner div img { + height: 100%; } -#staleTime { - flex-grow: 1; - font-size: 6vmin; - display: none; +#inner div.nl { + width: 100%; + margin: 0; + height: 3vmin; } -#clock { - display: none; +#errorMessage { + font-size: 25em; } -#delta { - display: none; +.stale { + text-decoration: line-through; } .close { diff --git a/views/clockviews/clock.css b/views/clockviews/clock.css deleted file mode 100644 index 96ffe68b84a..00000000000 --- a/views/clockviews/clock.css +++ /dev/null @@ -1,5 +0,0 @@ -#trend { - -webkit-transform: translateX(1%); - -webkit-flex-direction: column; - flex-direction: column; -} \ No newline at end of file diff --git a/views/clockviews/shared.html b/views/clockviews/clock.html similarity index 86% rename from views/clockviews/shared.html rename to views/clockviews/clock.html index cb27b137dfb..2893aec3612 100644 --- a/views/clockviews/shared.html +++ b/views/clockviews/clock.html @@ -1,5 +1,5 @@ - + @@ -21,26 +21,19 @@
-
-
-
- - -
-
arrow
-
-
-
+
>
- + + <%if (face == 'config') { %> + <%- include('clock-config.html', {}); %> + <% } %> diff --git a/views/error.html b/views/error.html new file mode 100644 index 00000000000..580618c4071 --- /dev/null +++ b/views/error.html @@ -0,0 +1,64 @@ + + + + + + + + Nightscout - Boot error + + + + + + + + + + + + + + + + + +
').css('width','150px').attr('align','left').append(translate('Event Type'))) .append($('').css('width','150px').attr('align','left').append(translate('Blood Glucose'))) .append($('').css('width','50px').attr('align','left').append(translate('Insulin'))) - .append($('').css('width','50px').attr('align','left').append(translate('Carbs'))) + .append($('').css('width','100px').attr('align','left').append(translate('Carbs/Food/Time'))) .append($('').css('width','50px').attr('align','left').append(translate('Protein'))) .append($('').css('width','50px').attr('align','left').append(translate('Fat'))) .append($('').css('width','50px').attr('align','left').append(translate('Duration'))) @@ -316,6 +316,25 @@ treatments.report = function report_treatments(datastorage, sorteddaystoshow, op } for (var t=0; t').addClass('border_bottom') .append($('') .append($('').addClass('deleteTreatment').css('cursor','pointer').attr('title',translate('Delete record')).attr('src',icon_remove).attr('data',JSON.stringify(tr)).attr('day',day)) @@ -323,10 +342,11 @@ treatments.report = function report_treatments(datastorage, sorteddaystoshow, op .append($('').addClass('editTreatment').css('cursor','pointer').attr('title',translate('Edit record')).attr('src',icon_edit).attr('data',JSON.stringify(tr)).attr('day',day)) ) .append($('').append(new Date(tr.created_at).toLocaleTimeString().replace(/([\d]+:[\d]{2})(:[\d]{2})(.*)/, '$1$3'))) - .append($('').append(tr.eventType ? translate(client.careportal.resolveEventName(tr.eventType)) : '')) + .append($('').append(tr.eventType ? translate(client.careportal.resolveEventName(tr.eventType)) + (tr.reason ? '
' + tr.reason : '') + + (tr.insulinNeedsScaleFactor ? '
' + tr.insulinNeedsScaleFactor * 100 + '%' : '') + (tr.correctionRange ? ' ' + correctionRangeText : '') : '')) .append($('
').attr('align','center').append(tr.glucose ? tr.glucose + ' ('+translate(tr.glucoseType)+')' : '')) .append($('').attr('align','center').append(tr.insulin ? tr.insulin.toFixed(2) : '')) - .append($('').attr('align','center').append(tr.carbs ? tr.carbs : '')) + .append($('').attr('align','center').append(carbs)) .append($('').attr('align','center').append(tr.protein ? tr.protein : '')) .append($('').attr('align','center').append(tr.fat ? tr.fat : '')) .append($('').attr('align','center').append(tr.duration ? tr.duration.toFixed(0) : '')) diff --git a/lib/sandbox.js b/lib/sandbox.js index 4bcee3b40e4..6805bee6982 100644 --- a/lib/sandbox.js +++ b/lib/sandbox.js @@ -45,6 +45,7 @@ function init () { reset(); sbx.runtimeEnvironment = 'server'; + sbx.runtimeState = ctx.runtimeState; sbx.time = Date.now(); sbx.settings = env.settings; sbx.data = ctx.ddata.clone(); diff --git a/lib/server/booterror.js b/lib/server/booterror.js index f08eb06db39..92de6cbc81b 100644 --- a/lib/server/booterror.js +++ b/lib/server/booterror.js @@ -1,22 +1,46 @@ 'use strict'; +const express = require('express'); +const path = require('path'); var _ = require('lodash'); -var head = 'Nightscout - Boot Error

Nightscout - Boot Error

'; -var tail = '
'; +function bootError(env, ctx) { -function bootError(ctx) { + const app = new express(); + let locals = {}; + + app.set('view engine', 'ejs'); + app.engine('html', require('ejs').renderFile); + app.set("views", path.join(__dirname, "../../views/")); + + app.get('*', (req, res, next) => { + + if (req.url.includes('images')) return next(); - return function pageHandler (req, res) { var errors = _.map(ctx.bootErrors, function (obj) { - obj.err = _.pick(obj.err, Object.getOwnPropertyNames(obj.err)); - return '
' + obj.desc + '
' + JSON.stringify(obj.err).replace(/\\n/g, '
') + '
'; + + let message; + + if (typeof obj.err === 'string' || obj.err instanceof String) { + message = obj.err; + } else { + message = JSON.stringify(_.pick(obj.err, Object.getOwnPropertyNames(obj.err))); + } + return '
' + obj.desc + '
' + message.replace(/\\n/g, '
') + '
'; }).join(' '); - res.set('Content-Type', 'text/html'); - res.send(head + errors + tail); + res.render('error.html', { + errors, + locals + }); + + }); + app.setLocals = function (_locals) { + locals = _locals; } + + return app; } module.exports = bootError; \ No newline at end of file diff --git a/lib/server/bootevent.js b/lib/server/bootevent.js index 2bb63ad78f0..ff4e9110f00 100644 --- a/lib/server/bootevent.js +++ b/lib/server/bootevent.js @@ -6,6 +6,11 @@ var UPDATE_THROTTLE = 5000; function boot (env, language) { + function startBoot(ctx, next) { + ctx.runtimeState = 'booting'; + next(); + } + ////////////////////////////////////////////////// // Check Node version. // Latest Node 8 LTS and Latest Node 10 LTS are recommended and supported. @@ -25,30 +30,21 @@ function boot (env, language) { var semver = require('semver'); var nodeVersion = process.version; - if ( semver.satisfies(nodeVersion, '^8.15.1') || semver.satisfies(nodeVersion, '^10.16.0')) { - //Latest Node 8 LTS and Latest Node 10 LTS are recommended and supported. + const isLTS = process.release.lts ? true : false; + + if (!isLTS) { + console.log( 'ERROR: Node version ' + nodeVersion + ' is not supported. Please use a secure LTS version or upgrade your Node'); + process.exit(1); + } + + if (semver.satisfies(nodeVersion, '^12.0.0') || semver.satisfies(nodeVersion, '^10.0.0')) { + //Latest Node 10 LTS and Node 12 LTS are recommended and supported. //Require at least Node 8 LTS and Node 10 LTS without known security issues console.debug('Node LTS version ' + nodeVersion + ' is supported'); next(); } - else if ( semver.eq(nodeVersion, '10.15.2')) { - //Latest Node version on Azure is tolerated, but not recommended - console.log('WARNING: Node version v10.15.2 and Microsoft Azure are not recommended.'); - console.log('WARNING: Please migrate to another hosting provider. Your Node version is outdated and insecure'); - next(); - } - else if ( semver.satisfies(nodeVersion, '^12.6.0')) { - //Latest Node version - console.debug('Node version ' + nodeVersion + ' is not a LTS version. Not recommended. Not supported'); - next(); - } else { - // Other versions will not start - console.log( 'ERROR: Node version ' + nodeVersion + ' is not supported. Please use a secure LTS version or upgrade your Node'); - process.exit(1); - } } - function checkEnv (ctx, next) { ctx.language = language; if (env.err) { @@ -95,6 +91,25 @@ function boot (env, language) { } } + function checkSettings (ctx, next) { + + ctx.bootErrors = ctx.bootErrors || []; + + console.log('Checking settings'); + + if (!env.storageURI) { + ctx.bootErrors.push({'desc': 'Mandatory setting missing', + err: 'MONGODB_URI setting is missing, cannot connect to database'}); + } + + if (!env.api_secret) { + ctx.bootErrors.push({'desc': 'Mandatory setting missing', + err: 'API_SECRET setting is missing, cannot enable REST API'}); + } + + next(); + } + function setupStorage (ctx, next) { if (hasBootErrors(ctx)) { @@ -107,7 +122,6 @@ function boot (env, language) { if (err) { throw err; } - ctx.store = store; console.log('OpenAPS Storage system ready'); next(); @@ -116,16 +130,20 @@ function boot (env, language) { //TODO assume mongo for now, when there are more storage options add a lookup require('../storage/mongo-storage')(env, function ready(err, store) { // FIXME, error is always null, if there is an error, the index.js will throw an exception + if (err) { + console.info('ERROR CONNECTING TO MONGO', err); + ctx.bootErrors = ctx.bootErrors || [ ]; + ctx.bootErrors.push({'desc': 'Unable to connect to Mongo', err: err.message}); + } console.log('Mongo Storage system ready'); ctx.store = store; - next(); }); } } catch (err) { - console.info('mongo err', err); + console.info('ERROR CONNECTING TO MONGO', err); ctx.bootErrors = ctx.bootErrors || [ ]; - ctx.bootErrors.push({'desc': 'Unable to connect to Mongo', err: err}); + ctx.bootErrors.push({'desc': 'Unable to connect to Mongo', err: err.message}); next(); } } @@ -176,9 +194,14 @@ function boot (env, language) { ctx.properties = require('../api/properties')(env, ctx); ctx.bus = require('../bus')(env.settings, ctx); ctx.ddata = require('../data/ddata')(); + ctx.cache = require('./cache')(env,ctx); ctx.dataloader = require('../data/dataloader')(env, ctx); ctx.notifications = require('../notifications')(env, ctx); + if (env.settings.isEnabled('alexa') || env.settings.isEnabled('googlehome')) { + ctx.virtAsstBase = require('../plugins/virtAsstBase')(env, ctx); + } + if (env.settings.isEnabled('alexa')) { ctx.alexa = require('../plugins/alexa')(env, ctx); } @@ -228,7 +251,7 @@ function boot (env, language) { }); ctx.bus.on('data-loaded', function updatePlugins ( ) { - console.info('reloading sandbox data'); + console.info('data loaded: reloading sandbox data and updating plugins'); var sbx = require('../sandbox')().serverInit(env, ctx); ctx.plugins.setProperties(sbx); ctx.notifications.initRequests(); @@ -237,6 +260,10 @@ function boot (env, language) { ctx.bus.emit('data-processed'); }); + ctx.bus.on('data-processed', function processed ( ) { + ctx.runtimeState = 'loaded'; + }); + ctx.bus.on('notification', ctx.pushnotify.emitNotification); next( ); @@ -247,7 +274,7 @@ function boot (env, language) { return next(); } - ctx.bridge = require('../plugins/bridge')(env); + ctx.bridge = require('../plugins/bridge')(env, ctx.bus); if (ctx.bridge) { ctx.bridge.startEngine(ctx.entries); } @@ -259,7 +286,7 @@ function boot (env, language) { return next(); } - ctx.mmconnect = require('../plugins/mmconnect').init(env, ctx.entries, ctx.devicestatus); + ctx.mmconnect = require('../plugins/mmconnect').init(env, ctx.entries, ctx.devicestatus, ctx.bus); if (ctx.mmconnect) { ctx.mmconnect.run(); } @@ -271,15 +298,18 @@ function boot (env, language) { return next(); } + ctx.runtimeState = 'booted'; ctx.bus.uptime( ); next( ); } return require('bootevent')( ) + .acquire(startBoot) .acquire(checkNodeVersion) .acquire(checkEnv) .acquire(augmentSettings) + .acquire(checkSettings) .acquire(setupStorage) .acquire(setupAuthorization) .acquire(setupInternals) diff --git a/lib/server/cache.js b/lib/server/cache.js new file mode 100644 index 00000000000..88e5f77ca02 --- /dev/null +++ b/lib/server/cache.js @@ -0,0 +1,103 @@ +'use strict'; + +/* This is a simple cache intended to reduce the amount of load + * Nightscout puts on MongoDB. The cache is based on identifying + * elements based on the MongoDB _id field and implements simple + * semantics for adding data to the cache in the runtime, intended + * to be accessed by the persistence layer as data is inserted, updated + * or deleted, as well as the periodic dataloader, which polls Mongo + * for new inserts. + * + * Longer term, the cache is planned to allow skipping the Mongo polls + * altogether. + */ + +const _ = require('lodash'); +const constants = require('../constants'); + +function cache (env, ctx) { + + const data = { + treatments: [] + , devicestatus: [] + , entries: [] + }; + + const retentionPeriods = { + treatments: constants.ONE_HOUR * 60 + , devicestatus: env.extendedSettings.devicestatus && env.extendedSettings.devicestatus.days && env.extendedSettings.devicestatus.days == 2 ? constants.TWO_DAYS : constants.ONE_DAY + , entries: constants.TWO_DAYS + }; + + function mergeCacheArrays (oldData, newData, retentionPeriod) { + + const ageLimit = Date.now() - retentionPeriod; + + var filteredOld = filterForAge(oldData, ageLimit); + var filteredNew = filterForAge(newData, ageLimit); + + const merged = ctx.ddata.idMergePreferNew(filteredOld, filteredNew); + + return _.sortBy(merged, function(item) { + return -item.mills; + }); + + function filterForAge(data, ageLimit) { + return _.filter(data, function hasId(object) { + const hasId = !_.isEmpty(object._id); + const isFresh = object.mills >= ageLimit; + return isFresh && hasId; + }); + } + + } + + data.isEmpty = (datatype) => { + return data[datatype].length < 20; + } + + data.getData = (datatype) => { + return _.cloneDeep(data[datatype]); + } + + data.insertData = (datatype, newData) => { + data[datatype] = mergeCacheArrays(data[datatype], newData, retentionPeriods[datatype]); + return data.getData(datatype); + } + + function dataChanged (operation) { + if (!data[operation.type]) return; + + if (operation.op == 'remove') { + // if multiple items were deleted, flush entire cache + if (!operation.changes) { + data.treatments = []; + data.devicestatus = []; + data.entries = []; + } else { + removeFromArray(data[operation.type], operation.changes); + } + } + + if (operation.op == 'update') { + data[operation.type] = mergeCacheArrays(data[operation.type], operation.changes, retentionPeriods[operation.type]); + } + } + + ctx.bus.on('data-update', dataChanged); + + function removeFromArray (array, id) { + for (let i = 0; i < array.length; i++) { + const o = array[i]; + if (o._id == id) { + //console.log('Deleting object from cache', id); + array.splice(i, 1); + break; + } + } + } + + return data; +} + +module.exports = cache; diff --git a/lib/server/clocks.js b/lib/server/clocks.js index 282acd01951..9926eefcf82 100644 --- a/lib/server/clocks.js +++ b/lib/server/clocks.js @@ -3,8 +3,7 @@ const express = require('express'); const path = require('path'); -// eslint-disable-next-line no-unused-vars -function clockviews(env, ctx) { +function clockviews() { const app = new express(); let locals = {}; @@ -18,7 +17,7 @@ function clockviews(env, ctx) { const face = req.params.face; console.log('Clockface requested:', face); - res.render('shared.html', { + res.render('clock.html', { face, locals }); diff --git a/lib/server/devicestatus.js b/lib/server/devicestatus.js index d35c6be87cb..bf71437d646 100644 --- a/lib/server/devicestatus.js +++ b/lib/server/devicestatus.js @@ -5,26 +5,55 @@ var find_options = require('./query'); function storage (collection, ctx) { - function create(obj, fn) { - - // Normalize all dates to UTC - const d = moment(obj.created_at).isValid() ? moment.parseZone(obj.created_at) : moment(); - obj.created_at = d.toISOString(); - obj.utcOffset = d.utcOffset(); - - api().insert(obj, function (err, doc) { - if (err != null && err.message) { - console.log('Error inserting the device status object', err.message); - fn(err.message, null); - return; - } - fn(null, doc.ops); - ctx.bus.emit('data-received'); - }); + function create (statuses, fn) { + + if (!Array.isArray(statuses)) { statuses = [statuses]; } + + const r = []; + let errorOccurred = false; + + for (let i = 0; i < statuses.length; i++) { + + const obj = statuses[i]; + + if (errorOccurred) return; + + // Normalize all dates to UTC + const d = moment(obj.created_at).isValid() ? moment.parseZone(obj.created_at) : moment(); + obj.created_at = d.toISOString(); + obj.utcOffset = d.utcOffset(); + + api().insertOne(obj, function(err, results) { + if (err !== null && err.message) { + console.log('Error inserting the device status object', err.message); + errorOccurred = true; + fn(err.message, null); + return; + } + + if (!err) { + + if (!obj._id) obj._id = results.insertedIds[0]._id; + r.push(obj); + + ctx.bus.emit('data-update', { + type: 'devicestatus' + , op: 'update' + , changes: ctx.ddata.processRawDataForRuntime([obj]) + }); + + // Last object! Return results + if (i == statuses.length - 1) { + fn(null, r); + ctx.bus.emit('data-received'); + } + } + }); + }; } - function last(fn) { - return list({count: 1}, function (err, entries) { + function last (fn) { + return list({ count: 1 }, function(err, entries) { if (entries && entries.length > 0) { fn(err, entries[0]); } else { @@ -37,18 +66,18 @@ function storage (collection, ctx) { return find_options(opts, storage.queryOpts); } - function list(opts, fn) { + function list (opts, fn) { // these functions, find, sort, and limit, are used to // dynamically configure the request, based on the options we've // been given // determine sort options - function sort ( ) { - return opts && opts.sort || {created_at: -1}; + function sort () { + return opts && opts.sort || { created_at: -1 }; } // configure the limit portion of the current query - function limit ( ) { + function limit () { if (opts && opts.count) { return this.limit(parseInt(opts.count)); } @@ -61,17 +90,31 @@ function storage (collection, ctx) { } // now just stitch them all together - limit.call(api( ) - .find(query_for(opts)) - .sort(sort( )) + limit.call(api() + .find(query_for(opts)) + .sort(sort()) ).toArray(toArray); } function remove (opts, fn) { - return api( ).remove(query_for(opts), fn); + + function removed (err, stat) { + + ctx.bus.emit('data-update', { + type: 'devicestatus' + , op: 'remove' + , count: stat.result.n + , changes: opts.find._id + }); + + fn(err, stat); + } + + return api().remove( + query_for(opts), removed); } - function api() { + function api () { return ctx.store.collection(collection); } @@ -80,9 +123,13 @@ function storage (collection, ctx) { api.query_for = query_for; api.last = last; api.remove = remove; - api.aggregate = require('./aggregate')({ }, api); + api.aggregate = require('./aggregate')({}, api); api.indexedFields = [ 'created_at' + + + + , 'NSCLIENT_ID' ]; return api; diff --git a/lib/server/entries.js b/lib/server/entries.js index d7258f13b79..50c8e0cc41a 100644 --- a/lib/server/entries.js +++ b/lib/server/entries.js @@ -10,52 +10,60 @@ var moment = require('moment'); * Encapsulate persistent storage of sgv entries. \**********/ -function storage(env, ctx) { +function storage (env, ctx) { // TODO: Code is a little redundant. // query for entries from storage function list (opts, fn) { - // these functions, find, sort, and limit, are used to - // dynamically configure the request, based on the options we've - // been given + // these functions, find, sort, and limit, are used to + // dynamically configure the request, based on the options we've + // been given - // determine sort options - function sort ( ) { - return opts && opts.sort || {date: -1}; - } + // determine sort options + function sort () { + return opts && opts.sort || { date: -1 }; + } - // configure the limit portion of the current query - function limit ( ) { - if (opts && opts.count) { - return this.limit(parseInt(opts.count)); - } - return this; + // configure the limit portion of the current query + function limit () { + if (opts && opts.count) { + return this.limit(parseInt(opts.count)); } + return this; + } - // handle all the results - function toArray (err, entries) { - fn(err, entries); - } + // handle all the results + function toArray (err, entries) { + fn(err, entries); + } - // now just stitch them all together - limit.call(api( ) - .find(query_for(opts)) - .sort(sort( )) - ).toArray(toArray); + // now just stitch them all together + limit.call(api() + .find(query_for(opts)) + .sort(sort()) + ).toArray(toArray); } function remove (opts, fn) { - api( ).remove(query_for(opts), function (err, stat) { - //TODO: this is triggering a read from Mongo, we can do better - ctx.bus.emit('data-received'); - fn(err, stat); + api().remove(query_for(opts), function(err, stat) { + + ctx.bus.emit('data-update', { + type: 'entries' + , op: 'remove' + , count: stat.result.n + , changes: opts.find._id }); + + //TODO: this is triggering a read from Mongo, we can do better + ctx.bus.emit('data-received'); + fn(err, stat); + }); } // return writable stream to lint each sgv record passing through it // TODO: get rid of this? not doing anything now - function map ( ) { + function map () { return es.map(function iter (item, next) { return next(null, item); }); @@ -72,7 +80,7 @@ function storage(env, ctx) { create(result, fn); } // lint and store the entire list - return es.pipeline(map( ), es.writeArray(done)); + return es.pipeline(map(), es.writeArray(done)); } //TODO: implement @@ -83,9 +91,9 @@ function storage(env, ctx) { // store new documents using the storage mechanism function create (docs, fn) { // potentially a batch insert - var firstErr = null, - numDocs = docs.length, - totalCreated = 0; + var firstErr = null + , numDocs = docs.length + , totalCreated = 0; docs.forEach(function(doc) { @@ -98,9 +106,22 @@ function storage(env, ctx) { doc.sysTime = _sysTime.toISOString(); if (doc.dateString) doc.dateString = doc.sysTime; - var query = (doc.sysTime && doc.type) ? {sysTime: doc.sysTime, type: doc.type} : doc; - api( ).update(query, doc, {upsert: true}, function (err) { + var query = (doc.sysTime && doc.type) ? { sysTime: doc.sysTime, type: doc.type } : doc; + api().update(query, doc, { upsert: true }, function(err, updateResults) { firstErr = firstErr || err; + + if (!err) { + if (updateResults.result.upserted) { + doc._id = updateResults.result.upserted[0]._id + } + + ctx.bus.emit('data-update', { + type: 'entries' + , op: 'update' + , changes: ctx.ddata.processRawDataForRuntime([doc]) + }); + } + if (++totalCreated === numDocs) { //TODO: this is triggering a read from Mongo, we can do better ctx.bus.emit('data-received'); @@ -110,8 +131,8 @@ function storage(env, ctx) { }); } - function getEntry(id, fn) { - api( ).findOne({_id: ObjectID(id)}, function (err, entry) { + function getEntry (id, fn) { + api().findOne({ _id: ObjectID(id) }, function(err, entry) { if (err) { fn(err); } else { @@ -125,7 +146,7 @@ function storage(env, ctx) { } // closure to represent the API - function api ( ) { + function api () { // obtain handle usable for querying the collection associated // with these records return ctx.store.collection(env.entries_collection); @@ -139,8 +160,22 @@ function storage(env, ctx) { api.persist = persist; api.query_for = query_for; api.getEntry = getEntry; - api.aggregate = require('./aggregate')({ }, api); - api.indexedFields = [ 'date', 'type', 'sgv', 'mbg', 'sysTime', 'dateString' ]; + api.aggregate = require('./aggregate')({}, api); + api.indexedFields = [ + 'date' + + , 'type' + + , 'sgv' + + , 'mbg' + + , 'sysTime' + + , 'dateString' + + , { 'type': 1, 'date': -1, 'dateString': 1 } + ]; return api; } @@ -153,11 +188,10 @@ storage.queryOpts = { , rssi: parseInt , noise: parseInt , mbg: parseInt - } + } , useEpoch: true }; // expose module storage.storage = storage; module.exports = storage; - diff --git a/lib/server/loop.js b/lib/server/loop.js index 6a04fcd73aa..ca87892bba6 100644 --- a/lib/server/loop.js +++ b/lib/server/loop.js @@ -1,4 +1,4 @@ -'use strict'; +//'use strict'; const apn = require('apn'); @@ -9,6 +9,10 @@ function init (env, ctx) { } loop.sendNotification = function sendNotification (data, remoteAddress, completion) { + + // console.info("JAP"); + // console.info(data); + if (env.extendedSettings.loop.apnsKey === undefined || env.extendedSettings.loop.apnsKey.length == 0) { completion("Loop notification failed: LOOP_APNS_KEY not set."); return; @@ -24,11 +28,6 @@ function init (env, ctx) { return; } - if (env.extendedSettings.loop.developerTeamId === undefined || env.extendedSettings.loop.developerTeamId.length != 10) { - completion("Loop notification failed: LOOP_DEVELOPER_TEAM_ID not set."); - return; - } - if (ctx.ddata.profiles === undefined || ctx.ddata.profiles.length < 1 || ctx.ddata.profiles[0].loopSettings === undefined) { completion("Loop notification failed: Could not find loopSettings in profile."); return; @@ -68,7 +67,38 @@ function init (env, ctx) { alert = "Cancel Temporary Override"; } else if (data.eventType === 'Temporary Override') { payload["override-name"] = data.reason; + if (data.duration !== undefined && parseInt(data.duration) > 0) { + payload["override-duration-minutes"] = parseInt(data.duration); + } alert = data.reasonDisplay + " Temporary Override"; + } else if (data.eventType === 'Remote Carbs Entry') { + payload["carbs-entry"] = parseFloat(data.remoteCarbs); + if(payload["carbs-entry"] > 0.0 ) { + payload["absorption-time"] = 3.0; + if (data.remoteAbsorption !== undefined && parseFloat(data.remoteAbsorption) > 0.0) { + payload["absorption-time"] = parseFloat(data.remoteAbsorption); + } + if (data.otp !== undefined && data.otp.length > 0) { + payload["otp"] = ""+data.otp + } + alert = "Remote Carbs Entry: "+payload["carbs-entry"]+" grams\n"; + alert += "Absorption Time: "+payload["absorption-time"]+" hours"; + } else { + completion("Loop remote carbs failed. Incorrect carbs entry: ", data.remoteCarbs); + return; + } + + } else if (data.eventType === 'Remote Bolus Entry') { + payload["bolus-entry"] = parseFloat(data.remoteBolus); + if(payload["bolus-entry"] > 0.0 ) { + alert = "Remote Bolus Entry: "+payload["bolus-entry"]+" U\n"; + if (data.otp !== undefined && data.otp.length > 0) { + payload["otp"] = ""+data.otp + } + } else { + completion("Loop remote bolus failed. Incorrect bolus entry: ", data.remoteBolus); + return; + } } else { completion("Loop notification failed: Unhandled event type:", data.eventType); return; @@ -89,10 +119,6 @@ function init (env, ctx) { notification.expiry = Math.round((Date.now() / 1000)) + 60 * 5; // Allow this to enact within 5 minutes. notification.payload = payload; - if (data.duration && parseInt(data.duration) > 0) { - notification.payload["override-duration-minutes"] = parseInt(data.duration); - } - provider.send(notification, [loopSettings.deviceToken]).then( (response) => { if (response.sent && response.sent.length > 0) { completion(); diff --git a/lib/server/pebble.js b/lib/server/pebble.js index 544aa878268..97b756a9b84 100644 --- a/lib/server/pebble.js +++ b/lib/server/pebble.js @@ -176,7 +176,7 @@ function configure (env, ctx) { req.rawbg = env.settings.isEnabled('rawbg'); req.iob = env.settings.isEnabled('iob'); req.cob = env.settings.isEnabled('cob'); - req.mmol = (req.query.units || env.DISPLAY_UNITS) === 'mmol'; + req.mmol = (req.query.units || env.settings.units) === 'mmol'; req.count = parseInt(req.query.count) || 1; next( ); diff --git a/lib/server/profile.js b/lib/server/profile.js index d456b590959..e49e366d15a 100644 --- a/lib/server/profile.js +++ b/lib/server/profile.js @@ -1,5 +1,8 @@ 'use strict'; +var find_options = require('./query'); +var consts = require('../constants'); + function storage (collection, ctx) { var ObjectID = require('mongodb').ObjectID; @@ -23,10 +26,53 @@ function storage (collection, ctx) { ctx.bus.emit('data-received'); } - function list (fn) { - return api( ).find({ }).sort({startDate: -1}).toArray(fn); + function list (fn, count) { + const limit = count !== null ? count : Number(consts.PROFILES_DEFAULT_COUNT); + return api( ).find({ }).limit(limit).sort({startDate: -1}).toArray(fn); + } + + function list_query (opts, fn) { + + storage.queryOpts = { + walker: {} + , dateField: 'startDate' + }; + + function limit () { + if (opts && opts.count) { + return this.limit(parseInt(opts.count)); + } + return this; + } + + return limit.call(api() + .find(query_for(opts)) + .sort(opts && opts.sort && query_sort(opts) || { startDate: -1 }), opts) + .toArray(fn); + } + + function query_for (opts) { + var retVal = find_options(opts, storage.queryOpts); + return retVal; } + function query_sort (opts) { + if (opts && opts.sort) { + var sortKeys = Object.keys(opts.sort); + + for (var i = 0; i < sortKeys.length; i++) { + if (opts.sort[sortKeys[i]] == '1') { + opts.sort[sortKeys[i]] = 1; + } + else { + opts.sort[sortKeys[i]] = -1; + } + } + return opts.sort; + } + } + + function last (fn) { return api().find().sort({startDate: -1}).limit(1).toArray(fn); } @@ -43,6 +89,7 @@ function storage (collection, ctx) { } api.list = list; + api.list_query = list_query; api.create = create; api.save = save; api.remove = remove; diff --git a/lib/server/treatments.js b/lib/server/treatments.js index c02bd50f317..a9107ea99b2 100644 --- a/lib/server/treatments.js +++ b/lib/server/treatments.js @@ -3,7 +3,6 @@ var _ = require('lodash'); var async = require('async'); var moment = require('moment'); - var find_options = require('./query'); function storage (env, ctx) { @@ -25,8 +24,7 @@ function storage (env, ctx) { errs.push(err); callback(err, docs) }); - // eslint-disable-next-line no-unused-vars - }, function (err, docs) { + }, function () { errs = _.compact(errs); done(errs.length > 0 ? errs : null, allDocs); }); @@ -49,12 +47,16 @@ function storage (env, ctx) { }; api( ).update(query, obj, {upsert: true}, function complete (err, updateResults) { + + if (err) console.error('Problem upserting treatment', err); + if (!err) { if (updateResults.result.upserted) { obj._id = updateResults.result.upserted[0]._id } } + // TODO document this feature if (!err && obj.preBolus) { //create a new object to insert copying only the needed fields var pbTreat = { @@ -68,11 +70,32 @@ function storage (env, ctx) { } query.created_at = pbTreat.created_at; - api( ).update(query, pbTreat, {upsert: true}, function pbComplete (err) { + api( ).update(query, pbTreat, {upsert: true}, function pbComplete (err, updateResults) { + + if (!err) { + if (updateResults.result.upserted) { + pbTreat._id = updateResults.result.upserted[0]._id + } + } + var treatments = _.compact([obj, pbTreat]); + + ctx.bus.emit('data-update', { + type: 'treatments', + op: 'update', + changes: ctx.ddata.processRawDataForRuntime(treatments) + }); + fn(err, treatments); }); } else { + + ctx.bus.emit('data-update', { + type: 'treatments', + op: 'update', + changes: ctx.ddata.processRawDataForRuntime([obj]) + }); + fn(err, [obj]); } @@ -100,7 +123,16 @@ function storage (env, ctx) { function remove (opts, fn) { return api( ).remove(query_for(opts), function (err, stat) { - //TODO: this is triggering a read from Mongo, we can do better + //TODO: this is triggering a read from Mongo, we can do better + //console.log('Treatment removed', opts); // , stat); + + ctx.bus.emit('data-update', { + type: 'treatments', + op: 'remove', + count: stat.result.n, + changes: opts.find._id + }); + ctx.bus.emit('data-received'); fn(err, stat); }); @@ -109,7 +141,26 @@ function storage (env, ctx) { function save (obj, fn) { obj._id = new ObjectID(obj._id); prepareData(obj); - api().save(obj, fn); + + function saved (err, created) { + if (!err) { + // console.log('Treatment updated', created); + + ctx.ddata.processRawDataForRuntime(obj); + + ctx.bus.emit('data-update', { + type: 'treatments', + op: 'update', + changes: ctx.ddata.processRawDataForRuntime([obj]) + }); + + } + if (err) console.error('Problem saving treating', err); + + fn(err, created); + } + + api().save(obj, saved); ctx.bus.emit('data-received'); } @@ -134,6 +185,7 @@ function storage (env, ctx) { , 'percent' , 'absolute' , 'duration' + , { 'eventType' : 1, 'duration' : 1, 'created_at' : 1 } ]; api.remove = remove; @@ -147,6 +199,7 @@ function prepareData(obj) { // Convert all dates to UTC dates + // TODO remove this -> must not create new date if missing const d = moment(obj.created_at).isValid() ? moment.parseZone(obj.created_at) : moment(); obj.created_at = d.toISOString(); @@ -170,7 +223,7 @@ function prepareData(obj) { obj.relative = Number(obj.relative); obj.preBolus = Number(obj.preBolus); - //NOTE: the eventTime is sent by the client, but deleted, we only store created_at right now + //NOTE: the eventTime is sent by the client, but deleted, we only store created_at var eventTime; if (obj.eventTime) { eventTime = new Date(obj.eventTime).toISOString(); diff --git a/lib/server/websocket.js b/lib/server/websocket.js index afced8bfb37..7a685ccde05 100644 --- a/lib/server/websocket.js +++ b/lib/server/websocket.js @@ -7,7 +7,7 @@ var ObjectID = require('mongodb').ObjectID; function init (env, ctx, server) { - function websocket ( ) { + function websocket () { return websocket; } @@ -25,21 +25,20 @@ function init (env, ctx, server) { // TODO: this would be better to have somehow integrated/improved var supportedCollections = { - 'treatments' : env.treatments_collection, - 'entries': env.entries_collection, - 'devicestatus': env.devicestatus_collection, - 'profile': env.profile_collection, - 'food': env.food_collection, - 'activity': env.activity_collection + 'treatments': env.treatments_collection + , 'entries': env.entries_collection + , 'devicestatus': env.devicestatus_collection + , 'profile': env.profile_collection + , 'food': env.food_collection + , 'activity': env.activity_collection }; // This is little ugly copy but I was unable to pass testa after making module from status and share with /api/v1/status - // eslint-disable-next-line no-unused-vars - function status (profile) { + function status () { var versionNum = 0; var verParse = /(\d+)\.(\d+)\.(\d+)*/.exec(env.version); if (verParse) { - versionNum = 10000 * parseInt(verParse[1]) + 100 * parseInt(verParse[2]) + 1 * parseInt(verParse[3]) ; + versionNum = 10000 * parseInt(verParse[1]) + 100 * parseInt(verParse[2]) + 1 * parseInt(verParse[3]); } var apiEnabled = env.api_secret ? true : false; @@ -64,14 +63,22 @@ function init (env, ctx, server) { return info; } - function start ( ) { + function start () { io = require('socket.io')({ - 'transports': ['xhr-polling'], 'log level': 0 + 'transports': ['xhr-polling'] + , 'log level': 0 }).listen(server, { //these only effect the socket.io.js file that is sent to the client, but better than nothing - 'browser client minification': true, - 'browser client etag': true, - 'browser client gzip': false + 'browser client minification': true + , 'browser client etag': true + , 'browser client gzip': false + }); + + ctx.bus.on('teardown', function serverTeardown () { + Object.keys(io.sockets.sockets).forEach(function(s) { + io.sockets.sockets[s].disconnect(true); + }); + io.close(); }); } @@ -79,7 +86,7 @@ function init (env, ctx, server) { ctx.authorization.resolve({ api_secret: message.secret, token: message.token }, function resolved (err, result) { if (err) { - return callback( err, { + return callback(err, { read: false , write: false , write_treatment: false @@ -97,9 +104,9 @@ function init (env, ctx, server) { function emitData (delta) { if (lastData.cals) { - console.log(LOG_WS + 'running websocket.emitData', ctx.ddata.lastUpdated); + // console.log(LOG_WS + 'running websocket.emitData', ctx.ddata.lastUpdated); if (lastProfileSwitch !== ctx.ddata.lastProfileFromSwitch) { - console.log(LOG_WS + 'profile switch detected OLD: ' + lastProfileSwitch + ' NEW: ' + ctx.ddata.lastProfileFromSwitch); + // console.log(LOG_WS + 'profile switch detected OLD: ' + lastProfileSwitch + ' NEW: ' + ctx.ddata.lastProfileFromSwitch); delta.status = status(ctx.ddata.profiles); lastProfileSwitch = ctx.ddata.lastProfileFromSwitch; } @@ -107,7 +114,7 @@ function init (env, ctx, server) { } } - function listeners ( ) { + function listeners () { io.sockets.on('connection', function onConnection (socket) { var socketAuthorization = null; var clientType = null; @@ -118,16 +125,15 @@ function init (env, ctx, server) { console.log(LOG_WS + 'Connection from client ID: ', socket.client.id, ' IP: ', remoteIP); io.emit('clients', ++watchers); - socket.on('ack', function onAck(level, group, silenceTime) { + socket.on('ack', function onAck (level, group, silenceTime) { ctx.notifications.ack(level, group, silenceTime, true); }); - socket.on('disconnect', function onDisconnect ( ) { + socket.on('disconnect', function onDisconnect () { io.emit('clients', --watchers); - console.log(LOG_WS + 'Disconnected client ID: ',socket.client.id); + console.log(LOG_WS + 'Disconnected client ID: ', socket.client.id); }); - function checkConditions (action, data) { var collection = supportedCollections[data.collection]; if (!collection) { @@ -162,10 +168,10 @@ function init (env, ctx, server) { socket.on('loadRetro', function loadRetro (opts, callback) { if (callback) { - callback( { result: 'success' } ); + callback({ result: 'success' }); } //TODO: use opts to only send delta for retro data - socket.emit('retroUpdate', {devicestatus: lastData.devicestatus}); + socket.emit('retroUpdate', { devicestatus: lastData.devicestatus }); console.info('sent retroUpdate', opts); }); @@ -179,30 +185,46 @@ function init (env, ctx, server) { // } // } socket.on('dbUpdate', function dbUpdate (data, callback) { - console.log(LOG_WS + 'dbUpdate client ID: ', socket.client.id, ' data: ', data); - var collection = supportedCollections[data.collection]; + console.log(LOG_WS + 'dbUpdate client ID: ', socket.client.id, ' data: ', data); + var collection = supportedCollections[data.collection]; var check = checkConditions('dbUpdate', data); if (check) { - if (callback) { - callback( check ); + if (callback) { + callback(check); } return; } - var id ; + var id; try { - id = new ObjectID(data._id); - } catch (err){ - console.error(err); + id = new ObjectID(data._id); + } catch (err) { + console.error(err); id = new ObjectID(); } - ctx.store.collection(collection).update( - { '_id': id }, - { $set: data.data } + + ctx.store.collection(collection).update({ '_id': id } + , { $set: data.data } + , function(err, results) { + + if (!err) { + ctx.store.collection(collection).findOne({ '_id': id } + , function(err, results) { + console.log('Got results', results); + if (!err) { + ctx.bus.emit('data-update', { + type: data.collection + , op: 'update' + , changes: ctx.ddata.processRawDataForRuntime([results]) + }); + } + }); + } + } ); if (callback) { - callback( { result: 'success' } ); + callback({ result: 'success' }); } ctx.bus.emit('data-received'); }); @@ -217,13 +239,13 @@ function init (env, ctx, server) { // } // } socket.on('dbUpdateUnset', function dbUpdateUnset (data, callback) { - console.log(LOG_WS + 'dbUpdateUnset client ID: ', socket.client.id, ' data: ', data); - var collection = supportedCollections[data.collection]; + console.log(LOG_WS + 'dbUpdateUnset client ID: ', socket.client.id, ' data: ', data); + var collection = supportedCollections[data.collection]; var check = checkConditions('dbUpdate', data); if (check) { - if (callback) { - callback( check ); + if (callback) { + callback(check); } return; } @@ -232,10 +254,25 @@ function init (env, ctx, server) { ctx.store.collection(collection).update( { '_id': objId }, { $unset: data.data } - ); + , function(err, results) { + + if (!err) { + ctx.store.collection(collection).findOne({ '_id': objId } + , function(err, results) { + console.log('Got results', results); + if (!err) { + ctx.bus.emit('data-update', { + type: data.collection + , op: 'update' + , changes: ctx.ddata.processRawDataForRuntime([results]) + }); + } + }); + } + }); if (callback) { - callback( { result: 'success' } ); + callback({ result: 'success' }); } ctx.bus.emit('data-received'); }); @@ -249,14 +286,14 @@ function init (env, ctx, server) { // } // } socket.on('dbAdd', function dbAdd (data, callback) { - console.log(LOG_WS + 'dbAdd client ID: ', socket.client.id, ' data: ', data); + console.log(LOG_WS + 'dbAdd client ID: ', socket.client.id, ' data: ', data); var collection = supportedCollections[data.collection]; var maxtimediff = times.mins(1).msecs; var check = checkConditions('dbAdd', data); if (check) { - if (callback) { - callback( check ); + if (callback) { + callback(check); } return; } @@ -272,7 +309,7 @@ function init (env, ctx, server) { if (data.collection === 'treatments') { var query; if (data.data.NSCLIENT_ID) { - query = { NSCLIENT_ID: data.data.NSCLIENT_ID }; + query = { NSCLIENT_ID: data.data.NSCLIENT_ID }; } else { query = { created_at: data.data.created_at @@ -280,19 +317,19 @@ function init (env, ctx, server) { }; } - // try to find exact match + // try to find exact match ctx.store.collection(collection).find(query).toArray(function findResult (err, array) { if (err || array.length > 0) { - console.log(LOG_DEDUP + 'Exact match'); - if (callback) { - callback([array[0]]); - } - return; + console.log(LOG_DEDUP + 'Exact match'); + if (callback) { + callback([array[0]]); + } + return; } - var selected = false; - var query_similiar = { - created_at: {$gte: new Date(new Date(data.data.created_at).getTime() - maxtimediff).toISOString(), $lte: new Date(new Date(data.data.created_at).getTime() + maxtimediff).toISOString()} + var selected = false; + var query_similiar = { + created_at: { $gte: new Date(new Date(data.data.created_at).getTime() - maxtimediff).toISOString(), $lte: new Date(new Date(data.data.created_at).getTime() + maxtimediff).toISOString() } }; if (data.data.insulin) { query_similiar.insulin = data.data.insulin; @@ -306,7 +343,7 @@ function init (env, ctx, server) { query_similiar.percent = data.data.percent; selected = true; } - if (data.data.absolute) { + if (data.data.absolute) { query_similiar.absolute = data.data.absolute; selected = true; } @@ -314,7 +351,7 @@ function init (env, ctx, server) { query_similiar.duration = data.data.duration; selected = true; } - if (data.data.NSCLIENT_ID) { + if (data.data.NSCLIENT_ID) { query_similiar.NSCLIENT_ID = data.data.NSCLIENT_ID; selected = true; } @@ -329,10 +366,7 @@ function init (env, ctx, server) { console.log(LOG_DEDUP + 'Found similiar', array[0]); array[0].created_at = data.data.created_at; var objId = new ObjectID(array[0]._id); - ctx.store.collection(collection).update( - { '_id': objId }, - { $set: {created_at: data.data.created_at} } - ); + ctx.store.collection(collection).update({ '_id': objId }, { $set: { created_at: data.data.created_at } }); if (callback) { callback([array[0]]); } @@ -346,6 +380,13 @@ function init (env, ctx, server) { console.log('treatments data insertion error: ', err.message); return; } + + ctx.bus.emit('data-update', { + type: data.collection + , op: 'update' + , changes: ctx.ddata.processRawDataForRuntime(doc.ops) + }); + if (callback) { callback(doc.ops); } @@ -353,7 +394,7 @@ function init (env, ctx, server) { }); }); }); - // devicestatus deduping + // devicestatus deduping } else if (data.collection === 'devicestatus') { var queryDev; if (data.data.NSCLIENT_ID) { @@ -379,8 +420,15 @@ function init (env, ctx, server) { console.log('devicestatus insertion error: ', err.message); return; } + + ctx.bus.emit('data-update', { + type: 'devicestatus' + , op: 'update' + , changes: ctx.ddata.processRawDataForRuntime(doc.ops) + }); + if (callback) { - callback(doc.ops); + callback(doc.ops); } ctx.bus.emit('data-received'); }); @@ -390,6 +438,13 @@ function init (env, ctx, server) { console.log(data.collection + ' insertion error: ', err.message); return; } + + ctx.bus.emit('data-update', { + type: data.collection + , op: 'update' + , changes: ctx.ddata.processRawDataForRuntime(doc.ops) + }); + if (callback) { callback(doc.ops); } @@ -403,24 +458,34 @@ function init (env, ctx, server) { // _id: 'some mongo record id' // } socket.on('dbRemove', function dbRemove (data, callback) { - console.log(LOG_WS + 'dbRemove client ID: ', socket.client.id, ' data: ', data); - var collection = supportedCollections[data.collection]; + console.log(LOG_WS + 'dbRemove client ID: ', socket.client.id, ' data: ', data); + var collection = supportedCollections[data.collection]; var check = checkConditions('dbUpdate', data); if (check) { - if (callback) { - callback( check ); + if (callback) { + callback(check); } return; } var objId = new ObjectID(data._id); - ctx.store.collection(collection).remove( - { '_id': objId } - ); + ctx.store.collection(collection).remove({ '_id': objId } + , function(err, stat) { + + if (!err) { + ctx.bus.emit('data-update', { + type: data.collection + , op: 'remove' + , count: stat.result.n + , changes: data._id + }); + + } + }); if (callback) { - callback( { result: 'success' } ); + callback({ result: 'success' }); } ctx.bus.emit('data-received'); }); @@ -437,15 +502,9 @@ function init (env, ctx, server) { socketAuthorization = authorization; clientType = message.client; history = message.history || 48; //default history is 48 hours - var from = message.from; if (socketAuthorization.read) { socket.join('DataReceivers'); - var msecHistory = times.hours(history).msecs; - // if `from` is received, it's a reconnection and full data is not needed - if (from && from > 0) { - msecHistory = Math.min(new Date().getTime() - from, msecHistory); - } if (lastData && lastData.dataWithRecentStatuses) { let data = lastData.dataWithRecentStatuses(); @@ -457,7 +516,7 @@ function init (env, ctx, server) { socket.emit('dataUpdate', data); } } - console.log(LOG_WS + 'Authetication ID: ', socket.client.id, ' client: ', clientType, ' history: ' + history); + // console.log(LOG_WS + 'Authetication ID: ', socket.client.id, ' client: ', clientType, ' history: ' + history); if (callback) { callback(socketAuthorization); } @@ -471,7 +530,7 @@ function init (env, ctx, server) { socket.on('nsping', function ping (message, callback) { var clientTime = message.mills; timeDiff = new Date().getTime() - clientTime; - console.log(LOG_WS + 'Ping from client ID: ',socket.client.id, ' client: ', clientType, ' timeDiff: ', (timeDiff/1000).toFixed(1) + 'sec'); + // console.log(LOG_WS + 'Ping from client ID: ',socket.client.id, ' client: ', clientType, ' timeDiff: ', (timeDiff/1000).toFixed(1) + 'sec'); if (callback) { callback({ result: 'pong', mills: new Date().getTime(), authorization: socketAuthorization }); } @@ -479,15 +538,15 @@ function init (env, ctx, server) { }); } - websocket.update = function update ( ) { - console.log(LOG_WS + 'running websocket.update'); + websocket.update = function update () { + // console.log(LOG_WS + 'running websocket.update'); if (lastData.sgvs) { var delta = calcData(lastData, ctx.ddata); if (delta.delta) { - console.log('lastData full size', JSON.stringify(lastData).length,'bytes'); - if (delta.sgvs) { console.log('patientData update size', JSON.stringify(delta).length,'bytes'); } + // console.log('lastData full size', JSON.stringify(lastData).length,'bytes'); + // if (delta.sgvs) { console.log('patientData update size', JSON.stringify(delta).length,'bytes'); } emitData(delta); - } else { console.log('delta calculation indicates no new data is present'); } + }; // else { console.log('delta calculation indicates no new data is present'); } } lastData = ctx.ddata.clone(); }; @@ -511,8 +570,8 @@ function init (env, ctx, server) { } }; - start( ); - listeners( ); + start(); + listeners(); if (ctx.storageSocket) { ctx.storageSocket.init(io); diff --git a/lib/settings.js b/lib/settings.js index c2497ed66d5..98a53b93a83 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -31,7 +31,7 @@ function init () { , alarmPumpBatteryLow: false , language: 'en' , scaleY: 'log' - , showPlugins: '' + , showPlugins: 'dbsize' , showForecast: 'ar2' , focusHours: 3 , heartbeat: 60 @@ -51,8 +51,33 @@ function init () { , deNormalizeDates: false , showClockDelta: false , showClockLastTime: false + , bolusRenderOver: 1 + , frameUrl1: '' + , frameUrl2: '' + , frameUrl3: '' + , frameUrl4: '' + , frameUrl5: '' + , frameUrl6: '' + , frameUrl7: '' + , frameUrl8: '' + , frameName1: '' + , frameName2: '' + , frameName3: '' + , frameName4: '' + , frameName5: '' + , frameName6: '' + , frameName7: '' + , frameName8: '' }; + var secureSettings = [ + 'apnsKey' + , 'apnsKeyId' + , 'developerTeamId' + , 'userName' + , 'password' + ]; + var valueMappers = { nightMode: mapTruthy , alarmUrgentHigh: mapTruthy @@ -80,6 +105,29 @@ function init () { , bgTargetBottom: mapNumber }; + function filterObj(obj, secureKeys) { + if (obj && typeof obj === 'object') { + var allKeys = Object.keys(obj); + for (var i = 0 ; i < allKeys.length ; i++) { + var k = allKeys[i]; + if (secureKeys.includes(k)) { + delete obj[k]; + } else { + var value = obj[k]; + if ( typeof value === 'object') { + filterObj(value, secureKeys); + } + } + } + } + return obj; + } + + function filteredSettings(settingsObject) { + let so = _.cloneDeep(settingsObject); + return filterObj(so, secureSettings); + } + function mapNumberArray (value) { if (!value || _.isArray(value)) { return value; @@ -119,7 +167,7 @@ function init () { } //TODO: getting sent in status.json, shouldn't be - settings.DEFAULT_FEATURES = ['bgnow', 'delta', 'direction', 'timeago', 'devicestatus', 'upbat', 'errorcodes', 'profile']; + settings.DEFAULT_FEATURES = ['bgnow', 'delta', 'direction', 'timeago', 'devicestatus', 'upbat', 'errorcodes', 'profile', 'dbsize', 'runtimestate', 'basal', 'careportal']; var wasSet = []; @@ -158,7 +206,9 @@ function init () { function getAndPrepare (key) { var raw = accessor(nameFromKey(key, nameType)) || ''; var cleaned = decodeURIComponent(raw).toLowerCase(); - return cleaned ? cleaned.split(' ') : []; + cleaned = cleaned ? cleaned.split(' ') : []; + cleaned = _.filter(cleaned, function(e) { return e !== ""; } ); + return cleaned; } function enableIf (feature, condition) { @@ -290,34 +340,40 @@ function init () { return enabled; } - function isAlarmEventEnabled (notify) { - var enabled = false; + function isUrgentHighAlarmEnabled(notify) { + return notify.eventName === 'high' && notify.level === levels.URGENT && settings.alarmUrgentHigh; + } - if ('high' !== notify.eventName && 'low' !== notify.eventName) { - enabled = true; - } else if (notify.eventName === 'high' && notify.level === levels.URGENT && settings.alarmUrgentHigh) { - enabled = true; - } else if (notify.eventName === 'high' && settings.alarmHigh) { - enabled = true; - } else if (notify.eventName === 'low' && notify.level === levels.URGENT && settings.alarmUrgentLow) { - enabled = true; - } else if (notify.eventName === 'low' && settings.alarmLow) { - enabled = true; - } + function isHighAlarmEnabled(notify) { + return notify.eventName === 'high' && settings.alarmHigh; + } - return enabled; + function isUrgentLowAlarmEnabled(notify) { + return notify.eventName === 'low' && notify.level === levels.URGENT && settings.alarmUrgentLow; + } + + function isLowAlarmEnabled(notify) { + return notify.eventName === 'low' && settings.alarmLow; + } + + function isAlarmEventEnabled (notify) { + return ('high' !== notify.eventName && 'low' !== notify.eventName) + || isUrgentHighAlarmEnabled(notify) + || isHighAlarmEnabled(notify) + || isUrgentLowAlarmEnabled(notify) + || isLowAlarmEnabled(notify); } function snoozeMinsForAlarmEvent (notify) { var snoozeTime; - if (notify.eventName === 'high' && notify.level === levels.URGENT && settings.alarmUrgentHigh) { + if (isUrgentHighAlarmEnabled(notify)) { snoozeTime = settings.alarmUrgentHighMins; - } else if (notify.eventName === 'high' && settings.alarmHigh) { + } else if (isHighAlarmEnabled(notify)) { snoozeTime = settings.alarmHighMins; - } else if (notify.eventName === 'low' && notify.level === levels.URGENT && settings.alarmUrgentLow) { + } else if (isUrgentLowAlarmEnabled(notify)) { snoozeTime = settings.alarmUrgentLowMins; - } else if (notify.eventName === 'low' && settings.alarmLow) { + } else if (isLowAlarmEnabled(notify)) { snoozeTime = settings.alarmLowMins; } else if (notify.level === levels.URGENT) { snoozeTime = settings.alarmUrgentMins; @@ -338,6 +394,7 @@ function init () { settings.isAlarmEventEnabled = isAlarmEventEnabled; settings.snoozeMinsForAlarmEvent = snoozeMinsForAlarmEvent; settings.snoozeFirstMinsForAlarmEvent = snoozeFirstMinsForAlarmEvent; + settings.filteredSettings = filteredSettings; return settings; diff --git a/lib/storage/mongo-storage.js b/lib/storage/mongo-storage.js index 275cde6eb8a..8c2533873c7 100644 --- a/lib/storage/mongo-storage.js +++ b/lib/storage/mongo-storage.js @@ -1,12 +1,11 @@ 'use strict'; var mongodb = require('mongodb'); - var connection = null; +var MongoClient = mongodb.MongoClient; +var mongo = {}; function init (env, cb, forceNewConnection) { - var MongoClient = mongodb.MongoClient; - var mongo = {}; function maybe_connect (cb) { @@ -20,42 +19,69 @@ function init (env, cb, forceNewConnection) { } } else { if (!env.storageURI) { - throw new Error('MongoDB connection string is missing. Please set MONGO_CONNECTION environment variable'); + throw new Error('MongoDB connection string is missing. Please set MONGODB_URI environment variable'); } console.log('Setting up new connection to MongoDB'); - var timeout = 30 * 1000; - var options = { reconnectInterval: 10000, reconnectTries: 500, connectTimeoutMS: timeout, - socketTimeoutMS: timeout, useNewUrlParser: true }; + var timeout = 30 * 1000; + var options = { + reconnectInterval: 10000 + , reconnectTries: 500 + , connectTimeoutMS: timeout + , socketTimeoutMS: timeout + , useNewUrlParser: true + }; var connect_with_retry = function(i) { - return MongoClient.connect(env.storageURI, options, function connected(err, client) { - if (err) { - //console.log('err=', err) - if (err.name && err.name === "MongoNetworkError") { - var timeout = (i > 15) ? 60000 : i*3000; - console.log('Error connecting to MongoDB: %j - retrying in ' + timeout/1000 + ' sec', err); - setTimeout(connect_with_retry, timeout, i+1); - } else if (err.message) { - throw new Error('MongoDB connection string '+env.storageURI+' seems invalid: '+err.message) ; - } - } else { + + MongoClient.connect(env.storageURI, options) + .then(client => { console.log('Successfully established a connected to MongoDB'); - + var dbName = env.storageURI.split('/').pop().split('?'); - dbName=dbName[0]; // drop Connection Options + dbName = dbName[0]; // drop Connection Options mongo.db = client.db(dbName); connection = mongo.db; mongo.client = client; - // If there is a valid callback, then invoke the function to perform the callback - if (cb && cb.call) { - cb(err, mongo); + mongo.db.command({ connectionStatus: 1 }).then( + result => { + const roles = result.authInfo.authenticatedUserRoles; + if (roles.length > 0 && roles[0].role == 'readAnyDatabase') { + console.error('Mongo user is read only'); + cb(new Error('MongoDB connection is in read only mode! Go back to MongoDB configuration and check your database user has read and write access.'), null); + } + + console.log('Mongo user role seems ok:', roles); + + // If there is a valid callback, then invoke the function to perform the callback + if (cb && cb.call) { + cb(null, mongo); + } + } + ); + }) + .catch(err => { + if (err.message && err.message.includes('AuthenticationFailed')) { + console.log('Authentication to Mongo failed'); + cb(new Error('MongoDB authentication failed! Double check the URL has the right username and password in MONGODB_URI.'), null); + return; + } + + if (err.name && err.name === "MongoNetworkError") { + var timeout = (i > 15) ? 60000 : i * 3000; + console.log('Error connecting to MongoDB: %j - retrying in ' + timeout / 1000 + ' sec', err); + setTimeout(connect_with_retry, timeout, i + 1); + if (i == 1) cb(new Error('MongoDB connection failed! Double check the MONGODB_URI setting in Heroku.'), null); + } else { + cb(new Error('MONGODB_URI ' + env.storageURI + ' seems invalid: ' + err.message)); } - } - }); + }); + }; - connect_with_retry(1); + + return connect_with_retry(1); + } } @@ -64,9 +90,9 @@ function init (env, cb, forceNewConnection) { }; mongo.ensureIndexes = function ensureIndexes (collection, fields) { - fields.forEach(function (field) { + fields.forEach(function(field) { console.info('ensuring index for: ' + field); - collection.ensureIndex(field, function (err) { + collection.createIndex(field, { 'background': true }, function(err) { if (err) { console.error('unable to ensureIndex for: ' + field + ' - ' + err); } diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 7d3a1730a7d..a137dcd1533 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,104 +1,63 @@ { "name": "nightscout", - "version": "13.0.1", + "version": "14.0.7", "lockfileVersion": 1, "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz", + "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==", "requires": { - "@babel/highlight": "^7.0.0" + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "semver": "^5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } } }, "@babel/core": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.6.2.tgz", - "integrity": "sha512-l8zto/fuoZIbncm+01p8zPSDZu/VuuJhAfA7d/AbzM09WR7iVhavvfNDYCNpo1VvLk6E6xgAoP9P+/EMJHuRkQ==", - "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.6.2", - "@babel/helpers": "^7.6.2", - "@babel/parser": "^7.6.2", - "@babel/template": "^7.6.0", - "@babel/traverse": "^7.6.2", - "@babel/types": "^7.6.0", - "convert-source-map": "^1.1.0", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz", + "integrity": "sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.4", + "@babel/helper-module-transforms": "^7.11.0", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.11.4", + "@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", - "json5": "^2.1.0", - "lodash": "^4.17.13", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" }, "dependencies": { - "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/generator": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.2.tgz", - "integrity": "sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ==", - "requires": { - "@babel/types": "^7.6.0", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/parser": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.2.tgz", - "integrity": "sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==" - }, - "@babel/template": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", - "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.6.0", - "@babel/types": "^7.6.0" - } - }, - "@babel/traverse": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.2.tgz", - "integrity": "sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==", - "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.6.2", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.6.2", - "@babel/types": "^7.6.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" + "safe-buffer": "~5.1.1" } }, "debug": { @@ -109,24 +68,19 @@ "ms": "^2.1.1" } }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" - }, - "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", - "requires": { - "minimist": "^1.2.0" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "requires": { + "path-parse": "^1.0.6" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -140,22 +94,15 @@ } }, "@babel/generator": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.0.tgz", - "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", + "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", "requires": { - "@babel/types": "^7.4.0", + "@babel/types": "^7.11.0", "jsesc": "^2.5.1", - "lodash": "^4.17.11", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" + "source-map": "^0.5.0" }, "dependencies": { - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -164,1140 +111,821 @@ } }, "@babel/helper-annotate-as-pure": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", + "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.10.4" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" } }, - "@babel/helper-call-delegate": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", - "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", + "@babel/helper-compilation-targets": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", + "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" + "@babel/compat-data": "^7.10.4", + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "levenary": "^1.1.1", + "semver": "^5.5.0" }, "dependencies": { - "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/generator": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.2.tgz", - "integrity": "sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ==", - "requires": { - "@babel/types": "^7.6.0", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/parser": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.2.tgz", - "integrity": "sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==" - }, - "@babel/traverse": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.2.tgz", - "integrity": "sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==", - "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.6.2", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.6.2", - "@babel/types": "^7.6.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, + "@babel/helper-create-class-features-plugin": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", + "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", + "requires": { + "@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": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", + "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-regex": "^7.10.4", + "regexpu-core": "^4.7.0" + } + }, "@babel/helper-define-map": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", - "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.5.5", - "lodash": "^4.17.13" - }, - "dependencies": { - "@babel/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" } }, "@babel/helper-explode-assignable-expression": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz", + "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==", "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/types": "^7.10.4" } }, "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.10.4" } }, "@babel/helper-hoist-variables": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", - "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", "requires": { - "@babel/types": "^7.4.4" - }, - "dependencies": { - "@babel/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.10.4" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", - "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", "requires": { - "@babel/types": "^7.5.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.11.0" } }, "@babel/helper-module-imports": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.10.4" } }, "@babel/helper-module-transforms": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", - "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/template": "^7.4.4", - "@babel/types": "^7.5.5", - "lodash": "^4.17.13" - }, - "dependencies": { - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/parser": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.2.tgz", - "integrity": "sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==" - }, - "@babel/template": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", - "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.6.0", - "@babel/types": "^7.6.0" - } - }, - "@babel/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } + "@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": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "^7.10.4" } }, "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==" + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" }, "@babel/helper-regex": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", - "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", "requires": { - "lodash": "^4.17.13" + "lodash": "^4.17.19" } }, "@babel/helper-remap-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz", + "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==", "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-replace-supers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", - "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", "requires": { - "@babel/helper-member-expression-to-functions": "^7.5.5", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/generator": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.2.tgz", - "integrity": "sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ==", - "requires": { - "@babel/types": "^7.6.0", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/parser": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.2.tgz", - "integrity": "sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==" - }, - "@babel/traverse": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.2.tgz", - "integrity": "sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==", - "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.6.2", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.6.2", - "@babel/types": "^7.6.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } + "@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": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", + "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", + "requires": { + "@babel/types": "^7.11.0" } }, "@babel/helper-split-export-declaration": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.0.tgz", - "integrity": "sha512-7Cuc6JZiYShaZnybDmfwhY4UYHzI6rlqhWjaIqbsJGsIqPimEYy5uh3akSRLMg65LSdSEnJ8a8/bWQN6u2oMGw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", "requires": { - "@babel/types": "^7.4.0" + "@babel/types": "^7.11.0" } }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" + }, "@babel/helper-wrap-function": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", - "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", + "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.2.0" + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helpers": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.2.tgz", - "integrity": "sha512-3/bAUL8zZxYs1cdX2ilEE0WobqbCmKWr/889lf2SS0PpDcpEIY8pb1CCyz0pEcX3pEb+MCbks1jIokz2xLtGTA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", "requires": { - "@babel/template": "^7.6.0", - "@babel/traverse": "^7.6.2", - "@babel/types": "^7.6.0" - }, - "dependencies": { - "@babel/generator": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.2.tgz", - "integrity": "sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ==", - "requires": { - "@babel/types": "^7.6.0", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/parser": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.2.tgz", - "integrity": "sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==" - }, - "@babel/template": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", - "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.6.0", - "@babel/types": "^7.6.0" - } - }, - "@babel/traverse": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.2.tgz", - "integrity": "sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==", - "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.6.2", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.6.2", - "@babel/types": "^7.6.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "requires": { - "@babel/highlight": "^7.0.0" - } - } - } - }, - "@babel/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "requires": { + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } } }, "@babel/parser": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.3.tgz", - "integrity": "sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==" + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", + "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==" }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", - "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", + "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.2.0" + "@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": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", - "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", + "@babel/plugin-proposal-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz", + "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0" + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, - "@babel/plugin-proposal-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", - "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", + "@babel/plugin-proposal-dynamic-import": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", + "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" } }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz", - "integrity": "sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==", + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz", + "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", + "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz", + "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", + "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", + "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz", + "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.10.4" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", + "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", + "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", + "requires": { + "@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-private-methods": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz", + "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz", - "integrity": "sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", + "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.6.0" - }, - "dependencies": { - "regexpu-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", - "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", - "requires": { - "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" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==" - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "requires": { - "jsesc": "~0.5.0" - } - } + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-async-generators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", - "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", + "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-dynamic-import": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", - "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-syntax-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", - "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-object-rest-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", - "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", + "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", - "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", + "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", - "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", + "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" + "@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": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", - "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", + "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.2.tgz", - "integrity": "sha512-zZT8ivau9LOQQaOGC7bQLQOT4XPkPXgN2ERfUgk1X8ql+mVkLc4E8eKk+FO3o0154kxzqenWCorfmEXpEZcrSQ==", + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz", + "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.13" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-classes": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", - "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.5.5", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5", - "@babel/helper-split-export-declaration": "^7.4.4", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", + "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", + "requires": { + "@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" - }, - "dependencies": { - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/plugin-transform-computed-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", - "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", + "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-destructuring": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz", - "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", + "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz", - "integrity": "sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", + "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.6.0" - }, - "dependencies": { - "regexpu-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", - "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", - "requires": { - "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" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==" - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "requires": { - "jsesc": "~0.5.0" - } - } + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", - "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", + "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", - "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", + "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-for-of": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", - "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", + "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-function-name": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", - "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", + "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", - "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", + "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", - "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", + "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", - "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", + "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@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": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz", - "integrity": "sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", + "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", "requires": { - "@babel/helper-module-transforms": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@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": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", - "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", + "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/helper-plugin-utils": "^7.0.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@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": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", - "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", + "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.2.tgz", - "integrity": "sha512-xBdB+XOs+lgbZc2/4F5BVDVcDNS4tcSKQc96KmlqLEAwz6tpYPEvPdmDfvVG0Ssn8lAhronaRs6Z6KSexIpK5g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", + "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", "requires": { - "regexpu-core": "^4.6.0" - }, - "dependencies": { - "regexpu-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", - "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", - "requires": { - "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" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==" - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "requires": { - "jsesc": "~0.5.0" - } - } + "@babel/helper-create-regexp-features-plugin": "^7.10.4" } }, "@babel/plugin-transform-new-target": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", - "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", + "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-object-super": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", - "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", + "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4" } }, "@babel/plugin-transform-parameters": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", - "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", + "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", "requires": { - "@babel/helper-call-delegate": "^7.4.4", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-property-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", - "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", + "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-regenerator": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", - "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", + "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", "requires": { - "regenerator-transform": "^0.14.0" + "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", - "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", + "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", - "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", + "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-spread": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz", - "integrity": "sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", + "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", - "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", + "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" } }, "@babel/plugin-transform-template-literals": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", - "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", + "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", - "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", + "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz", + "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz", - "integrity": "sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", + "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.6.0" - }, - "dependencies": { - "regexpu-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", - "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", - "requires": { - "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" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==" - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "requires": { - "jsesc": "~0.5.0" - } - } + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/preset-env": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.6.2.tgz", - "integrity": "sha512-Ru7+mfzy9M1/YTEtlDS8CD45jd22ngb9tXnn64DvQK3ooyqSw9K4K9DUWmYknTTVk4TqygL9dqCrZgm1HMea/Q==", - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-dynamic-import": "^7.5.0", - "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.6.2", - "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.6.2", - "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0", - "@babel/plugin-syntax-json-strings": "^7.2.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", - "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.5.0", - "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.6.2", - "@babel/plugin-transform-classes": "^7.5.5", - "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.6.0", - "@babel/plugin-transform-dotall-regex": "^7.6.2", - "@babel/plugin-transform-duplicate-keys": "^7.5.0", - "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.4", - "@babel/plugin-transform-function-name": "^7.4.4", - "@babel/plugin-transform-literals": "^7.2.0", - "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.5.0", - "@babel/plugin-transform-modules-commonjs": "^7.6.0", - "@babel/plugin-transform-modules-systemjs": "^7.5.0", - "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.6.2", - "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.5.5", - "@babel/plugin-transform-parameters": "^7.4.4", - "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.5", - "@babel/plugin-transform-reserved-words": "^7.2.0", - "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.6.2", - "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.4.4", - "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.6.2", - "@babel/types": "^7.6.0", - "browserslist": "^4.6.0", - "core-js-compat": "^3.1.1", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.0.tgz", + "integrity": "sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg==", + "requires": { + "@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.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.11.0", + "browserslist": "^4.12.0", + "core-js-compat": "^3.6.2", "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", + "levenary": "^1.1.1", "semver": "^5.5.0" }, "dependencies": { - "@babel/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -1305,30 +933,50 @@ } } }, + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "requires": { + "@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/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, "@babel/template": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.0.tgz", - "integrity": "sha512-SOWwxxClTTh5NdbbYZ0BmaBVzxzTh2tO/TeLTbF6MO6EzVhHTnff8CdBXx3mEtazFBoysmEM6GU/wF+SuSx4Fw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.0", - "@babel/types": "^7.4.0" + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/traverse": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.3.tgz", - "integrity": "sha512-HmA01qrtaCwwJWpSKpA948cBvU5BrmviAief/b3AVw936DtcdsTexlbyzNuDnthwhOQ37xshn7hvQaEQk7ISYQ==", - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/types": "^7.4.0", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", + "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "requires": { + "@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.11" + "lodash": "^4.17.19" }, "dependencies": { "debug": { @@ -1340,177 +988,187 @@ } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" } } }, "@babel/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", - "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", + "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" } }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", + "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==" + }, "@webassemblyjs/ast": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", - "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", "requires": { - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5" + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", - "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==" }, "@webassemblyjs/helper-api-error": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", - "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==" }, "@webassemblyjs/helper-buffer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", - "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==" }, "@webassemblyjs/helper-code-frame": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", - "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", "requires": { - "@webassemblyjs/wast-printer": "1.8.5" + "@webassemblyjs/wast-printer": "1.9.0" } }, "@webassemblyjs/helper-fsm": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", - "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==" }, "@webassemblyjs/helper-module-context": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", - "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", "requires": { - "@webassemblyjs/ast": "1.8.5", - "mamacro": "^0.0.3" + "@webassemblyjs/ast": "1.9.0" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", - "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" }, "@webassemblyjs/helper-wasm-section": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", - "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" } }, "@webassemblyjs/ieee754": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", - "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", - "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", - "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==" }, "@webassemblyjs/wasm-edit": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", - "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/helper-wasm-section": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-opt": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "@webassemblyjs/wast-printer": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" } }, "@webassemblyjs/wasm-gen": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", - "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" } }, "@webassemblyjs/wasm-opt": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", - "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" } }, "@webassemblyjs/wasm-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", - "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" } }, "@webassemblyjs/wast-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", - "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/floating-point-hex-parser": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-code-frame": "1.8.5", - "@webassemblyjs/helper-fsm": "1.8.5", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/wast-printer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", - "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5", + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", "@xtuc/long": "4.2.2" } }, @@ -1536,45 +1194,45 @@ "dev": true }, "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" + "mime-types": "~2.1.24", + "negotiator": "0.6.2" } }, "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==" }, "acorn-globals": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz", - "integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", "requires": { "acorn": "^6.0.1", "acorn-walk": "^6.0.1" }, "dependencies": { "acorn": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==" + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" } } }, "acorn-jsx": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.2.tgz", - "integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", "dev": true }, "acorn-walk": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", - "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==" }, "after": { "version": "0.8.2", @@ -1582,11 +1240,11 @@ "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" }, "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "version": "6.12.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", + "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" @@ -1598,16 +1256,9 @@ "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" }, "ajv-keywords": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", - "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==" - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" }, "ansi-align": { "version": "2.0.0", @@ -1624,12 +1275,6 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -1652,18 +1297,26 @@ } }, "ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, "ansi-escapes": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz", - "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", "dev": true, "requires": { - "type-fest": "^0.5.2" + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } } }, "ansi-html": { @@ -1678,27 +1331,20 @@ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } }, "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, "apn": { @@ -1787,6 +1433,18 @@ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, + "array.prototype.map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", + "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.4" + } + }, "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", @@ -1801,13 +1459,21 @@ } }, "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } } }, "assert": { @@ -1861,9 +1527,9 @@ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" }, "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, "asynckit": { "version": "0.4.0", @@ -1881,9 +1547,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==" }, "babel-code-frame": { "version": "6.26.0", @@ -1893,84 +1559,78 @@ "chalk": "^1.1.3", "esutils": "^2.0.2", "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } } }, "babel-eslint": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz", - "integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", "eslint-visitor-keys": "^1.0.0", "resolve": "^1.12.0" - } - }, - "babel-loader": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", - "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", - "requires": { - "find-cache-dir": "^2.0.0", - "loader-utils": "^1.0.2", - "mkdirp": "^0.5.1", - "pify": "^4.0.1" }, "dependencies": { - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "path-parse": "^1.0.6" } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "requires": { - "find-up": "^3.0.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, + "babel-loader": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", + "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", + "requires": { + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" + } + }, "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", "requires": { "object.assign": "^4.1.0" } @@ -1999,6 +1659,11 @@ "pascalcase": "^0.1.1" }, "dependencies": { + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", @@ -2040,11 +1705,6 @@ "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" - }, "base64id": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", @@ -2099,9 +1759,27 @@ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" }, "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } }, "blob": { "version": "0.0.5", @@ -2109,14 +1787,14 @@ "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" }, "bluebird": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", - "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==" + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" }, "body-parser": { "version": "1.19.0", @@ -2133,18 +1811,6 @@ "qs": "6.7.0", "raw-body": "2.4.0", "type-is": "~1.6.17" - }, - "dependencies": { - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - } } }, "bootevent": { @@ -2155,11 +1821,6 @@ "chainsaw": "~0.1.0" } }, - "bowser": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.7.0.tgz", - "integrity": "sha512-aIlMvstvu8x+34KEiOHD3AsBgdrzg6sxALYiukOWhFvGMbQI6TRP/iY0LMhUrHs56aD6P1G0Z7h45PUJaa5m9w==" - }, "boxen": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", @@ -2181,30 +1842,10 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "string-width": { @@ -2225,15 +1866,6 @@ "requires": { "ansi-regex": "^3.0.0" } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, @@ -2260,9 +1892,9 @@ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, "browser-process-hrtime": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", - "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" }, "browser-stdout": { "version": "1.3.1", @@ -2311,20 +1943,51 @@ "requires": { "bn.js": "^4.1.0", "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } } }, "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "requires": { - "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.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } } }, "browserify-zlib": { @@ -2336,30 +1999,36 @@ } }, "browserslist": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.0.tgz", - "integrity": "sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz", + "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==", "requires": { - "caniuse-lite": "^1.0.30000989", - "electron-to-chromium": "^1.3.247", - "node-releases": "^1.1.29" + "caniuse-lite": "^1.0.30001111", + "electron-to-chromium": "^1.3.523", + "escalade": "^3.0.2", + "node-releases": "^1.1.60" } }, "bson": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.1.tgz", - "integrity": "sha512-jCGVYLoYMHDkOsbwJZBCqwMHyH4c+wzgI9hG7Z6SZJRXWr+x58pdIbm2i9a/jFGCkRJqRUr8eoI7lDWa0hTkxg==" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz", + "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==" }, "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", "requires": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" }, "dependencies": { + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -2388,14 +2057,14 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, "cacache": { - "version": "12.0.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", - "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", "requires": { "bluebird": "^3.5.5", "chownr": "^1.1.1", @@ -2414,19 +2083,6 @@ "y18n": "^4.0.0" }, "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -2434,11 +2090,6 @@ "requires": { "yallist": "^3.0.2" } - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" } } }, @@ -2456,6 +2107,13 @@ "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" + }, + "dependencies": { + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + } } }, "caching-transform": { @@ -2468,30 +2126,6 @@ "make-dir": "^2.0.0", "package-hash": "^3.0.0", "write-file-atomic": "^2.4.2" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } } }, "callsite": { @@ -2506,20 +2140,14 @@ "dev": true }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "camelize": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", - "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "caniuse-lite": { - "version": "1.0.30000999", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000999.tgz", - "integrity": "sha512-1CUyKyecPeksKwXZvYw0tEoaMCo/RwBlXmEtN5vVnabvO0KPd9RQLcaAuR9/1F+KDMv6esmOFWlsXuzDk+8rxg==" + "version": "1.0.30001119", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001119.tgz", + "integrity": "sha512-Hpwa4obv7EGP+TjkCh/wVvbtNJewxmtg4yVJBLFnxo35vbPapBr138bUWENkb5j5L9JZJ9RXLn4OrXRG/cecPQ==" }, "capture-stack-trace": { "version": "1.0.1", @@ -2548,15 +2176,28 @@ } }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } } }, "chardet": { @@ -2577,110 +2218,24 @@ "dev": true }, "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" } }, "chownr": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", - "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "chrome-trace-event": { "version": "1.0.2", @@ -2727,13 +2282,20 @@ } }, "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", "requires": { "source-map": "~0.6.0" - } - }, + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, "cli-boxes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", @@ -2750,9 +2312,9 @@ } }, "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true }, "cliui": { @@ -2770,26 +2332,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -2805,6 +2347,23 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, + "codacy-coverage": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/codacy-coverage/-/codacy-coverage-3.4.0.tgz", + "integrity": "sha512-A0ats3/gZtOw76muu++HZ6QrInztWjjLefkLJmmBpjPfyn6nNwNLoApmGmj3F3dfgl2+o6u5GwPnUBkKdfKXTQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.x", + "commander": "^2.x", + "jacoco-parse": "^2.x", + "joi": "^13.x", + "lcov-parse": "^1.x", + "lodash": "^4.17.4", + "log-driver": "^1.x", + "request": "^2.88.0", + "request-promise": "^4.x" + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -2828,22 +2387,18 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "requires": { "delayed-stream": "~1.0.0" } }, "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "component-bind": { "version": "1.0.0", @@ -2851,9 +2406,10 @@ "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" }, "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true }, "component-inherit": { "version": "0.0.3", @@ -2861,11 +2417,11 @@ "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" }, "compressible": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.16.tgz", - "integrity": "sha512-JQfEOdnI7dASwCuSPWIeVYwc/zMsu/+tRhoUvEfXz2gxOA2DNjmG5vhtFdBlhWPPGo+RdT9S3tgc/uH5qgDiiA==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "requires": { - "mime-db": ">= 1.38.0 < 2" + "mime-db": ">= 1.43.0 < 2" } }, "compression": { @@ -2880,6 +2436,13 @@ "on-headers": "~1.0.2", "safe-buffer": "5.1.2", "vary": "~1.1.2" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + } } }, "concat-map": { @@ -2887,44 +2450,37 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, "configstore": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", - "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.5.tgz", + "integrity": "sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==", "dev": true, "requires": { - "dot-prop": "^4.1.0", + "dot-prop": "^4.2.1", "graceful-fs": "^4.1.2", "make-dir": "^1.0.0", "unique-string": "^1.0.0", "write-file-atomic": "^2.0.0", "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "requires": { - "date-now": "^0.1.4" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" - }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -2933,28 +2489,15 @@ "safe-buffer": "5.1.2" } }, - "content-security-policy-builder": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.1.0.tgz", - "integrity": "sha512-/MtLWhJVvJNkA9dVLAp6fg9LxD2gfI6R2Fi1hPmfjYXSahJJzcfvoeDOxSyp4NvxMuwWv3WMssE9o31DoULHrQ==" - }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "requires": { - "safe-buffer": "~5.1.1" - } - }, "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" }, "cookie-signature": { "version": "1.0.6", @@ -2986,12 +2529,19 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "core-js-compat": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.2.1.tgz", - "integrity": "sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A==", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", + "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", "requires": { - "browserslist": "^4.6.6", - "semver": "^6.3.0" + "browserslist": "^4.8.5", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + } } }, "core-util-is": { @@ -3010,39 +2560,22 @@ "nested-error-stacks": "^2.0.0", "pify": "^4.0.1", "safe-buffer": "^5.0.1" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } } }, "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", "requires": { "bn.js": "^4.1.0", - "elliptic": "^6.0.0" + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } } }, "create-error-class": { @@ -3092,9 +2625,9 @@ }, "dependencies": { "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -3103,24 +2636,6 @@ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, "crypto-random-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", @@ -3147,19 +2662,18 @@ } }, "css-selector-tokenizer": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", - "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", + "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", "requires": { - "cssesc": "^0.1.0", - "fastparse": "^1.1.1", - "regexpu-core": "^1.0.0" + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" } }, "cssesc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", - "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" }, "cssmin": { "version": "0.4.3", @@ -3167,9 +2681,9 @@ "integrity": "sha1-yRlAd+Dr2s1pHV9ZAVudgZ840BU=" }, "cssom": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", - "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==" + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" }, "cssstyle": { "version": "0.3.1", @@ -3179,15 +2693,26 @@ "cssom": "0.3.x" } }, + "csv-parse": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.12.0.tgz", + "integrity": "sha512-wPQl3H79vWLPI8cgKFcQXl0NBgYYEqVnT1i6/So7OjMpsI540oD7p93r3w6fDSyPvwkTepG05F69/7AViX2lXg==", + "dev": true + }, + "csv-stringify": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.5.1.tgz", + "integrity": "sha512-HM0/86Ks8OwFbaYLd495tqTs1NhscZL52dC4ieKYumy8+nawQYC0xZ63w1NqLf0M148T2YLYqowoImc1giPn0g==" + }, "cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" }, "d3": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-5.12.0.tgz", - "integrity": "sha512-flYVMoVuhPFHd9zVCe2BxIszUWqBcd5fvQGMNRmSiBrgdnh6Vlruh60RJQTouAK9xPbOB0plxMvBm4MoyODXNg==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz", + "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", "requires": { "d3-array": "1", "d3-axis": "1", @@ -3233,9 +2758,9 @@ "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==" }, "d3-brush": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.3.tgz", - "integrity": "sha512-v8bbYyCFKjyCzFk/tdWqXwDykY8YWqhXYjcYxfILIit085VZOpj4XJKOMccTsvWxgzSLMJQg5SiqHjslsipEDg==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", + "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", "requires": { "d3-dispatch": "1", "d3-drag": "1", @@ -3259,9 +2784,9 @@ "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" }, "d3-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.0.tgz", - "integrity": "sha512-TzNPeJy2+iEepfiL92LAAB7fvnp/dV2YwANPVHdDWmYMm23qIJBYww3qT8I8C1wXrmrg4UWs7BKc2tKIgyjzHg==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" }, "d3-contour": { "version": "1.3.2", @@ -3272,23 +2797,23 @@ } }, "d3-dispatch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.5.tgz", - "integrity": "sha512-vwKx+lAqB1UuCeklr6Jh1bvC4SZgbSqbkGBLClItFBIYH4vqDJCA7qfoy14lXmJdnBOdxndAMxjCbImJYW7e6g==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", + "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==" }, "d3-drag": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.4.tgz", - "integrity": "sha512-ICPurDETFAelF1CTHdIyiUM4PsyZLaM+7oIBhmyP+cuVjze5vDZ8V//LdOFjg0jGnFIZD/Sfmk0r95PSiu78rw==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", + "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", "requires": { "d3-dispatch": "1", "d3-selection": "1" } }, "d3-dsv": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.1.1.tgz", - "integrity": "sha512-1EH1oRGSkeDUlDRbhsFytAXU6cAmXFzc52YUe6MRlPClmWb85MP1J5x+YJRzya4ynZWnbELdSAvATFW/MbxaXw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", + "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", "requires": { "commander": "2", "iconv-lite": "0.4", @@ -3296,14 +2821,14 @@ } }, "d3-ease": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.5.tgz", - "integrity": "sha512-Ct1O//ly5y5lFM9YTdu+ygq7LleSgSE4oj7vUt9tPLHUi8VCV7QoizGpdWRWAwCO9LdYzIrQDg97+hGVdsSGPQ==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", + "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==" }, "d3-fetch": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.1.2.tgz", - "integrity": "sha512-S2loaQCV/ZeyTyIF2oP8D1K9Z4QizUzW7cWeAOAS4U88qOt3Ucf6GsmgthuYSdyB2HyEm4CeGvkQxWsmInsIVA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", + "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", "requires": { "d3-dsv": "1" } @@ -3320,45 +2845,45 @@ } }, "d3-format": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.1.tgz", - "integrity": "sha512-TUswGe6hfguUX1CtKxyG2nymO+1lyThbkS1ifLX0Sr+dOQtAD5gkrffpHnx+yHNKUZ0Bmg5T4AjUQwugPDrm0g==" + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", + "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==" }, "d3-geo": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.11.6.tgz", - "integrity": "sha512-z0J8InXR9e9wcgNtmVnPTj0TU8nhYT6lD/ak9may2PdKqXIeHUr8UbFLoCtrPYNsjv6YaLvSDQVl578k6nm7GA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", + "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", "requires": { "d3-array": "1" } }, "d3-hierarchy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.8.tgz", - "integrity": "sha512-L+GHMSZNwTpiq4rt9GEsNcpLa4M96lXMR8M/nMG9p5hBE0jy6C+3hWtyZMenPQdwla249iJy7Nx0uKt3n+u9+w==" + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", + "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==" }, "d3-interpolate": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.3.2.tgz", - "integrity": "sha512-NlNKGopqaz9qM1PXh9gBF1KSCVh+jSFErrSlD/4hybwoNX/gt1d8CDbDW+3i+5UOHhjC6s6nMvRxcuoMVNgL2w==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", + "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", "requires": { "d3-color": "1" } }, "d3-path": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.8.tgz", - "integrity": "sha512-J6EfUNwcMQ+aM5YPOB8ZbgAZu6wc82f/0WFxrxwV6Ll8wBwLaHLKCqQ5Imub02JriCVVdPjgI+6P3a4EWJCxAg==" + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" }, "d3-polygon": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.5.tgz", - "integrity": "sha512-RHhh1ZUJZfhgoqzWWuRhzQJvO7LavchhitSTHGu9oj6uuLFzYZVeBzaWTQ2qSO6bz2w55RMoOCf0MsLCDB6e0w==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", + "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==" }, "d3-quadtree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.6.tgz", - "integrity": "sha512-NUgeo9G+ENQCQ1LsRr2qJg3MQ4DJvxcDNCiohdJGHt5gRhBW6orIB5m5FJ9kK3HNL8g9F4ERVoBzcEwQBfXWVA==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", + "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==" }, "d3-random": { "version": "1.1.2", @@ -3388,14 +2913,14 @@ } }, "d3-selection": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.0.tgz", - "integrity": "sha512-EYVwBxQGEjLCKF2pJ4+yrErskDnz5v403qvAid96cNdCMr8rmCYfY5RGzWz24mdIbxmDf6/4EAH+K9xperD5jg==" + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", + "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==" }, "d3-shape": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.5.tgz", - "integrity": "sha512-VKazVR3phgD+MUCldapHD7P9kcrvPcexeX/PkMJmkUov4JM8IxsSg1DvbYoYich9AtdTsa5nNk2++ImPiDiSxg==", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", "requires": { "d3-path": "1" } @@ -3406,22 +2931,22 @@ "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" }, "d3-time-format": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.3.tgz", - "integrity": "sha512-6k0a2rZryzGm5Ihx+aFMuO1GgelgIz+7HhB4PH4OEndD5q2zGn1mDfRdNrulspOfR6JXkb2sThhDK41CSK85QA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", + "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", "requires": { "d3-time": "1" } }, "d3-timer": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.9.tgz", - "integrity": "sha512-rT34J5HnQUHhcLvhSB9GjCkN0Ddd5Y8nCwDBG2u6wQEeYxT/Lf51fTFFkldeib/sE/J0clIe0pnCfs6g/lRbyg==" + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", + "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" }, "d3-transition": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.2.0.tgz", - "integrity": "sha512-VJ7cmX/FPIPJYuaL2r1o1EMHLttvoIuZhhuAlRoOxDzogV8iQS6jYulDm3xEU3TqL80IZIhI551/ebmCMrkvhw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", + "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", "requires": { "d3-color": "1", "d3-dispatch": "1", @@ -3456,11 +2981,6 @@ "assert-plus": "^1.0.0" } }, - "dasherize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz", - "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" - }, "data-urls": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", @@ -3472,14 +2992,14 @@ }, "dependencies": { "abab": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", - "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz", + "integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==" }, "whatwg-url": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", - "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", "requires": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", @@ -3488,11 +3008,6 @@ } } }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -3579,7 +3094,13 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" }, "depd": { "version": "1.1.2", @@ -3587,9 +3108,9 @@ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", "requires": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" @@ -3619,13 +3140,15 @@ "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } } }, - "dns-prefetch-control": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.2.0.tgz", - "integrity": "sha512-hvSnros73+qyZXhHFjx2CMLwoj3Fe7eR9EJsFsqmcI1bB2OBWL/+0YzaEaKssCHnj/6crawNnUyw74Gm2EKe+Q==" - }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -3648,25 +3171,15 @@ "webidl-conversions": "^4.0.2" } }, - "dont-sniff-mimetype": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.1.0.tgz", - "integrity": "sha512-ZjI4zqTaxveH2/tTlzS1wFp+7ncxNZaIEWYg3lzZRHkKf5zPT/MnEG6WL0BhHMJUabkh8GeU5NL5j+rEUCb7Ug==" - }, "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", + "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", "dev": true, "requires": { "is-obj": "^1.0.0" } }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -3684,6 +3197,15 @@ "stream-shift": "^1.0.0" } }, + "easyxml": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/easyxml/-/easyxml-2.0.1.tgz", + "integrity": "sha1-7qCShCyREwCox4GRPL5b04pQcRw=", + "requires": { + "elementtree": "^0.1.6", + "inflect": "^0.3.0" + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -3707,19 +3229,27 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "ejs": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.1.tgz", - "integrity": "sha512-kS/gEPzZs3Y1rRsbGX4UOSjtP/CeJP0CxSNZHYxGfVM/VgLcv0ZqM7C45YyTj2DI2g7+P9Dd24C+IMIg6D0nYQ==" + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", + "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" }, "electron-to-chromium": { - "version": "1.3.275", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.275.tgz", - "integrity": "sha512-/YWtW/VapMnuYA1lNOaa1F4GhR1LBf+CUTp60lzDPEEh0XOzyOAyULyYZVF9vziZ3qSbTqCwmKwsyRXp66STbw==" + "version": "1.3.554", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.554.tgz", + "integrity": "sha512-Vtz2dVH5nMtKK4brahmgScwFS8PBnpA4VObYXtlsqN8ZpT9IFelv0Rpflc1+NIILjGVaj6vEiXQbhrs3Pl8O7g==" + }, + "elementtree": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz", + "integrity": "sha1-mskb5uUvtuYkTE5UpKw+2K6OKcA=", + "requires": { + "sax": "1.1.4" + } }, "elliptic": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", - "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", "requires": { "bn.js": "^4.4.0", "brorand": "^1.0.1", @@ -3728,18 +3258,24 @@ "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } } }, "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" }, "encodeurl": { "version": "1.0.2", @@ -3747,9 +3283,9 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "requires": { "once": "^1.4.0" } @@ -3767,6 +3303,11 @@ "ws": "~3.3.1" }, "dependencies": { + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -3805,6 +3346,11 @@ "yeast": "0.1.2" }, "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -3838,22 +3384,83 @@ } }, "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", "requires": { "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", + "memory-fs": "^0.5.0", "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } } }, "env-cmd": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-8.0.2.tgz", - "integrity": "sha512-gHX8MnQXw1iS7dc2KeJdBdxca7spIkxkNwIuORLwm8kDg6xHh5wWnv1Yv3pc64nLZR6kufQSCmwTz16sRmd/rg==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-10.1.0.tgz", + "integrity": "sha512-mMdWTT9XKN7yNth/6N6g2GuKuJTsKMDHlQFUDacb/heQRRWOTIZ42t1rMHnQu4jYxU1ajdTeJM+9eEETlqToMA==", "dev": true, "requires": { - "cross-spawn": "^6.0.5" + "commander": "^4.0.0", + "cross-spawn": "^7.0.0" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "errno": { @@ -3880,22 +3487,57 @@ "requires": { "accepts": "~1.3.7", "escape-html": "~1.0.3" - }, - "dependencies": { - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - } + } + }, + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "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.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "es-get-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", + "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", + "dev": true, + "requires": { + "es-abstract": "^1.17.4", + "has-symbols": "^1.0.1", + "is-arguments": "^1.0.4", + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" } }, "es6-error": { @@ -3905,9 +3547,14 @@ "dev": true }, "es6-promisify": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.0.2.tgz", - "integrity": "sha512-eO6vFm0JvqGzjWIQA6QVKjxpmELfhWbDUWHm1rPfIbn55mhKPiAa5xpLmQWJrNa629ZIeQ8ZvMAi13kvrjK6Mg==" + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.1.1.tgz", + "integrity": "sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==" + }, + "escalade": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", + "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==" }, "escape-html": { "version": "1.0.3", @@ -3919,22 +3566,10 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, - "escodegen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", - "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, "eslint": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.2.1.tgz", - "integrity": "sha512-ES7BzEzr0Q6m5TK9i+/iTpKjclXitOdDK4vT07OqbkBT2/VcN/gO9EL1C4HlK3TAOXYv2ItcmbVR9jO1MR0fJg==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -3944,19 +3579,19 @@ "debug": "^4.0.1", "doctrine": "^3.0.0", "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.2", + "eslint-utils": "^1.4.3", "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.0", + "espree": "^6.1.2", "esquery": "^1.0.1", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^11.7.0", + "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^6.4.1", + "inquirer": "^7.0.0", "is-glob": "^4.0.0", "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", @@ -3965,7 +3600,7 @@ "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", + "optionator": "^0.8.3", "progress": "^2.0.0", "regexpp": "^2.0.1", "semver": "^6.1.2", @@ -3982,40 +3617,55 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "ms": "^2.1.1" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "eslint-scope": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", "dev": true, "requires": { - "ms": "^2.1.1" + "type-fest": "^0.8.1" } }, - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", - "dev": true + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } }, "ms": { "version": "2.1.2", @@ -4023,6 +3673,20 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -4031,15 +3695,6 @@ "requires": { "ansi-regex": "^4.1.0" } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, @@ -4057,67 +3712,70 @@ } }, "eslint-scope": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", - "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", - "dev": true, + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + } } }, "eslint-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", - "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.0.0" + "eslint-visitor-keys": "^1.1.0" } }, "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true }, "espree": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.0.tgz", - "integrity": "sha512-boA7CHRLlVWUSg3iL5Kmlt/xT3Q+sXnKoRYYzj1YeM10A76TEJBbotV5pKbnK42hEUIr121zTv+QLRM5LsCPXQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", "dev": true, "requires": { - "acorn": "^7.0.0", - "acorn-jsx": "^5.0.0", + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", "eslint-visitor-keys": "^1.1.0" }, "dependencies": { "acorn": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz", - "integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", "dev": true } } }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" - }, "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } } }, "esrecurse": { @@ -4126,17 +3784,19 @@ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "requires": { "estraverse": "^4.1.0" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + } } }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" - }, "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "etag": { "version": "1.8.1", @@ -4155,12 +3815,19 @@ "split": "0.3", "stream-combiner": "~0.0.4", "through": "~2.3.1" + }, + "dependencies": { + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + } } }, "events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==" }, "evp_bytestokey": { "version": "1.0.3", @@ -4239,11 +3906,6 @@ "homedir-polyfill": "^1.0.1" } }, - "expect-ct": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.2.0.tgz", - "integrity": "sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g==" - }, "expose-loader": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/expose-loader/-/expose-loader-0.7.5.tgz", @@ -4284,32 +3946,6 @@ "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" - }, - "dependencies": { - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - } } }, "express-minify": { @@ -4320,12 +3956,20 @@ "clean-css": "^4.1.7", "on-headers": "^1.0.1", "uglify-js": "^3.0.28" + }, + "dependencies": { + "uglify-js": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.2.tgz", + "integrity": "sha512-GXCYNwqoo0MbLARghYjxVBxDCnU0tLqN7IPLdHHbibCb1NI5zBkU2EPcy/GaVxc0BtTjqyGXJCINe6JMR2Dpow==" + } } }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "extend-shallow": { "version": "3.0.2", @@ -4417,44 +4061,34 @@ } }, "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz", + "integrity": "sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=" }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fastparse": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==" }, - "feature-policy": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz", - "integrity": "sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ==" - }, "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==" + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" }, "figures": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.0.0.tgz", - "integrity": "sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" @@ -4476,8 +4110,26 @@ "requires": { "loader-utils": "^1.0.2", "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, "filesize": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", @@ -4507,24 +4159,28 @@ } }, "find-cache-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", - "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", - "dev": true, + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "requires": { "commondir": "^1.0.1", - "mkdirp": "^0.5.1", - "pkg-dir": "^1.0.0" + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "dependencies": { + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + } } }, "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "locate-path": "^3.0.0" } }, "findup-sync": { @@ -4538,6 +4194,23 @@ "resolve-dir": "^1.0.1" } }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + } + } + }, "flat-cache": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", @@ -4547,610 +4220,142 @@ "flatted": "^2.0.0", "rimraf": "2.6.3", "write": "1.0.3" - } - }, - "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", - "dev": true - }, - "flot": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/flot/-/flot-0.8.3.tgz", - "integrity": "sha512-xg2otcTJDvS+ERK+my4wxG/ASq90QURXtoM4LhacCq0jQW2jbyjdttbRNqU2cPykrpMvJ6b2uSp6SAgYAzj9tQ==" - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "foreground-child": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", - "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", - "dev": true, - "requires": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" }, "dependencies": { - "cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" + "glob": "^7.1.3" } } } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", - "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==", - "dev": true - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } - }, - "frameguard": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.1.0.tgz", - "integrity": "sha512-TxgSKM+7LTA6sidjOiSZK9wxY0ffMPY3Wta//MqwmX0nZuEHc8QrkV8Fh3ZhMJeiH+Uyh/tcaarImRy8u77O7g==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "optional": true, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "flot": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/flot/-/flot-0.8.3.tgz", + "integrity": "sha512-xg2otcTJDvS+ERK+my4wxG/ASq90QURXtoM4LhacCq0jQW2jbyjdttbRNqU2cPykrpMvJ6b2uSp6SAgYAzj9tQ==" + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "dev": true, + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "dev": true, "requires": { - "string-width": "^1.0.2 || 2" + "lru-cache": "^4.0.1", + "which": "^1.2.9" } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "optional": true } } }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", + "dev": true + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -5162,6 +4367,11 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -5187,10 +4397,9 @@ } }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5201,10 +4410,9 @@ } }, "glob-parent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", - "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", - "dev": true, + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "requires": { "is-glob": "^4.0.1" } @@ -5275,9 +4483,9 @@ } }, "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" }, "growl": { "version": "1.10.5", @@ -5295,40 +4503,37 @@ "pify": "^4.0.1" }, "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true } } }, - "handlebars": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", - "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", - "dev": true, - "requires": { - "neo-async": "^2.6.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - } - }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -5343,6 +4548,13 @@ "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "requires": { "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + } } }, "has-cors": { @@ -5350,15 +4562,10 @@ "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, "has-value": { "version": "1.0.0", @@ -5408,12 +4615,35 @@ } }, "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } } }, "hash.js": { @@ -5440,63 +4670,10 @@ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, - "heapdump": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/heapdump/-/heapdump-0.3.15.tgz", - "integrity": "sha512-n8aSFscI9r3gfhOcAECAtXFaQ1uy4QSke6bnaL+iymYZ/dWs9cqDqHM+rALfsHUwukUbxsdlECZ0pKmJdQ/4OA==", - "requires": { - "nan": "^2.13.2" - } - }, "helmet": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.21.1.tgz", - "integrity": "sha512-IC/54Lxvvad2YiUdgLmPlNFKLhNuG++waTF5KPYq/Feo3NNhqMFbcLAlbVkai+9q0+4uxjxGPJ9bNykG+3zZNg==", - "requires": { - "depd": "2.0.0", - "dns-prefetch-control": "0.2.0", - "dont-sniff-mimetype": "1.1.0", - "expect-ct": "0.2.0", - "feature-policy": "0.3.0", - "frameguard": "3.1.0", - "helmet-crossdomain": "0.4.0", - "helmet-csp": "2.9.2", - "hide-powered-by": "1.1.0", - "hpkp": "2.0.0", - "hsts": "2.2.0", - "ienoopen": "1.1.0", - "nocache": "2.1.0", - "referrer-policy": "1.2.0", - "x-xss-protection": "1.3.0" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - } - } - }, - "helmet-crossdomain": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz", - "integrity": "sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA==" - }, - "helmet-csp": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.9.2.tgz", - "integrity": "sha512-Lt5WqNfbNjEJ6ysD4UNpVktSyjEKfU9LVJ1LaFmPfYseg/xPealPfgHhtqdAdjPDopp5zbg/VWCyp4cluMIckw==", - "requires": { - "bowser": "^2.6.1", - "camelize": "1.0.0", - "content-security-policy-builder": "2.1.0", - "dasherize": "2.0.0" - } - }, - "hide-powered-by": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.1.0.tgz", - "integrity": "sha512-Io1zA2yOA1YJslkr+AJlWSf2yWFkKjvkcL9Ni1XSUqnGLr/qRQe2UI3Cn/J9MsJht7yEVCe0SscY1HgVMujbgg==" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-4.1.0.tgz", + "integrity": "sha512-KWy75fYN8hOG2Rhl8e5B3WhOzb0by1boQum85TiddIE9iu6gV+TXbUjVC17wfej0o/ZUpqB9kxM0NFCZRMzf+Q==" }, "hmac-drbg": { "version": "1.0.1", @@ -5508,6 +4685,12 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hoek": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.4.tgz", + "integrity": "sha512-Alr4ZQgoMlnere5FZJsIyfIjORBqZll5POhDsF4q64dPuJR6rNxXdDxtHSQq8OXRurhmx+PWYEE8bXRROY8h0w==", + "dev": true + }, "homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -5523,31 +4706,11 @@ "dev": true }, "hosted-git-info": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", - "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, - "hpkp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz", - "integrity": "sha1-EOFCJk52IVpdMMROxD3mTe5tFnI=" - }, - "hsts": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.2.0.tgz", - "integrity": "sha512-ToaTnQ2TbJkochoVcdXYm4HOCliNozlviNsg+X2XQLQvZNI/kCHR9rZxVYpJB3UPcHz80PgxRyWQ7PdU1r+VBQ==", - "requires": { - "depd": "2.0.0" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - } - } - }, "html-encoding-sniffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", @@ -5557,9 +4720,15 @@ } }, "html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", + "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, "http-errors": { @@ -5619,11 +4788,6 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, - "ienoopen": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.1.0.tgz", - "integrity": "sha512-MFs36e/ca6ohEKtinTJ5VvAJ6oDRAYFdYXweUnGY9L9vcoqFOU4n2ZhmJ0C4z/cwGZ3YIQRSB3XZ1+ghZkY5NQ==" - }, "iferr": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", @@ -5642,13 +4806,21 @@ "dev": true }, "import-fresh": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", - "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } } }, "import-lazy": { @@ -5664,24 +4836,6 @@ "requires": { "pkg-dir": "^3.0.0", "resolve-cwd": "^2.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "requires": { - "find-up": "^3.0.0" - } - } } }, "imurmurhash": { @@ -5699,6 +4853,11 @@ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" }, + "inflect": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/inflect/-/inflect-0.3.0.tgz", + "integrity": "sha1-gdDqqja1CmAjC3UQBIs5xBQv5So=" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -5719,76 +4878,120 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.1.tgz", - "integrity": "sha512-uxNHBeQhRXIoHWTSNYUFhQVrHYFThIt6IVo2fFmSe8aBwdR3/w6b58hJpiL/fMukFkvGzjg+hSxFtwvVmKZmXw==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", "dev": true, "requires": { "ansi-escapes": "^4.2.1", - "chalk": "^2.4.2", + "chalk": "^4.1.0", "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", + "cli-width": "^3.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", - "lodash": "^4.17.15", + "lodash": "^4.17.19", "mute-stream": "0.0.8", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", "string-width": "^4.1.0", - "strip-ansi": "^5.1.0", + "strip-ansi": "^6.0.0", "through": "^2.3.6" }, "dependencies": { "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } }, "interpret": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" }, "invariant": { "version": "2.2.4", @@ -5798,15 +5001,10 @@ "loose-envify": "^1.0.0" } }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" - }, "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, "is-accessor-descriptor": { "version": "0.1.6", @@ -5826,6 +5024,12 @@ } } }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -5833,11 +5037,11 @@ "dev": true }, "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "^2.0.0" } }, "is-buffer": { @@ -5845,6 +5049,12 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", + "dev": true + }, "is-ci": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", @@ -5872,6 +5082,12 @@ } } }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -5900,10 +5116,9 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "is-glob": { "version": "4.0.1", @@ -5923,6 +5138,12 @@ "is-path-inside": "^1.0.0" } }, + "is-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", + "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", + "dev": true + }, "is-npm": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", @@ -5949,6 +5170,12 @@ "path-is-inside": "^1.0.1" } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -5957,28 +5184,53 @@ "isobject": "^3.0.1" } }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, "is-redirect": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", "dev": true }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true + }, + "is-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", + "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", "dev": true }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } }, "is-typedarray": { "version": "1.0.0", @@ -5996,9 +5248,27 @@ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" }, "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "isemail": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", + "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", + "dev": true, + "requires": { + "punycode": "2.x.x" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } }, "isexe": { "version": "2.0.0", @@ -6015,105 +5285,6 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, "istanbul-lib-coverage": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", @@ -6155,26 +5326,10 @@ "supports-color": "^6.1.0" }, "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "supports-color": { @@ -6210,49 +5365,150 @@ "ms": "^2.1.1" } }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0" + } + }, + "iterate-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", + "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==", + "dev": true + }, + "iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "dev": true, + "requires": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + } + }, + "jacoco-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jacoco-parse/-/jacoco-parse-2.0.1.tgz", + "integrity": "sha512-YGhIb2iXuQ4/zNh2zgHd6Z6dqlYwLYH1wfsxtTNQ+jnHH9PhhuMwqOFihXymSI41trxok48LdKkSeDIWs28tYg==", + "dev": true, + "requires": { + "mocha": "^5.2.0", + "xml2js": "^0.4.9" + }, + "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, - "istanbul-reports": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", - "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "joi": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-13.7.0.tgz", + "integrity": "sha512-xuY5VkHfeOYK3Hdi91ulocfuFopwgbSORmIwzcwHKESQhC7w1kD5jaVSPnqDxS2I8t3RZ9omCKAxNwXN5zG1/Q==", "dev": true, "requires": { - "handlebars": "^4.1.2" + "hoek": "5.x.x", + "isemail": "3.x.x", + "topo": "3.x.x" } }, "jquery": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz", - "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==" + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", + "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==" }, "jquery-ui-bundle": { "version": "1.12.1-migrate", @@ -6264,20 +5520,15 @@ "resolved": "https://registry.npmjs.org/jquery.tooltips/-/jquery.tooltips-1.0.0.tgz", "integrity": "sha1-/Ko2Il0IXQ/NY71E4rAGtUGDHHI=" }, - "js-levenshtein": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", - "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==" - }, "js-storage": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/js-storage/-/js-storage-1.1.0.tgz", "integrity": "sha512-XwkyTB3cjwBSaaKo+edR/n8ZbmX/mj5lJpW/O753NYvMpClQeurucceIvX3HeF4ZTTY2YRPXTVzgPByK4pA7aQ==" }, "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.13.1", @@ -6333,12 +5584,74 @@ "whatwg-url": "^6.4.1", "ws": "^4.0.0", "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } } }, "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, "json-parse-better-errors": { "version": "1.0.2", @@ -6367,11 +5680,18 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", "requires": { - "minimist": "^1.2.0" + "minimist": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + } } }, "jsonwebtoken": { @@ -6397,9 +5717,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -6412,6 +5732,13 @@ "extsprintf": "1.3.0", "json-schema": "0.2.3", "verror": "1.10.0" + }, + "dependencies": { + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + } } }, "jwa": { @@ -6434,9 +5761,9 @@ } }, "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "latest-version": { "version": "3.1.0", @@ -6447,26 +5774,28 @@ "package-json": "^4.0.0" } }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "requires": { - "invert-kv": "^2.0.0" - } + "lcov-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", + "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", + "dev": true }, "left-pad": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==" }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + }, + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "leven": "^3.1.0" } }, "load-json-file": { @@ -6479,16 +5808,71 @@ "parse-json": "^4.0.0", "pify": "^3.0.0", "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, "loader-fs-cache": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.2.tgz", - "integrity": "sha512-70IzT/0/L+M20jUlEqZhZyArTU6VKLRTYRDAYN26g4jfzpJqjipLL3/hgYpySqI9PwsVRHHFja0LfEmsx9X2Cw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz", + "integrity": "sha512-ldcgZpjNJj71n+2Mf6yetz+c9bM4xpKtNds4LbqXzU/PTdeAX0g3ytnU1AJMEcTk2Lex4Smpe3Q/eCTsvUBxbA==", "dev": true, "requires": { "find-cache-dir": "^0.1.1", - "mkdirp": "0.5.1" + "mkdirp": "^0.5.1" + }, + "dependencies": { + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "find-cache-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", + "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "mkdirp": "^0.5.1", + "pkg-dir": "^1.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "^1.0.0" + } + } } }, "loader-runner": { @@ -6497,13 +5881,28 @@ "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" }, "loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", "requires": { "big.js": "^5.2.2", - "emojis-list": "^2.0.0", + "emojis-list": "^3.0.0", "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + } } }, "locate-path": { @@ -6513,19 +5912,12 @@ "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - } } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, "lodash.difference": { "version": "4.5.0", @@ -6578,6 +5970,73 @@ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" }, + "log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true + }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -6600,28 +6059,30 @@ "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" + }, + "dependencies": { + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } } }, "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==" - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "requires": { - "p-defer": "^1.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } } }, "map-cache": { @@ -6643,13 +6104,13 @@ } }, "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", "requires": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" } }, "md5.js": { @@ -6667,16 +6128,6 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, "memory-cache": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", @@ -6691,6 +6142,12 @@ "readable-stream": "^2.0.1" } }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -6703,6 +6160,14 @@ "dev": true, "requires": { "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "methods": { @@ -6814,30 +6279,38 @@ "requires": { "bn.js": "^4.0.0", "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } } }, "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==" + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==" }, "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" }, "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "requires": { - "mime-db": "1.40.0" + "mime-db": "1.43.0" } }, "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true }, "minimalistic-assert": { "version": "1.0.1", @@ -6858,13 +6331,16 @@ } }, "minimed-connect-to-nightscout": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/minimed-connect-to-nightscout/-/minimed-connect-to-nightscout-1.3.2.tgz", - "integrity": "sha512-1fF1ekFafvzNB9VzoP5T74KVJ32UDi9s4IE8ezNGOJ1XUAAq3qgWYGC4tZgug51sbMvr7c77XQw0bIPl2RpU9Q==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/minimed-connect-to-nightscout/-/minimed-connect-to-nightscout-1.4.0.tgz", + "integrity": "sha512-hxbcncJPiQOoTtjp1VquoxA4ab/Lbn1LiwAymeaEUfyqUxaj9E7w8CHJ/kGbgEu2oYHsqUMvJ1orOlCuUA/g6g==", "requires": { + "axios": "^0.19.2", + "axios-cookiejar-support": "^1.0.0", "common": "^0.2.5", "lodash": "^4.17.15", - "request": "^2.88.0" + "request": "^2.88.0", + "tough-cookie": "^4.0.0" }, "dependencies": { "ajv": { @@ -6932,6 +6408,23 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "requires": { + "follow-redirects": "1.5.10" + } + }, + "axios-cookiejar-support": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/axios-cookiejar-support/-/axios-cookiejar-support-1.0.0.tgz", + "integrity": "sha512-9pBlIU5jfrGZTnUQlt8symShviSTOSlOKGtryHx76lJPnKIXDqUT3JDAjJ1ywOQLyfiWrthIt4iJiVP2L2S4jA==", + "requires": { + "is-redirect": "^1.0.0", + "pify": "^5.0.0" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -7201,6 +6694,29 @@ "is-buffer": "~2.0.3" } }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -7351,6 +6867,11 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", @@ -7445,9 +6966,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, "log-symbols": { "version": "2.2.0", @@ -7680,10 +7201,15 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==" + }, "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "pump": { "version": "3.0.0", @@ -7734,6 +7260,20 @@ "node-uuid": { "version": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } } } }, @@ -7842,19 +7382,13 @@ } }, "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" } }, "tunnel-agent": { @@ -7870,6 +7404,11 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -8068,12 +7607,7 @@ } } } - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } }, "mississippi": { "version": "3.0.0", @@ -8090,6 +7624,19 @@ "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + } } }, "mixin-deep": { @@ -8112,102 +7659,219 @@ } }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" }, "dependencies": { "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" } } }, "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.2.tgz", + "integrity": "sha512-I8FRAcuACNMLQn3lS4qeWLxXqLvGf6r2CaLstDpZmMUUSmvW6Cnm1AuHxgbc7ctZVRcfwspCRbDHymPsi3dkJw==", "dev": true, "requires": { + "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", + "chokidar": "3.4.2", + "debug": "4.1.1", + "diff": "4.0.2", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", "growl": "1.10.5", - "he": "1.1.1", + "he": "1.2.0", + "js-yaml": "3.14.0", + "log-symbols": "4.0.0", "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" + "ms": "2.1.2", + "object.assign": "4.1.0", + "promise.allsettled": "1.0.2", + "serialize-javascript": "4.0.0", + "strip-json-comments": "3.0.1", + "supports-color": "7.1.0", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.0.0", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.1" }, "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "ms": "2.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" } }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" } } } }, "moment": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" }, "moment-locales-webpack-plugin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/moment-locales-webpack-plugin/-/moment-locales-webpack-plugin-1.1.0.tgz", - "integrity": "sha512-0Hn+xdNmQt+XZgsWOlwXJcQ881nURSoDJY1o4hOLiyGaUVZbY475GrvyBXUOMc5mgjvPiQz/KU8ht/IoRnadMg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/moment-locales-webpack-plugin/-/moment-locales-webpack-plugin-1.2.0.tgz", + "integrity": "sha512-QAi5v0OlPUP7GXviKMtxnpBAo8WmTHrUNN7iciAhNOEAd9evCOvuN0g1N7ThIg3q11GLCkjY1zQ2saRcf/43nQ==", "requires": { "lodash.difference": "^4.5.0" } }, "moment-timezone": { - "version": "0.5.26", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.26.tgz", - "integrity": "sha512-sFP4cgEKTCymBBKgoxZjYzlSovC20Y6J7y3nanDc5RoBIXKlZhoYwBoZGe3flwU6A372AcRwScH8KiwV6zjy1g==", + "version": "0.5.31", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", + "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", "requires": { "moment": ">= 2.9.0" } }, "moment-timezone-data-webpack-plugin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/moment-timezone-data-webpack-plugin/-/moment-timezone-data-webpack-plugin-1.1.0.tgz", - "integrity": "sha512-szKf9rbRoY9u3WNcwK6D0tdCREk/OZkcF1k163Xc5m7GcqBh28LgNVWisb4sje6/qdG3WUkFD5hJ7/lmKOkBAA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/moment-timezone-data-webpack-plugin/-/moment-timezone-data-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-0V0xnHZpdHLsSerIQ2yNEPBC3uJWfU/zNT3nB0PO+tjmGHuNeUWqNDiw7ZpLo54uER6/OAE75EJ7ThmlwkGuZw==", "requires": { "find-cache-dir": "^3.0.0", "make-dir": "^3.0.0" }, "dependencies": { + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, "find-cache-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.0.0.tgz", - "integrity": "sha512-t7ulV1fmbxh5G9l/492O1p5+EBbr3uwpt6odhFTMc+nWyhmbloe+ja9BZ8pIBtqFWhOmCWVjx+pTW4zDkFoclw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", "requires": { "commondir": "^1.0.1", - "make-dir": "^3.0.0", + "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" } }, @@ -8229,9 +7893,9 @@ } }, "make-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", - "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "requires": { "semver": "^6.0.0" } @@ -8260,13 +7924,16 @@ } }, "mongodb": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.2.tgz", - "integrity": "sha512-fqJt3iywelk4yKu/lfwQg163Bjpo5zDKhXiohycvon4iQHbrfflSAz9AIlRE6496Pm/dQKQK5bMigdVo2s6gBg==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.0.tgz", + "integrity": "sha512-/XWWub1mHZVoqEsUppE0GV7u9kanLvHxho6EvBxQbShXTKYF9trhZC2NzbulRGeG7xMJHD8IOWRcdKx5LPjAjQ==", "requires": { - "bson": "^1.1.1", + "bl": "^2.2.0", + "bson": "^1.1.4", + "denque": "^1.4.1", "require_optional": "^1.0.1", - "safe-buffer": "^5.1.2" + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" } }, "mongomock": { @@ -8302,9 +7969,10 @@ "dev": true }, "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "optional": true }, "nanomatch": { "version": "1.2.13", @@ -8331,9 +7999,9 @@ "dev": true }, "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, "neo-async": { "version": "2.6.1", @@ -8351,11 +8019,6 @@ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, - "nocache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz", - "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==" - }, "node-cache": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-4.2.1.tgz", @@ -8400,39 +8063,134 @@ "vm-browserify": "^1.0.1" }, "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" } } }, "node-releases": { - "version": "1.1.34", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.34.tgz", - "integrity": "sha512-fNn12JTEfniTuCqo0r9jXgl44+KxRH/huV7zM/KAGOKxDKrHr6EbT7SSs4B+DNxyBE2mks28AD+Jw6PkfY5uwA==", - "requires": { - "semver": "^6.3.0" - } + "version": "1.1.60", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", + "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==" }, "nodemon": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.1.tgz", - "integrity": "sha512-/DXLzd/GhiaDXXbGId5BzxP1GlsqtMGM9zTmkWrgXtSqjKmGSbLicM/oAy4FR0YWm14jCHRwnR31AHS2dYFHrg==", + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.4.tgz", + "integrity": "sha512-VGPaqQBNk193lrJFotBU8nvWZPqEZY2eIzymy2jjY0fJ9qIsxA0sxQ8ATPl0gZC645gijYEc1jtZvpS8QWzJGQ==", "dev": true, "requires": { - "chokidar": "^2.1.5", - "debug": "^3.1.0", + "chokidar": "^2.1.8", + "debug": "^3.2.6", "ignore-by-default": "^1.0.1", "minimatch": "^3.0.4", - "pstree.remy": "^1.1.6", - "semver": "^5.5.0", - "supports-color": "^5.2.0", + "pstree.remy": "^1.1.7", + "semver": "^5.7.1", + "supports-color": "^5.5.0", "touch": "^3.1.0", "undefsafe": "^2.0.2", "update-notifier": "^2.5.0" }, "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -8442,12 +8200,109 @@ "ms": "^2.1.1" } }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -8462,16 +8317,17 @@ "requires": { "has-flag": "^3.0.0" } - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } } }, "normalize-package-data": { @@ -8486,6 +8342,15 @@ "validate-npm-package-license": "^3.0.1" }, "dependencies": { + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -8503,14 +8368,15 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, "requires": { "path-key": "^2.0.0" } }, "nwsapi": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.3.tgz", - "integrity": "sha512-RowAaJGEgYXEZfQ7tvvdtAQUKPyTR6T6wNu0fwlNsGQYr/h3yQc6oI8WnVZh3Y/Sylwc+dtAlvPqfFZjhTyk3A==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" }, "nyc": { "version": "14.1.1", @@ -8545,69 +8411,19 @@ "yargs-parser": "^13.0.0" }, "dependencies": { - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", "dev": true, "requires": { - "find-up": "^3.0.0" + "safe-buffer": "~5.1.1" } }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true } } @@ -8661,6 +8477,12 @@ "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", "dev": true }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -8715,9 +8537,9 @@ } }, "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { "mimic-fn": "^2.1.0" @@ -8729,43 +8551,6 @@ "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==", "dev": true }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -8777,64 +8562,21 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - }, - "dependencies": { - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } - } - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" - }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true }, "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { "p-try": "^2.0.0" } @@ -8885,9 +8627,9 @@ } }, "pako": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", - "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "parallel-transform": { "version": "1.2.0", @@ -8909,22 +8651,21 @@ } }, "parse-asn1": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", - "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", "requires": { - "asn1.js": "^4.0.0", + "asn1.js": "^5.2.0", "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", "pbkdf2": "^3.0.3", "safe-buffer": "^5.1.1" } }, "parse-duration": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/parse-duration/-/parse-duration-0.1.1.tgz", - "integrity": "sha1-ExFN3JiRwezSgANiRFVN5DZHoiY=" + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/parse-duration/-/parse-duration-0.1.3.tgz", + "integrity": "sha512-hMOZHfUmjxO5hMKn7Eft+ckP2M4nV4yzauLXiw3PndpkASnx5r8pDAMcOAiqxoemqWjMWmz4fOHQM6n6WwETXw==" }, "parse-json": { "version": "4.0.0", @@ -8983,13 +8724,9 @@ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", @@ -9024,6 +8761,14 @@ "dev": true, "requires": { "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, "pause-stream": { @@ -9035,9 +8780,9 @@ } }, "pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", "requires": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -9047,14 +8792,24 @@ } }, "pem": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/pem/-/pem-1.14.3.tgz", - "integrity": "sha512-Q+AMVMD3fzeVvZs5PHeI+pVt0hgZY2fjhkliBW43qyONLgCXPVk1ryim43F9eupHlNGLJNT5T/NNrzhUdiC5Zg==", + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/pem/-/pem-1.14.4.tgz", + "integrity": "sha512-v8lH3NpirgiEmbOqhx0vwQTxwi0ExsiWBGYh0jYNq7K6mQuO4gI6UEFlr6fLAdv9TPXRt6GqiwE37puQdIDS8g==", "requires": { "es6-promisify": "^6.0.0", "md5": "^2.2.1", "os-tmpdir": "^1.0.1", - "which": "^1.3.1" + "which": "^2.0.2" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } } }, "performance-now": { @@ -9062,11 +8817,15 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" + }, "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, "pinkie": { "version": "2.0.4", @@ -9084,12 +8843,11 @@ } }, "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "requires": { - "find-up": "^1.0.0" + "find-up": "^3.0.0" } }, "pn": { @@ -9112,23 +8870,15 @@ "supports-color": "^5.4.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "supports-color": { "version": "5.5.0", @@ -9191,20 +8941,10 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" - }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "progress": { "version": "2.0.3", @@ -9217,13 +8957,26 @@ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" }, + "promise.allsettled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", + "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", + "dev": true, + "requires": { + "array.prototype.map": "^1.0.1", + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "iterate-value": "^1.0.0" + } + }, "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", "requires": { "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" + "ipaddr.js": "1.9.1" } }, "prr": { @@ -9238,14 +8991,14 @@ "dev": true }, "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "pstree.remy": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz", - "integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, "public-encrypt": { @@ -9259,6 +9012,13 @@ "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + } } }, "pump": { @@ -9292,19 +9052,19 @@ } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.2.4.tgz", + "integrity": "sha1-VACKyXKux0F13vnLpt9/qdORh0A=" }, "pushover-notifications": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pushover-notifications/-/pushover-notifications-1.2.1.tgz", - "integrity": "sha512-FEPbbEhKPDw4PP/e4irEEv1gRmHvt2rulpsvj9OaWTBLWuTf0qBEuaydOsYnQdXS7zq0fAX/ptsj5/BqbKrcUw==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/pushover-notifications/-/pushover-notifications-1.2.2.tgz", + "integrity": "sha512-+3Xcj+kiMiouZK1Ws8yGBTyl8WMPZZdELgl/iVxYqNwDdlaObBHMhEGPRC6Zb9t0BE27ikOoOqSIO1cKZOtsDA==" }, "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, "querystring": { "version": "0.2.0", @@ -9352,13 +9112,6 @@ "http-errors": "1.7.2", "iconv-lite": "0.4.24", "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - } } }, "rc": { @@ -9373,6 +9126,12 @@ "strip-json-comments": "~2.0.1" }, "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -9400,23 +9159,12 @@ "requires": { "find-up": "^3.0.0", "read-pkg": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - } } }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -9435,39 +9183,37 @@ } }, "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "picomatch": "^2.2.1" } }, - "referrer-policy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.2.0.tgz", - "integrity": "sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA==" - }, "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", + "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==" }, "regenerate-unicode-properties": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", - "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", "requires": { "regenerate": "^1.4.0" } }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, "regenerator-transform": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", - "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", "requires": { - "private": "^0.1.6" + "@babel/runtime": "^7.8.4" } }, "regex-not": { @@ -9486,13 +9232,16 @@ "dev": true }, "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", + "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" } }, "registry-auth-token": { @@ -9515,16 +9264,23 @@ } }, "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" }, "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", "requires": { "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + } } }, "release-zalgo": { @@ -9552,9 +9308,9 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -9563,7 +9319,7 @@ "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", - "har-validator": "~5.1.0", + "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -9573,41 +9329,72 @@ "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", + "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" }, "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" } } }, + "request-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", + "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, "request-promise-core": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", - "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.19" } }, "request-promise-native": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", - "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", "requires": { - "request-promise-core": "1.1.2", + "request-promise-core": "1.1.4", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" } @@ -9631,11 +9418,6 @@ "semver": "^5.1.0" }, "dependencies": { - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -9643,14 +9425,6 @@ } } }, - "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "requires": { - "path-parse": "^1.0.6" - } - }, "resolve-cwd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", @@ -9688,10 +9462,9 @@ } }, "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" }, "resolve-url": { "version": "0.2.1", @@ -9720,26 +9493,11 @@ "dev": true }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "requires": { "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } } }, "ripemd160": { @@ -9752,13 +9510,10 @@ } }, "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true }, "run-queue": { "version": "1.0.3", @@ -9774,9 +9529,9 @@ "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" }, "rxjs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", - "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz", + "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -9800,19 +9555,28 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha1-dLbTPJrh4AFRDxeakRaFiPGu2qk=" }, "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" } }, "semver": { @@ -9870,9 +9634,12 @@ } }, "serialize-javascript": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", - "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "requires": { + "randombytes": "^2.1.0" + } }, "serve-static": { "version": "1.14.1", @@ -9931,9 +9698,9 @@ } }, "share2nightscout-bridge": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/share2nightscout-bridge/-/share2nightscout-bridge-0.2.1.tgz", - "integrity": "sha512-tzMlJHYNysMsPgCwbG0y+hHA6XtYtpZ13YCoXQ6aQqxsn8fln/JUkJU8jCt1LfeMkvY2BAq+d4oek4r0aACQoQ==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/share2nightscout-bridge/-/share2nightscout-bridge-0.2.4.tgz", + "integrity": "sha512-GLDEMnIETcxUZj/dRgnhsHz33/tFSojZsP5FNHn8mUS/UHmAR6AE6GIbjrUxWO2RQCKqf+E/v8o+ORUfOKKvgA==", "requires": { "request": "^2.88.0" }, @@ -10292,9 +10059,9 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "shiro-trie": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/shiro-trie/-/shiro-trie-0.4.8.tgz", - "integrity": "sha512-CtBcRIbueg6dnSE1XuFf03RX67GdSUFcb5+zhbTL+cESTd8Vjr42YvtHMKlOZvsLt0RmtbuLzslLix8E4nKFwg==" + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/shiro-trie/-/shiro-trie-0.4.9.tgz", + "integrity": "sha512-iNdNhhYLb9BsTOp242Wmk359ZiRZqAcGbMsxP0GQns0K8HMeO5zhOTFdnQE7ewgFGEPnmZaXPVHNU6zyhG+kYQ==" }, "should": { "version": "13.2.3", @@ -10345,15 +10112,16 @@ } }, "should-util": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.0.tgz", - "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", "dev": true }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true }, "simple-statistics": { "version": "0.7.0", @@ -10369,23 +10137,6 @@ "ansi-styles": "^3.2.0", "astral-regex": "^1.0.0", "is-fullwidth-code-point": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - } } }, "snapdragon": { @@ -10514,9 +10265,9 @@ } }, "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" }, "socket.io-client": { "version": "2.1.1", @@ -10539,6 +10290,11 @@ "to-array": "0.1.4" }, "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -10559,6 +10315,11 @@ "isarray": "2.0.1" }, "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -10566,6 +10327,11 @@ "requires": { "ms": "2.0.0" } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" } } }, @@ -10574,17 +10340,12 @@ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "requires": { - "atob": "^2.1.1", + "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", @@ -10592,12 +10353,19 @@ } }, "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "source-map-url": { @@ -10605,10 +10373,19 @@ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, "spawn-wrap": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", - "integrity": "sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", + "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", "dev": true, "requires": { "foreground-child": "^1.5.6", @@ -10620,9 +10397,9 @@ } }, "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -10630,15 +10407,15 @@ } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -10741,6 +10518,13 @@ "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "requires": { "duplexer": "~0.1.1" + }, + "dependencies": { + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + } } }, "stream-each": { @@ -10770,33 +10554,50 @@ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" }, "string-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz", - "integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^5.2.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" }, "dependencies": { "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } } } }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -10822,12 +10623,13 @@ "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true }, "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "style-loader": { @@ -10837,6 +10639,18 @@ "requires": { "loader-utils": "^1.1.0", "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "superagent": { @@ -10873,9 +10687,9 @@ "dev": true }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } @@ -10890,28 +10704,23 @@ "superagent": "^3.8.3" } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, "swagger-ui-dist": { - "version": "3.23.11", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.23.11.tgz", - "integrity": "sha512-ipENHHH/sqpngTpHXUwg55eAOZ7b2UVayUwwuWPA6nQSPhjBVXX4zOPpNKUwQIFOl3oIwVvZF7mqoxH7pMgVzA==" + "version": "3.32.5", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.32.5.tgz", + "integrity": "sha512-3SKHv8UVqsKKknivtACHbFDGcn297jkoZN2h6zAZ7b2yoaJNMaRadQpC3qFw3GobZTGzqHCgHph4ZH9NkaCjrQ==" }, "swagger-ui-express": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.1.2.tgz", - "integrity": "sha512-bVT16qj6WdNlEKFkSLOoTeGuqEm2lfOFRq6mVHAx+viA/ikORE+n4CS3WpVcYmQzM4HE6+DUFgAWcMRBJNpjcw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.1.4.tgz", + "integrity": "sha512-Ea96ecpC+Iq9GUqkeD/LFR32xSs8gYqmTW1gXCuKg81c26WV6ZC2FsBSPVExQP6WkyUuz5HEiR0sEv/HCC343g==", "requires": { "swagger-ui-dist": "^3.18.1" } }, "symbol-tree": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", - "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=" + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "table": { "version": "5.4.6", @@ -10923,58 +10732,6 @@ "lodash": "^4.17.14", "slice-ansi": "^2.1.0", "string-width": "^3.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } } }, "tapable": { @@ -10999,73 +10756,50 @@ "commander": "^2.19.0", "source-map": "~0.6.1", "source-map-support": "~0.5.10" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "terser-webpack-plugin": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", - "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", "requires": { "cacache": "^12.0.2", "find-cache-dir": "^2.1.0", "is-wsl": "^1.1.0", "schema-utils": "^1.0.0", - "serialize-javascript": "^2.1.2", + "serialize-javascript": "^4.0.0", "source-map": "^0.6.1", "terser": "^4.1.2", "webpack-sources": "^1.4.0", "worker-farm": "^1.7.0" }, "dependencies": { - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "requires": { - "find-up": "^3.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "terser": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.2.tgz", - "integrity": "sha512-Uufrsvhj9O1ikwgITGsZ5EZS6qPokUOkCegS7fYOdGTv+OA90vndUbU6PEjr5ePqHfNUbGyMO7xyIZv2MhsALQ==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", "requires": { "commander": "^2.20.0", "source-map": "~0.6.1", @@ -11074,32 +10808,16 @@ } } }, - "test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", - "dev": true, - "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" } }, "text-table": { @@ -11202,6 +10920,23 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "topo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz", + "integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==", + "dev": true, + "requires": { + "hoek": "6.x.x" + }, + "dependencies": { + "hoek": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", + "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", + "dev": true + } + } + }, "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -11229,6 +10964,13 @@ "requires": { "psl": "^1.1.28", "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } } }, "tr46": { @@ -11237,6 +10979,13 @@ "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", "requires": { "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } } }, "traverse": { @@ -11244,11 +10993,6 @@ "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" - }, "tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -11256,9 +11000,9 @@ "dev": true }, "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" }, "tty-browserify": { "version": "0.0.0", @@ -11287,9 +11031,9 @@ } }, "type-fest": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz", - "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, "type-is": { @@ -11306,24 +11050,15 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, - "uglify-js": { - "version": "3.5.6", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.6.tgz", - "integrity": "sha512-YDKRX8F0Y+Jr7LhoVk0n4G7ltR3Y7qFAj+DtVBthlOgCcIj1hyMigCfousVfn9HKmvJ+qiFlLDwaHx44/e5ZKw==", - "requires": { - "commander": "~2.20.0", - "source-map": "~0.6.1" - } - }, "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" }, "undefsafe": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", - "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", + "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", "dev": true, "requires": { "debug": "^2.2.0" @@ -11344,14 +11079,14 @@ } }, "unicode-match-property-value-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", - "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==" }, "unicode-property-aliases-ecmascript": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", - "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==" }, "union-value": { "version": "1.0.1", @@ -11442,9 +11177,9 @@ "dev": true }, "upath": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" }, "update-notifier": { "version": "2.5.0", @@ -11462,37 +11197,6 @@ "latest-version": "^3.0.0", "semver-diff": "^2.0.0", "xdg-basedir": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, "uri-js": { @@ -11501,6 +11205,13 @@ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "requires": { "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } } }, "urix": { @@ -11557,15 +11268,14 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "v8-compile-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==" }, "validate-npm-package-license": { "version": "3.0.4", @@ -11592,27 +11302,199 @@ "extsprintf": "^1.2.0" } }, - "vm-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", - "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==" - }, "w3c-hr-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", - "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", "requires": { - "browser-process-hrtime": "^0.1.2" + "browser-process-hrtime": "^1.0.0" } }, "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", + "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", "requires": { - "chokidar": "^2.0.2", + "chokidar": "^3.4.1", "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "optional": true, + "requires": { + "chokidar": "^2.1.8" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "optional": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "optional": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "optional": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } } }, "webidl-conversions": { @@ -11621,75 +11503,60 @@ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" }, "webpack": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.0.tgz", - "integrity": "sha512-yNV98U4r7wX1VJAj5kyMsu36T8RPPQntcb5fJLOsMz/pt/WrKC0Vp1bAlqPLkA1LegSwQwf6P+kAbyhRKVQ72g==", - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/wasm-edit": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.2.1", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz", + "integrity": "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", "ajv": "^6.10.2", "ajv-keywords": "^3.4.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.1.0", + "enhanced-resolve": "^4.3.0", "eslint-scope": "^4.0.3", "json-parse-better-errors": "^1.0.2", "loader-runner": "^2.4.0", "loader-utils": "^1.2.3", "memory-fs": "^0.4.1", "micromatch": "^3.1.10", - "mkdirp": "^0.5.1", + "mkdirp": "^0.5.3", "neo-async": "^2.6.1", "node-libs-browser": "^2.2.1", "schema-utils": "^1.0.0", "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.1", - "watchpack": "^1.6.0", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", "webpack-sources": "^1.4.1" }, "dependencies": { "acorn": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", - "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==" - }, - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==" + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } } } }, "webpack-bundle-analyzer": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.4.1.tgz", - "integrity": "sha512-Bs8D/1zF+17lhqj2OYmzi7HEVYqEVxu7lCO9Ff8BwajenOU0vAwEoV8e4ICCPNZAcqR1PCR/7o2SkW+cnCmF0A==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.8.0.tgz", + "integrity": "sha512-PODQhAYVEourCcOuU+NiYI7WdR8QyELZGgPvB1y2tjbUpbmcQOt5Q7jEK+ttd5se0KSBKD9SXHCEozS++Wllmw==", "dev": true, "requires": { - "acorn": "^6.0.7", - "acorn-walk": "^6.1.1", + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1", "bfj": "^6.1.1", "chalk": "^2.4.1", "commander": "^2.18.0", @@ -11704,39 +11571,16 @@ }, "dependencies": { "acorn": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", - "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true }, "ws": { "version": "6.2.1", @@ -11750,91 +11594,27 @@ } }, "webpack-cli": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.9.tgz", - "integrity": "sha512-xwnSxWl8nZtBl/AFJCOn9pG7s5CYUYdZxmmukv+fAHLcBIHM36dImfpQg3WfShZXeArkWlf6QRw24Klcsv8a5A==", - "requires": { - "chalk": "2.4.2", - "cross-spawn": "6.0.5", - "enhanced-resolve": "4.1.0", - "findup-sync": "3.0.0", - "global-modules": "2.0.0", - "import-local": "2.0.0", - "interpret": "1.2.0", - "loader-utils": "1.2.3", - "supports-color": "6.1.0", - "v8-compile-cache": "2.0.3", - "yargs": "13.2.4" + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", + "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", + "requires": { + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.1", + "findup-sync": "^3.0.0", + "global-modules": "^2.0.0", + "import-local": "^2.0.0", + "interpret": "^1.4.0", + "loader-utils": "^1.4.0", + "supports-color": "^6.1.0", + "v8-compile-cache": "^2.1.1", + "yargs": "^13.3.2" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "find-up": { + "has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "supports-color": { "version": "6.1.0", @@ -11843,29 +11623,6 @@ "requires": { "has-flag": "^3.0.0" } - }, - "v8-compile-cache": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz", - "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==" - }, - "yargs": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", - "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.0" - } } } }, @@ -11902,6 +11659,14 @@ "requires": { "ansi-colors": "^3.0.0", "uuid": "^3.3.2" + }, + "dependencies": { + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + } } }, "webpack-sources": { @@ -11911,6 +11676,13 @@ "requires": { "source-list-map": "^2.0.0", "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "whatwg-encoding": { @@ -11919,16 +11691,6 @@ "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", "requires": { "iconv-lite": "0.4.24" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } } }, "whatwg-mimetype": { @@ -11959,6 +11721,42 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, "widest-line": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", @@ -11974,12 +11772,6 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -12001,10 +11793,10 @@ } } }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, "worker-farm": { "version": "1.7.0", @@ -12014,6 +11806,12 @@ "errno": "~0.1.7" } }, + "workerpool": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", + "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", + "dev": true + }, "wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", @@ -12029,34 +11827,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -12101,11 +11871,6 @@ "safe-buffer": "~5.1.0" } }, - "x-xss-protection": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.3.0.tgz", - "integrity": "sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg==" - }, "xdg-basedir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", @@ -12117,6 +11882,22 @@ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true + }, "xmlhttprequest-ssl": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", @@ -12133,16 +11914,14 @@ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dev": true, + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", @@ -12153,74 +11932,62 @@ "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", + "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "decamelize": "^1.2.0", + "flat": "^4.1.0", + "is-plain-obj": "^1.1.0", + "yargs": "^14.2.3" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "yargs": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "cliui": "^5.0.0", + "decamelize": "^1.2.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": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" } }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "yargs-parser": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", + "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - } - } - }, "yeast": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", diff --git a/package.json b/package.json index 32ee90d2a33..bbc6f063262 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nightscout", - "version": "13.0.1", + "version": "14.0.7", "description": "Nightscout acts as a web-based CGM (Continuous Glucose Montinor) to allow multiple caregivers to remotely view a patients glucose data in realtime.", "license": "AGPL-3.0", "author": "Nightscout Team", @@ -27,17 +27,19 @@ }, "scripts": { "start": "node server.js", - "test": "env-cmd ./my.test.env mocha --exit tests/*.test.js", - "test-ci": "env-cmd ./ci.test.env mocha --exit tests/*.test.js", + "test": "env-cmd -f ./my.test.env mocha --exit tests/*.test.js", + "test-single": "env-cmd -f ./my.test.env mocha --exit tests/$TEST.test.js", + "test-ci": "env-cmd -f ./ci.test.env nyc --reporter=lcov --reporter=text-summary mocha --exit tests/*.test.js", "env": "env", "postinstall": "webpack --mode production --config webpack.config.js && npm run-script update-buster", "bundle": "webpack --mode production --config webpack.config.js && npm run-script update-buster", "bundle-dev": "webpack --mode development --config webpack.config.js && npm run-script update-buster", "bundle-analyzer": "webpack --mode development --config webpack.config.js --profile --json > stats.json && webpack-bundle-analyzer stats.json", "update-buster": "node bin/generateCacheBuster.js >tmp/cacheBusterToken", - "coverage": "env-cmd ./test.env nyc mocha --exit tests/*.test.js", - "dev": "env-cmd ./my.env nodemon server.js 0.0.0.0", - "prod": "env-cmd ./my.prod.env node server.js 0.0.0.0" + "coverage": "cat ./coverage/lcov.info | env-cmd -f ./ci.test.env codacy-coverage", + "dev": "env-cmd -f ./my.env nodemon server.js 0.0.0.0", + "prod": "env-cmd -f ./my.prod.env node server.js 0.0.0.0", + "lint": "eslint lib" }, "main": "server.js", "config": { @@ -55,15 +57,15 @@ } }, "engines": { - "node": "^10.15.2 || ^8.15.1", - "npm": "^6.4.1" + "node": "^10.22.0 || ^12.18.4", + "npm": "^6.14.6" }, "dependencies": { - "@babel/core": "^7.5.5", - "@babel/preset-env": "^7.5.5", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", "apn": "^2.2.0", "async": "^0.9.2", - "babel-loader": "^8.0.6", + "babel-loader": "^8.1.0", "base64url": "^3.0.1", "body-parser": "^1.19.0", "bootevent": "0.0.1", @@ -71,8 +73,10 @@ "compression": "^1.7.4", "css-loader": "^1.0.1", "cssmin": "^0.4.3", - "d3": "^5.12.0", - "ejs": "^2.6.2", + "csv-stringify": "^5.5.1", + "d3": "^5.16.0", + "easyxml": "^2.0.1", + "ejs": "^2.7.4", "errorhandler": "^1.5.1", "event-stream": "3.3.4", "expose-loader": "^0.7.5", @@ -80,60 +84,61 @@ "express-minify": "^1.0.0", "file-loader": "^3.0.1", "flot": "^0.8.3", - "heapdump": "^0.3.15", - "helmet": "^3.20.0", - "jquery": "^3.4.1", + "helmet": "^4.0.0", + "jquery": "^3.5.1", "jquery-ui-bundle": "^1.12.1-migrate", "jquery.tooltips": "^1.0.0", "js-storage": "^1.1.0", "jsdom": "~11.11.0", "jsonwebtoken": "^8.5.1", - "lodash": "^4.17.15", + "lodash": "^4.17.20", "memory-cache": "^0.2.0", - "mime": "^2.4.4", - "minimed-connect-to-nightscout": "^1.3.2", - "moment": "^2.24.0", - "moment-locales-webpack-plugin": "^1.1.0", - "moment-timezone": "^0.5.26", - "moment-timezone-data-webpack-plugin": "^1.1.0", - "mongodb": "^3.3.0", + "mime": "^2.4.6", + "minimed-connect-to-nightscout": "^1.4.0", + "moment": "^2.27.0", + "moment-locales-webpack-plugin": "^1.2.0", + "moment-timezone": "^0.5.31", + "moment-timezone-data-webpack-plugin": "^1.3.0", + "mongodb": "^3.6.0", "mongomock": "^0.1.2", "node-cache": "^4.2.1", - "parse-duration": "^0.1.1", - "pem": "^1.14.3", - "pushover-notifications": "^1.2.1", + "parse-duration": "^0.1.3", + "pem": "^1.14.4", + "pushover-notifications": "^1.2.2", "random-token": "0.0.8", - "request": "^2.88.0", + "request": "^2.88.2", "semver": "^6.3.0", - "share2nightscout-bridge": "^0.2.1", - "shiro-trie": "^0.4.8", + "share2nightscout-bridge": "^0.2.4", + "shiro-trie": "^0.4.9", "simple-statistics": "^0.7.0", "socket.io": "~2.1.1", "style-loader": "^0.23.1", - "swagger-ui-dist": "^3.23.5", - "swagger-ui-express": "^4.1.2", + "swagger-ui-dist": "^3.32.1", + "swagger-ui-express": "^4.1.4", "terser": "^3.17.0", "traverse": "^0.6.6", - "uuid": "^3.3.2", - "webpack": "^4.39.2", - "webpack-cli": "^3.3.7" + "uuid": "^3.4.0", + "webpack": "^4.44.1", + "webpack-cli": "^3.3.12" }, "devDependencies": { - "babel-eslint": "^10.0.3", + "babel-eslint": "^10.1.0", "benv": "^3.3.0", - "env-cmd": "^8.0.2", - "eslint": "^6.2.1", + "codacy-coverage": "^3.4.0", + "csv-parse": "^4.12.0", + "env-cmd": "^10.1.0", + "eslint": "^6.8.0", "eslint-loader": "^2.2.1", - "istanbul": "^0.4.5", - "mocha": "^5.2.0", - "nodemon": "^1.19.1", + "mocha": "^8.1.1", + "nodemon": "^1.19.4", "nyc": "^14.1.1", "should": "^13.2.3", "supertest": "^3.4.2", - "terser-webpack-plugin": "^1.4.1", - "webpack-bundle-analyzer": "^3.4.1", + "terser-webpack-plugin": "^1.4.5", + "webpack-bundle-analyzer": "^3.8.0", "webpack-dev-middleware": "^3.7.2", - "webpack-hot-middleware": "^2.25.0" + "webpack-hot-middleware": "^2.25.0", + "xml2js": "^0.4.23" }, "browserslist": "> 0.25%, not dead" } diff --git a/server.js b/server.js index df99724747a..f4350bbbe00 100644 --- a/server.js +++ b/server.js @@ -54,6 +54,12 @@ require('./lib/server/bootevent')(env, language).boot(function booted (ctx) { return; } + ctx.bus.on('teardown', function serverTeardown () { + server.close(); + clearTimeout(sendStartupAllClearTimer); + ctx.store.client.close(); + }); + /////////////////////////////////////////////////// // setup socket io for data and message transmission /////////////////////////////////////////////////// @@ -68,7 +74,7 @@ require('./lib/server/bootevent')(env, language).boot(function booted (ctx) { }); //after startup if there are no alarms send all clear - setTimeout(function sendStartupAllClear () { + let sendStartupAllClearTimer = setTimeout(function sendStartupAllClear () { var alarm = ctx.notifications.findHighestAlarm(); if (!alarm) { ctx.bus.emit('notification', { diff --git a/static/css/drawer.css b/static/css/drawer.css index f9e6147fe2d..3e5e72542a4 100644 --- a/static/css/drawer.css +++ b/static/css/drawer.css @@ -207,34 +207,49 @@ h1, legend, } #toolbar { - background: url(/images/logo2.png) no-repeat 3px 3px #333; - border-bottom: 1px solid #999; - top: 0; - margin: 0; - height: 44px; text-shadow: 0 0 5px black; + display: flex; + height: 44px; + margin: 0 0 10px; + padding: 0 15px 0 40px; + position: relative; + align-items: center; + background: url(/images/logo2.png) no-repeat 3px center #333; + border-bottom: 1px solid #999; + justify-content: space-between; } #toolbar .customTitle { color: #ccc; font-size: 16px; - margin-top: 0; - margin-left: 42px; - padding-top: 10px; - padding-right: 150px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } + +#toolbar .button-close { + color: #404040; + text-align: center; + text-shadow: none; + height: 20px; + width: 20px; + padding: 5px; + position: absolute; + top: 50%; + right: 10px; + transform: translateY(-50%); + background: grey; + border: 2px solid #404040; + border-radius: 5px; +} + +#toolbar .button-close + #buttonbar { + margin-right: 40px; +} + #buttonbar { - margin-right: 50px; - padding-right: 15px; - height: 44px; opacity: 0.75; vertical-align: middle; - position: absolute; - right: 0; - z-index: 500; } #buttonbar a, @@ -244,14 +259,17 @@ h1, legend, height: 44px; line-height: 44px; } + #buttonbar .selected { color: red; } + #buttonbar a { - float: left; + float: right; text-decoration: none; width: 34px; } + #buttonbar i { padding-left: 12px; } diff --git a/static/css/main.css b/static/css/main.css index 7c2e25837cb..d6bee072d16 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -9,7 +9,21 @@ font-style: normal; } - [class^="icon-"]:before, [class*=" icon-"]:before { +/* + Icon font for additional plugin icons. + Please read assets/fonts/README.md about update process +*/ +@font-face { + font-family: 'pluginicons'; + /* Plugin Icons font files content (from WOFF and SVG icon files, base64 encoded) */ + src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAWAAAsAAAAABTQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDxIE8mNtYXAAAAFoAAAAVAAAAFQXVdKJZ2FzcAAAAbwAAAAIAAAACAAAABBnbHlmAAABxAAAAUgAAAFIFA4eR2hlYWQAAAMMAAAANgAAADYXVLrVaGhlYQAAA0QAAAAkAAAAJAdQA8ZobXR4AAADaAAAABQAAAAUCY4AAGxvY2EAAAN8AAAADAAAAAwAKAC4bWF4cAAAA4gAAAAgAAAAIAAJAFxuYW1lAAADqAAAAbYAAAG2DBt7mXBvc3QAAAVgAAAAIAAAACAAAwAAAAMCxwGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA6QEDwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADgAAAAKAAgAAgACAAEAIOkB//3//wAAAAAAIOkB//3//wAB/+MXAwADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAwAA/8ADjgPAABsAOgBZAAABIgcOAQcGFRQXHgEXFjMyNz4BNzY1NCcuAScmARUUFx4BFxYzMjc+ATc2PQEUBw4BBwYjIicuAScmNREVFBceARcWMzI3PgE3Nj0BFAcOAQcGIyInLgEnJjUBx15TU3skJCQke1NTXl5TU3wjJCQjfFNT/dskJHtTU15eU1N8IyQkI3xTU15eU1N7JCQkJHtTU15eU1N8IyQkI3xTU15eU1N7JCQDwBISPikpMC8pKj0SEhISPSopLzApKT4SEv6rqy8qKT4SEhISPikqL6svKik+EhISEj4pKi/+46owKSk+EhISEj4pKTCqLykqPhESEhE+KikvAAAAAAEAAAABAABgRbaTXw889QALBAAAAAAA2lO7LAAAAADaU7ssAAD/wAOOA8AAAAAIAAIAAAAAAAAAAQAAA8D/wAAABAAAAAAAA44AAQAAAAAAAAAAAAAAAAAAAAUEAAAAAAAAAAAAAAACAAAAA44AAAAAAAAACgAUAB4ApAABAAAABQBaAAMAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEACwAAAAEAAAAAAAIABwCEAAEAAAAAAAMACwBCAAEAAAAAAAQACwCZAAEAAAAAAAUACwAhAAEAAAAAAAYACwBjAAEAAAAAAAoAGgC6AAMAAQQJAAEAFgALAAMAAQQJAAIADgCLAAMAAQQJAAMAFgBNAAMAAQQJAAQAFgCkAAMAAQQJAAUAFgAsAAMAAQQJAAYAFgBuAAMAAQQJAAoANADUcGx1Z2luaWNvbnMAcABsAHUAZwBpAG4AaQBjAG8AbgBzVmVyc2lvbiAxLjAAVgBlAHIAcwBpAG8AbgAgADEALgAwcGx1Z2luaWNvbnMAcABsAHUAZwBpAG4AaQBjAG8AbgBzcGx1Z2luaWNvbnMAcABsAHUAZwBpAG4AaQBjAG8AbgBzUmVndWxhcgBSAGUAZwB1AGwAYQBycGx1Z2luaWNvbnMAcABsAHUAZwBpAG4AaQBjAG8AbgBzRm9udCBnZW5lcmF0ZWQgYnkgSWNvTW9vbi4ARgBvAG4AdAAgAGcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format('woff'), + url(data:application/font-svg;charset=utf-8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIiA+DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+DQo8bWV0YWRhdGE+R2VuZXJhdGVkIGJ5IEljb01vb248L21ldGFkYXRhPg0KPGRlZnM+DQo8Zm9udCBpZD0icGx1Z2luaWNvbnMiIGhvcml6LWFkdi14PSIxMDI0Ij4NCjxmb250LWZhY2UgdW5pdHMtcGVyLWVtPSIxMDI0IiBhc2NlbnQ9Ijk2MCIgZGVzY2VudD0iLTY0IiAvPg0KPG1pc3NpbmctZ2x5cGggaG9yaXotYWR2LXg9IjEwMjQiIC8+DQo8Z2x5cGggdW5pY29kZT0iJiN4MjA7IiBob3Jpei1hZHYteD0iNTEyIiBkPSIiIC8+DQo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwMTsiIGdseXBoLW5hbWU9ImRhdGFiYXNlIiBob3Jpei1hZHYteD0iOTEwIiBkPSJNNDU1LjExMSA5NjBjLTI1MS40NDkgMC00NTUuMTExLTEwMS44MzEtNDU1LjExMS0yMjcuNTU2czIwMy42NjItMjI3LjU1NiA0NTUuMTExLTIyNy41NTYgNDU1LjExMSAxMDEuODMxIDQ1NS4xMTEgMjI3LjU1Ni0yMDMuNjYyIDIyNy41NTYtNDU1LjExMSAyMjcuNTU2ek0wIDYxOC42Njd2LTE3MC42NjdjMC0xMjUuNzI0IDIwMy42NjItMjI3LjU1NiA0NTUuMTExLTIyNy41NTZzNDU1LjExMSAxMDEuODMxIDQ1NS4xMTEgMjI3LjU1NnYxNzAuNjY3YzAtMTI1LjcyNC0yMDMuNjYyLTIyNy41NTYtNDU1LjExMS0yMjcuNTU2cy00NTUuMTExIDEwMS44MzEtNDU1LjExMSAyMjcuNTU2ek0wIDMzNC4yMjJ2LTE3MC42NjdjMC0xMjUuNzI0IDIwMy42NjItMjI3LjU1NiA0NTUuMTExLTIyNy41NTZzNDU1LjExMSAxMDEuODMxIDQ1NS4xMTEgMjI3LjU1NnYxNzAuNjY3YzAtMTI1LjcyNC0yMDMuNjYyLTIyNy41NTYtNDU1LjExMS0yMjcuNTU2cy00NTUuMTExIDEwMS44MzEtNDU1LjExMSAyMjcuNTU2eiIgLz4NCjwvZm9udD48L2RlZnM+PC9zdmc+) format('svg'); + font-weight: normal; + font-style: normal; +} + + [class^="icon-"]:before, [class*=" icon-"]:before, + [class^="plugicon-"]:before, [class*=" plugicon-"]:before { font-family: "nsicons"; font-style: normal; font-weight: normal; @@ -43,6 +57,10 @@ /* Uncomment for 3D effect */ /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ } + +[class^="plugicon-"]:before, [class*=" plugicon-"]:before { + font-family: "pluginicons"; +} .icon-volume:before { content: '\e800'; } .icon-plus:before { content: '\e801'; } @@ -65,6 +83,9 @@ .icon-chart-line:before { content: '\f201'; } .icon-hourglass:before { content: '\f254'; } +/* Plugin Icons id-s (copy from generated icon style.css) */ +.plugicon-database:before { content: "\e901"; } + html, body { margin: 0; padding: 0; @@ -427,12 +448,30 @@ a, a:visited, a:link { display: none; } -#authorizationstatus a { +.toolbar-title { + text-align: left; + padding: 0 10px; +} + +.toolbar-title h2 { + margin: 0; +} + +.page-content { + padding: 10px; +} + +.authentication-status { + padding: 10px; + border-top: 1px solid #bdbdbd; +} + +.authentication-status a { color: #2196f3; text-decoration: underline; } -#authorizationstatus .small { +.authentication-status .small { font-size: 12px; } @@ -498,6 +537,11 @@ a, a:visited, a:link { } @media (max-width: 750px) { + .x.axis { + font-size: 2.5vmin !important; + } + + .bgStatus { width: 50%; padding: 0 0 20px 0; @@ -639,6 +683,10 @@ a, a:visited, a:link { #chartContainer { font-size: 14px; } + .y.axis { + font-size: 2.5vmin !important; + } + } @media (max-height: 600px) { @@ -651,6 +699,22 @@ a, a:visited, a:link { #container #toolbar { float: right; height: auto; + background: none; + border-bottom: none; + margin: 0px; + } + + #buttonbar { + margin-right: 0px; + padding-right: 15px; + margin-top: 15px; + height: 44px; + opacity: 0.75; + vertical-align: middle; + position: absolute; + right: 0; + z-index: 500; + width: 400px; } #toolbar .customTitle { diff --git a/static/css/report.css b/static/css/report.css index afe046f00d9..6994eb96b6c 100644 --- a/static/css/report.css +++ b/static/css/report.css @@ -24,26 +24,32 @@ body { #tabnav { text-align: left; - margin: 1em 0 1em 0; + margin: 1em 0 0; font: bold 11pt verdana, arial, sans-serif; border-bottom: 1px solid #6c6; list-style-type: none; - padding: 3px 10px 3px 10px; + padding: 0 0 0 15px; } -#tabnav li{ - display: inline; - padding: 3px 4px; - border: 1px solid #6c6; +#tabnav li { + display: inline-block; + padding: 10px 15px; + border-top: 1px solid #6c6; + border-right: 1px solid #6c6; + border-bottom: none; background-color: #cfc; color: #666; - margin-right: 0; + margin: 0 0 -1px 0; text-decoration: none; - border-bottom: none; +} + +#tabnav li:first-child { + border-left: 1px solid #6c6; } #tabnav .selected { background: #fff; + border-bottom: 1px solid #fff; } #tabnav li:hover { @@ -66,4 +72,41 @@ body { float: right; min-width: 150px; max-width: 400px; +} + +main { + padding: 15px; +} + +input[type=date], +input[type=text], +input[type=number], +select { + font: 13px verdana, arial, sans-serif; +} + +label { + display: inline-flex; + justify-content: flex-start; + align-items: center; + margin-right: 7px; +} + +#rp_to { + margin-right: 10px; +} + +.presetdates { + display: inline-block; + margin-right: 8px; +} + +#rp_show { + background-color: #cfc; + border: 1px solid #6c6; + color: #666; + padding: 10px; + font-weight: bold; + font-size: 12pt; + text-transform: uppercase; } \ No newline at end of file diff --git a/static/css/translations.css b/static/css/translations.css index 8408cf29f45..b1fae30e253 100644 --- a/static/css/translations.css +++ b/static/css/translations.css @@ -1,5 +1,16 @@ -td,th { +body { + color: black; + font-family: 'Open Sans', Helvetica, Arial, sans-serif; + background-color: white; +} + +th, +td { vertical-align: top; text-align: left; border: 1px solid } + +#translations { + padding: 15px; +} diff --git a/static/images/errorcat.jpg b/static/images/errorcat.jpg new file mode 100644 index 00000000000..15c1fb058b0 Binary files /dev/null and b/static/images/errorcat.jpg differ diff --git a/static/profile/js/profileeditor.js b/static/profile/js/profileeditor.js index c1443e5cade..77a1b205d7a 100644 --- a/static/profile/js/profileeditor.js +++ b/static/profile/js/profileeditor.js @@ -85,7 +85,7 @@ // Fetch data from mongo peStatus.hide().text(translate('Loading profile records ...')).fadeIn('slow'); - $.ajax('/api/v1/profile.json', { + $.ajax('/api/v1/profile.json?count=20', { headers: client.headers() , success: function (records) { if (!records.length) { @@ -681,12 +681,13 @@ // This is a crude way of preventing the user from changing the inputs whilst waiting. // If the user was able to make changes, they'd be lost when the done callback redraws anyway. $('#pe_form').hide(); - + var headers = client.headers(); + headers['Content-Type'] = 'application/json'; $.ajax({ method: 'PUT' , url: '/api/v1/profile/' - , data: adjustedRecord - , headers: client.headers() + , data: JSON.stringify(adjustedRecord) + , headers: headers }).done(function postSuccess (data, status) { console.info('profile saved', data); $('#pe_form').show(); // allow edits again diff --git a/static/report/js/predictions.js b/static/report/js/predictions.js deleted file mode 100644 index 336483a0dce..00000000000 --- a/static/report/js/predictions.js +++ /dev/null @@ -1,40 +0,0 @@ - -var predictedOffset = 0; - -function predictForward() { - predictedOffset += 5; - $("#rp_predictedOffset").html(predictedOffset); - $("#rp_show").click(); -} - -function predictMoreForward() { - predictedOffset += 30; - $("#rp_predictedOffset").html(predictedOffset); - $("#rp_show").click(); -} - -function predictBackward() { - predictedOffset -= 5; - $("#rp_predictedOffset").html(predictedOffset); - $("#rp_show").click(); -} - -function predictMoreBackward() { - predictedOffset -= 30; - $("#rp_predictedOffset").html(predictedOffset); - $("#rp_show").click(); -} - -function predictResetToZero() { - predictedOffset = 0; - $("#rp_predictedOffset").html(predictedOffset); - $("#rp_show").click(); -} - -$(document).on('change', '#rp_optionspredicted', function() { - if (this.checked) - $("#rp_predictedSettings").show(); - else - $("#rp_predictedSettings").hide(); - predictResetToZero(); -}); diff --git a/static/report/js/report.js b/static/report/js/report.js index f7b02ec44af..9e171bb8730 100644 --- a/static/report/js/report.js +++ b/static/report/js/report.js @@ -459,11 +459,14 @@ if (loadeddays === dayscount) { sorteddaystoshow.sort(); var from = sorteddaystoshow[0]; + var dFrom = sorteddaystoshow[0]; + var dTo = sorteddaystoshow[(sorteddaystoshow.length - 1)]; + if (options.order === report_plugins.consts.ORDER_NEWESTONTOP) { sorteddaystoshow.reverse(); } - loadProfileSwitch(from, function loadProfileSwitchCallback() { - loadProfiles(function loadProfilesCallback() { + loadProfileSwitch(dFrom, function loadProfileSwitchCallback() { + loadProfilesRange(dFrom, dTo, sorteddaystoshow.length, function loadProfilesCallback() { $('#info > b').html('' + translate('Rendering') + ' ...'); window.setTimeout(function () { showreports(options); @@ -651,7 +654,7 @@ if (!datastorage.profileSwitchTreatments) datastorage.profileSwitchTreatments = []; $('#info-' + day).html(''+translate('Loading treatments data of')+' '+day+' ...'); - var tquery = '?find[created_at][$gte]='+new Date(from).toISOString()+'&find[created_at][$lt]='+new Date(to).toISOString(); + var tquery = '?find[created_at][$gte]='+new Date(from).toISOString()+'&find[created_at][$lt]='+new Date(to).toISOString()+'&count=1000'; return $.ajax('/api/v1/treatments.json'+tquery, { headers: client.headers() , cache: false @@ -709,7 +712,7 @@ }); } - function loadProfileSwitch(from, callback) { + function loadProfileSwitch (from, callback) { $('#info > b').html(''+translate('Loading profile switch data') + ' ...'); var tquery = '?find[eventType]=Profile Switch' + '&find[created_at][$lte]=' + new Date(from).toISOString() + '&count=1'; $.ajax('/api/v1/treatments.json'+tquery, { @@ -743,6 +746,69 @@ }).done(callback); } + function loadProfilesRange (dateFrom, dateTo, dayCount, callback) { + $('#info > b').html('' + translate('Loading profile range') + ' ...'); + + $.when( + loadProfilesRangeCore(dateFrom, dateTo, dayCount), + loadProfilesRangePrevious(dateFrom), + loadProfilesRangeNext(dateTo) + ) + .done(callback) + .fail(function () { + datastorage.profiles = []; + }); + } + + function loadProfilesRangeCore (dateFrom, dateTo, dayCount) { + $('#info > b').html('' + translate('Loading core profiles') + ' ...'); + + //The results must be returned in descending order to work with key logic in routines such as getCurrentProfile + var tquery = '?find[startDate][$gte]=' + new Date(dateFrom).toISOString() + '&find[startDate][$lte]=' + new Date(dateTo).toISOString() + '&sort[startDate]=-1&count=1000'; + + return $.ajax('/api/v1/profiles' + tquery, { + headers: client.headers(), + async: false, + success: function (records) { + datastorage.profiles = records; + } + }); + } + + function loadProfilesRangePrevious (dateFrom) { + $('#info > b').html('' + translate('Loading previous profile') + ' ...'); + + //Find first one before the start date and add to datastorage.profiles + var tquery = '?find[startDate][$lt]=' + new Date(dateFrom).toISOString() + '&sort[startDate]=-1&count=1'; + + return $.ajax('/api/v1/profiles' + tquery, { + headers: client.headers(), + async: false, + success: function (records) { + records.forEach(function (r) { + datastorage.profiles.push(r); + }); + } + }); + } + + function loadProfilesRangeNext (dateTo) { + $('#info > b').html('' + translate('Loading next profile') + ' ...'); + + //Find first one after the end date and add to datastorage.profiles + var tquery = '?find[startDate][$gt]=' + new Date(dateTo).toISOString() + '&sort[startDate]=1&count=1'; + + return $.ajax('/api/v1/profiles' + tquery, { + headers: client.headers(), + async: false, + success: function (records) { + records.forEach(function (r) { + //must be inserted as top to maintain profiles being sorted by date in descending order + datastorage.profiles.unshift(r); + }); + } + }); + } function processData(data, day, options, callback) { if (daystoshow[day].treatmentsonly) { diff --git a/swagger.json b/swagger.json index dce7854e05b..d4f9cbde296 100755 --- a/swagger.json +++ b/swagger.json @@ -8,7 +8,7 @@ "info": { "title": "Nightscout API", "description": "Own your DData with the Nightscout API", - "version": "13.0.1", + "version": "14.0.7", "license": { "name": "AGPL 3", "url": "https://www.gnu.org/licenses/agpl.txt" diff --git a/swagger.yaml b/swagger.yaml index a08f701d7a5..98d89401be6 100755 --- a/swagger.yaml +++ b/swagger.yaml @@ -4,7 +4,7 @@ servers: info: title: Nightscout API description: Own your DData with the Nightscout API - version: 13.0.1 + version: 14.0.7 license: name: AGPL 3 url: 'https://www.gnu.org/licenses/agpl.txt' diff --git a/test b/test new file mode 100644 index 00000000000..e69de29bb2d diff --git a/testing/populate.js b/testing/populate.js index 34c307b7759..c4d9e1422a1 100644 --- a/testing/populate.js +++ b/testing/populate.js @@ -3,19 +3,22 @@ var mongodb = require('mongodb'); var env = require('./../env')(); -var util = require('./helpers/util'); +var util = require('./util'); main(); function main() { var MongoClient = mongodb.MongoClient; - MongoClient.connect(env.storageURI, function connected(err, db) { + MongoClient.connect(env.storageURI, { "useUnifiedTopology" : true, "useNewUrlParser" : true }, function connected(err, client) { console.log('Connecting to mongo...'); if (err) { console.log('Error occurred: ', err); throw err; } + + var db = client.db(); + populate_collection(db); }); } diff --git a/tests/admintools.test.js b/tests/admintools.test.js index 0b95acdf6c1..2fe6169f59a 100644 --- a/tests/admintools.test.js +++ b/tests/admintools.test.js @@ -66,7 +66,7 @@ var someData = { describe('admintools', function ( ) { var self = this; - this.timeout(30000); // TODO: see why this test takes longer on Travis to complete + this.timeout(45000); // TODO: see why this test takes longer on CI to complete before(function (done) { benv.setup(function() { diff --git a/tests/api.alexa.test.js b/tests/api.alexa.test.js new file mode 100644 index 00000000000..440050eb2cc --- /dev/null +++ b/tests/api.alexa.test.js @@ -0,0 +1,97 @@ +'use strict'; + +var request = require('supertest'); +var language = require('../lib/language')(); +const bodyParser = require('body-parser'); + +require('should'); + +describe('Alexa REST api', function ( ) { + this.timeout(10000); + const apiRoot = require('../lib/api/root'); + const api = require('../lib/api/'); + before(function (done) { + var env = require('../env')( ); + env.settings.enable = ['alexa']; + env.settings.authDefaultRoles = 'readable'; + env.api_secret = 'this is my long pass phrase'; + this.wares = require('../lib/middleware/')(env); + this.app = require('express')( ); + this.app.enable('api'); + var self = this; + require('../lib/server/bootevent')(env, language).boot(function booted (ctx) { + self.app.use('/api', bodyParser({ + limit: 1048576 * 50 + }), apiRoot(env, ctx)); + + self.app.use('/api/v1', bodyParser({ + limit: 1048576 * 50 + }), api(env, ctx)); + done( ); + }); + }); + + it('Launch Request', function (done) { + request(this.app) + .post('/api/v1/alexa') + .send({ + "request": { + "type": "LaunchRequest", + "locale": "en-US" + } + }) + .expect(200) + .end(function (err, res) { + if (err) return done(err); + + const launchText = 'What would you like to check on Nightscout?'; + + res.body.response.outputSpeech.text.should.equal(launchText); + res.body.response.reprompt.outputSpeech.text.should.equal(launchText); + res.body.response.shouldEndSession.should.equal(false); + done( ); + }); + }); + + it('Launch Request With Intent', function (done) { + request(this.app) + .post('/api/v1/alexa') + .send({ + "request": { + "type": "LaunchRequest", + "locale": "en-US", + "intent": { + "name": "UNKNOWN" + } + } + }) + .expect(200) + .end(function (err, res) { + if (err) return done(err); + + const unknownIntentText = 'I\'m sorry, I don\'t know what you\'re asking for.'; + + res.body.response.outputSpeech.text.should.equal(unknownIntentText); + res.body.response.shouldEndSession.should.equal(true); + done( ); + }); + }); + + it('Session Ended', function (done) { + request(this.app) + .post('/api/v1/alexa') + .send({ + "request": { + "type": "SessionEndedRequest", + "locale": "en-US" + } + }) + .expect(200) + .end(function (err) { + if (err) return done(err); + + done( ); + }); + }); +}); + diff --git a/tests/api.entries.test.js b/tests/api.entries.test.js index 098b5c45663..6c0c3f14e45 100644 --- a/tests/api.entries.test.js +++ b/tests/api.entries.test.js @@ -307,4 +307,66 @@ describe('Entries REST api', function ( ) { }); }); + it('post multipole entries, query, delete, verify gone', function (done) { + // insert a glucose entry - needs to be unique from example data + console.log('Inserting glucose entry') + request(self.app) + .post('/entries/') + .set('api-secret', self.env.api_secret || '') + .send([{ + "type": "sgv", "sgv": "199", "dateString": "2014-07-20T00:44:15.000-07:00" + , "date": 1405791855000, "device": "dexcom", "direction": "NOT COMPUTABLE" + }, { + "type": "sgv", "sgv": "200", "dateString": "2014-07-20T00:44:15.001-07:00" + , "date": 1405791855001, "device": "dexcom", "direction": "NOT COMPUTABLE" + }]) + .expect(200) + .end(function (err) { + if (err) { + done(err); + } else { + // make sure treatment was inserted successfully + console.log('Ensuring glucose entry was inserted successfully'); + request(self.app) + .get('/entries.json?find[dateString][$gte]=2014-07-20&count=100') + .set('api-secret', self.env.api_secret || '') + .expect(200) + .expect(function (response) { + var entry = response.body[0]; + response.body.length.should.equal(2); + entry.sgv.should.equal('200'); + entry.utcOffset.should.equal(-420); + }) + .end(function (err) { + if (err) { + done(err); + } else { + // delete the glucose entry + console.log('Deleting test glucose entry'); + request(self.app) + .delete('/entries.json?find[dateString][$gte]=2014-07-20&count=100') + .set('api-secret', self.env.api_secret || '') + .expect(200) + .end(function (err) { + if (err) { + done(err); + } else { + // make sure it was deleted + console.log('Testing if glucose entries were deleted'); + request(self.app) + .get('/entries.json?find[dateString][$gte]=2014-07-20&count=100') + .set('api-secret', self.env.api_secret || '') + .expect(200) + .expect(function (response) { + response.body.length.should.equal(0); + }) + .end(done); + } + }); + } + }); + } + }); + }); + }); diff --git a/tests/api.treatments.test.js b/tests/api.treatments.test.js index 4ba3739f4c0..2b1d3ee877d 100644 --- a/tests/api.treatments.test.js +++ b/tests/api.treatments.test.js @@ -34,10 +34,11 @@ describe('Treatment API', function ( ) { it('post single treatments', function (done) { self.ctx.treatments().remove({ }, function ( ) { + var now = (new Date()).toISOString(); request(self.app) .post('/api/treatments/') .set('api-secret', self.env.api_secret || '') - .send({eventType: 'Meal Bolus', carbs: '30', insulin: '2.00', preBolus: '15', glucose: 100, glucoseType: 'Finger', units: 'mg/dl'}) + .send({eventType: 'Meal Bolus', created_at: now, carbs: '30', insulin: '2.00', preBolus: '15', glucose: 100, glucoseType: 'Finger', units: 'mg/dl'}) .expect(200) .end(function (err) { if (err) { @@ -61,6 +62,25 @@ describe('Treatment API', function ( ) { }); }); + /* + it('saving entry without created_at should fail', function (done) { + + self.ctx.treatments().remove({ }, function ( ) { + request(self.app) + .post('/api/treatments/') + .set('api-secret', self.env.api_secret || '') + .send({eventType: 'Meal Bolus', carbs: '30', insulin: '2.00', preBolus: '15', glucose: 100, glucoseType: 'Finger', units: 'mg/dl'}) + .expect(422) + .end(function (err) { + if (err) { + done(err); + } else { + done(); + } + }); + }); + }); +*/ it('post single treatments in zoned time format', function (done) { @@ -101,12 +121,13 @@ describe('Treatment API', function ( ) { it('post a treatment array', function (done) { self.ctx.treatments().remove({ }, function ( ) { + var now = (new Date()).toISOString(); request(self.app) .post('/api/treatments/') .set('api-secret', self.env.api_secret || '') .send([ - {eventType: 'BG Check', glucose: 100, preBolus: '0', glucoseType: 'Finger', units: 'mg/dl', notes: ''} - , {eventType: 'Meal Bolus', carbs: '30', insulin: '2.00', preBolus: '15', glucose: 100, glucoseType: 'Finger', units: 'mg/dl'} + {eventType: 'BG Check', created_at: now, glucose: 100, preBolus: '0', glucoseType: 'Finger', units: 'mg/dl', notes: ''} + , {eventType: 'Meal Bolus', created_at: now, carbs: '30', insulin: '2.00', preBolus: '15', glucose: 100, glucoseType: 'Finger', units: 'mg/dl'} ]) .expect(200) .end(function (err) { @@ -168,10 +189,11 @@ describe('Treatment API', function ( ) { it('post a treatment, query, delete, verify gone', function (done) { // insert a treatment - needs to be unique from example data console.log('Inserting treatment entry'); + var now = (new Date()).toISOString(); request(self.app) .post('/api/treatments/') .set('api-secret', self.env.api_secret || '') - .send({eventType: 'Meal Bolus', carbs: '99', insulin: '2.00', preBolus: '15', glucose: 100, glucoseType: 'Finger', units: 'mg/dl'}) + .send({eventType: 'Meal Bolus', created_at: now, carbs: '99', insulin: '2.00', preBolus: '15', glucose: 100, glucoseType: 'Finger', units: 'mg/dl'}) .expect(200) .end(function (err) { if (err) { diff --git a/tests/api3.basic.test.js b/tests/api3.basic.test.js index 8e51b343585..d13b8628562 100644 --- a/tests/api3.basic.test.js +++ b/tests/api3.basic.test.js @@ -19,16 +19,7 @@ describe('Basic REST API3', function() { after(function after () { - self.instance.server.close(); - }); - - - it('GET /swagger', async () => { - let res = await request(self.app) - .get('/api/v3/swagger.yaml') - .expect(200); - - res.header['content-length'].should.be.above(0); + self.instance.ctx.bus.teardown(); }); diff --git a/tests/api3.create.test.js b/tests/api3.create.test.js index cbd17a3e826..5ea3ab1a869 100644 --- a/tests/api3.create.test.js +++ b/tests/api3.create.test.js @@ -16,7 +16,7 @@ describe('API3 CREATE', function() { self.validDoc = { date: (new Date()).getTime(), app: testConst.TEST_APP, - device: testConst.TEST_DEVICE, + device: testConst.TEST_DEVICE + ' API3 CREATE', eventType: 'Correction Bolus', insulin: 0.3 }; @@ -72,7 +72,7 @@ describe('API3 CREATE', function() { after(() => { - self.instance.server.close(); + self.instance.ctx.bus.teardown(); }); diff --git a/tests/api3.delete.test.js b/tests/api3.delete.test.js index 203d32edce8..7cee15410a0 100644 --- a/tests/api3.delete.test.js +++ b/tests/api3.delete.test.js @@ -28,7 +28,7 @@ describe('API3 UPDATE', function() { after(() => { - self.instance.server.close(); + self.instance.ctx.bus.teardown(); }); diff --git a/tests/api3.generic.workflow.test.js b/tests/api3.generic.workflow.test.js index acebe39555a..7cfbc53f618 100644 --- a/tests/api3.generic.workflow.test.js +++ b/tests/api3.generic.workflow.test.js @@ -9,10 +9,8 @@ describe('Generic REST API3', function() { , instance = require('./fixtures/api3/instance') , authSubject = require('./fixtures/api3/authSubject') , opTools = require('../lib/api3/shared/operationTools') - , utils = require('./fixtures/api3/utils') ; - utils.randomString('32', 'aA#'); // let's have a brand new identifier for your testing document self.urlLastModified = '/api/v3/lastModified'; self.historyTimestamp = 0; @@ -21,7 +19,7 @@ describe('Generic REST API3', function() { insulin: 1, date: (new Date()).getTime(), app: testConst.TEST_APP, - device: testConst.TEST_DEVICE + device: testConst.TEST_DEVICE + ' Generic REST API3' }; self.identifier = opTools.calculateIdentifier(self.docOriginal); self.docOriginal.identifier = self.identifier; @@ -46,7 +44,7 @@ describe('Generic REST API3', function() { after(() => { - self.instance.server.close(); + self.instance.ctx.bus.teardown(); }); diff --git a/tests/api3.patch.test.js b/tests/api3.patch.test.js index 38850b46ad5..36dccc94bfa 100644 --- a/tests/api3.patch.test.js +++ b/tests/api3.patch.test.js @@ -15,7 +15,7 @@ describe('API3 PATCH', function() { date: (new Date()).getTime(), utcOffset: -180, app: testConst.TEST_APP, - device: testConst.TEST_DEVICE, + device: testConst.TEST_DEVICE + ' API3 PATCH', eventType: 'Correction Bolus', insulin: 0.3 }; @@ -51,7 +51,7 @@ describe('API3 PATCH', function() { after(() => { - self.instance.server.close(); + self.instance.ctx.bus.teardown(); }); diff --git a/tests/api3.read.test.js b/tests/api3.read.test.js index b18b0225bb9..d9f73ebf13a 100644 --- a/tests/api3.read.test.js +++ b/tests/api3.read.test.js @@ -15,7 +15,7 @@ describe('API3 READ', function() { self.validDoc = { date: (new Date()).getTime(), app: testConst.TEST_APP, - device: testConst.TEST_DEVICE, + device: testConst.TEST_DEVICE + ' API3 READ', uploaderBattery: 58 }; self.validDoc.identifier = opTools.calculateIdentifier(self.validDoc); @@ -38,7 +38,7 @@ describe('API3 READ', function() { after(() => { - self.instance.server.close(); + self.instance.ctx.bus.teardown(); }); diff --git a/tests/api3.renderer.test.js b/tests/api3.renderer.test.js new file mode 100644 index 00000000000..70401897025 --- /dev/null +++ b/tests/api3.renderer.test.js @@ -0,0 +1,268 @@ +/* eslint require-atomic-updates: 0 */ +'use strict'; + +require('should'); + +describe('API3 output renderers', function() { + const self = this + , testConst = require('./fixtures/api3/const.json') + , instance = require('./fixtures/api3/instance') + , authSubject = require('./fixtures/api3/authSubject') + , opTools = require('../lib/api3/shared/operationTools') + , _ = require('lodash') + , xml2js = require('xml2js') + , csvParse = require('csv-parse/lib/sync') + ; + + self.historyFrom = (new Date()).getTime() - 1000; // starting timestamp for HISTORY operations + + self.doc1 = testConst.SAMPLE_ENTRIES[0]; + self.doc1.date = (new Date()).getTime() - (5 * 60 * 1000); + self.doc1.identifier = opTools.calculateIdentifier(self.doc1); + + self.doc2 = testConst.SAMPLE_ENTRIES[1]; + self.doc2.date = (new Date()).getTime(); + self.doc2.identifier = opTools.calculateIdentifier(self.doc2); + + self.xmlParser = new xml2js.Parser({ + explicitArray: false + }); + + self.csvParserOptions = { + columns: true, + skip_empty_lines: true + }; + + self.timeout(15000); + + + before(async () => { + self.instance = await instance.create({}); + + self.app = self.instance.app; + self.env = self.instance.env; + self.url = '/api/v3/entries'; + + let authResult = await authSubject(self.instance.ctx.authorization.storage); + + self.subject = authResult.subject; + self.token = authResult.token; + }); + + + after(() => { + self.instance.server.close(); + }); + + + /** + * Checks if all properties from obj1 are string identical in obj2 + * (comparison of properties is made using toString()) + * @param {Object} obj1 + * @param {Object} obj2 + */ + self.checkProps = function checkProps (obj1, obj2) { + for (let propName in obj1) { + obj1[propName].toString().should.eql(obj2[propName].toString()); + } + }; + + + /** + * Checks if all objects from arrModel exist in arr + * (with string identical properties) + * @param arrModel + * @param arr + */ + self.checkItems = function checkItems (arrModel, arr) { + for (let itemModel of arrModel) { + const item = _.find(arr, (doc) => doc.identifier === itemModel.identifier); + item.should.not.be.empty(); + self.checkProps(itemModel, item); + } + }; + + + /** + * Checks if given text is valid XML. + * Next checks if all objects from arrModel exist in parsed array + * (with string identical properties) + * @param arrModel + * @param xmlText + * @returns {Promise} + */ + self.checkXmlItems = async function checkXmlItems (arrModel, xmlText) { + xmlText.should.startWith(''); + + const xml = await self.xmlParser.parseStringPromise(xmlText); + xml.items.should.not.be.empty(); + let items = xml.items.item; + items.should.be.Array(); + items.length.should.be.aboveOrEqual(arrModel.length); + + self.checkItems(arrModel, items); + }; + + + /** + * Checks if given text is valid CSV. + * Next checks if all objects from arrModel exist in parsed array + * (with string identical properties) + * @param arrModel + * @param csvText + * @returns {Promise} + */ + self.checkCsvItems = async function checkXmlItems (arrModel, csvText) { + csvText.should.not.be.empty(); + + const items = csvParse(csvText, self.csvParserOptions); + items.should.be.Array(); + items.length.should.be.aboveOrEqual(arrModel.length); + + self.checkItems(arrModel, items); + }; + + + it('should create 2 mock documents', async () => { + + async function createDoc (doc) { + + let res = await self.instance.post(`${self.url}?token=${self.token.create}`) + .send(doc) + .expect(201); + + res.body.should.be.empty(); + + res = await self.instance.get(`${self.url}/${doc.identifier}?token=${self.token.read}`) + .expect(200); + return res.body; + } + + self.doc1json = await createDoc(self.doc1); + self.doc2json = await createDoc(self.doc2); + }); + + + it('READ/SEARCH/HISTORY should not accept unsupported content type', async () => { + + async function check406 (request) { + const res = await request + .expect(406); + res.body.message.should.eql('Unsupported output format requested'); + } + + await check406(self.instance.get(`${self.url}/${self.doc1.identifier}.ttf?fields=_all&token=${self.token.read}`)); + await check406(self.instance.get(`${self.url}/${self.doc1.identifier}?fields=_all&token=${self.token.read}`) + .set('Accept', 'font/ttf')); + + await check406(self.instance.get(`${self.url}.ttf?fields=_all&token=${self.token.read}`)); + await check406(self.instance.get(`${self.url}?fields=_all&token=${self.token.read}`) + .set('Accept', 'font/ttf')); + + await check406(self.instance.get(`${self.url}/history/${self.doc1.date}.ttf?token=${self.token.read}`)); + await check406(self.instance.get(`${self.url}/history/${self.doc1.date}?token=${self.token.read}`) + .set('Accept', 'font/ttf')); + }); + + + it('READ should accept xml content type', async () => { + let res = await self.instance.get(`${self.url}/${self.doc1.identifier}.xml?fields=_all&token=${self.token.read}`) + .expect(200); + + res.text.should.startWith(''); + + const xml = await self.xmlParser.parseStringPromise(res.text); + xml.item.should.not.be.empty(); + self.checkProps(self.doc1, xml.item); + + let res2 = await self.instance.get(`${self.url}/${self.doc1.identifier}?fields=_all&token=${self.token.read}`) + .set('Accept', 'application/xml') + .expect(200); + + res.text.should.eql(res2.text); + }); + + + it('READ should accept csv content type', async () => { + let res = await self.instance.get(`${self.url}/${self.doc1.identifier}.csv?fields=_all&token=${self.token.read}`) + .expect(200); + + await self.checkCsvItems([self.doc1], res.text); + + let res2 = await self.instance.get(`${self.url}/${self.doc1.identifier}?fields=_all&token=${self.token.read}`) + .set('Accept', 'text/csv') + .expect(200); + + res.text.should.eql(res2.text); + }); + + + it('SEARCH should accept xml content type', async () => { + let res = await self.instance.get(`${self.url}.xml?token=${self.token.read}&date$gte=${self.doc1.date}`) + .expect(200); + + await self.checkXmlItems([self.doc1, self.doc2], res.text); + + let res2 = await self.instance.get(`${self.url}?token=${self.token.read}&date$gte=${self.doc1.date}`) + .set('Accept', 'application/xml') + .expect(200); + + res.text.should.be.eql(res2.text); + }); + + + it('SEARCH should accept csv content type', async () => { + let res = await self.instance.get(`${self.url}.csv?token=${self.token.read}&date$gte=${self.doc1.date}`) + .expect(200); + + await self.checkCsvItems([self.doc1, self.doc2], res.text); + + let res2 = await self.instance.get(`${self.url}?token=${self.token.read}&date$gte=${self.doc1.date}`) + .set('Accept', 'text/csv') + .expect(200); + + res.text.should.be.eql(res2.text); + }); + + + it('HISTORY should accept xml content type', async () => { + let res = await self.instance.get(`${self.url}/history/${self.historyFrom}.xml?token=${self.token.read}`) + .expect(200); + + await self.checkXmlItems([self.doc1, self.doc2], res.text); + + let res2 = await self.instance.get(`${self.url}/history/${self.historyFrom}?token=${self.token.read}`) + .set('Accept', 'application/xml') + .expect(200); + + res.text.should.be.eql(res2.text); + }); + + + it('HISTORY should accept csv content type', async () => { + let res = await self.instance.get(`${self.url}/history/${self.historyFrom}.csv?token=${self.token.read}`) + .expect(200); + + await self.checkCsvItems([self.doc1, self.doc2], res.text); + + let res2 = await self.instance.get(`${self.url}/history/${self.historyFrom}?token=${self.token.read}`) + .set('Accept', 'text/csv') + .expect(200); + + res.text.should.be.eql(res2.text); + }); + + + it('should remove mock documents', async () => { + + async function deleteDoc (identifier) { + await self.instance.delete(`${self.url}/${identifier}?token=${self.token.delete}`) + .query({ 'permanent': 'true' }) + .expect(204); + } + + await deleteDoc(self.doc1.identifier); + await deleteDoc(self.doc2.identifier); + }); +}); + diff --git a/tests/api3.search.test.js b/tests/api3.search.test.js index dae0ebaaf34..af109a18451 100644 --- a/tests/api3.search.test.js +++ b/tests/api3.search.test.js @@ -65,7 +65,7 @@ describe('API3 SEARCH', function() { after(() => { - self.instance.server.close(); + self.instance.ctx.bus.teardown(); }); diff --git a/tests/api3.security.test.js b/tests/api3.security.test.js index 4cdc8e22b21..0e88e9fae19 100644 --- a/tests/api3.security.test.js +++ b/tests/api3.security.test.js @@ -7,7 +7,7 @@ const request = require('supertest') , moment = require('moment') ; require('should'); - + describe('Security of REST API3', function() { const self = this , instance = require('./fixtures/api3/instance') @@ -26,10 +26,10 @@ describe('Security of REST API3', function() { self.token = authResult.token; }); - + after(() => { - self.http.server.close(); - self.https.server.close(); + self.http.ctx.bus.teardown(); + self.https.ctx.bus.teardown(); }); diff --git a/tests/api3.socket.test.js b/tests/api3.socket.test.js index 5c2a5cf6461..9560c200c65 100644 --- a/tests/api3.socket.test.js +++ b/tests/api3.socket.test.js @@ -49,7 +49,7 @@ describe('Socket.IO in REST API3', function() { if(self.instance && self.instance.clientSocket && self.instance.clientSocket.connected) { self.instance.clientSocket.disconnect(); } - self.instance.server.close(); + self.instance.ctx.bus.teardown(); }); diff --git a/tests/api3.update.test.js b/tests/api3.update.test.js index 403aadb022e..481827b05d6 100644 --- a/tests/api3.update.test.js +++ b/tests/api3.update.test.js @@ -17,6 +17,7 @@ describe('API3 UPDATE', function() { date: (new Date()).getTime(), utcOffset: -180, app: testConst.TEST_APP, + device: testConst.TEST_DEVICE + ' API3 UPDATE', eventType: 'Correction Bolus', insulin: 0.3 }; @@ -51,7 +52,7 @@ describe('API3 UPDATE', function() { after(() => { - self.instance.server.close(); + self.instance.ctx.bus.teardown(); }); diff --git a/tests/client.renderer.test.js b/tests/client.renderer.test.js index ca81e7d99e8..5dc707ab2b1 100644 --- a/tests/client.renderer.test.js +++ b/tests/client.renderer.test.js @@ -64,7 +64,10 @@ describe('renderer', () => { describe(`data.mills ${extent.mills} and chart().brush.extent() times ${extent.times}`, () => { it(extent.expectation, () => { - renderer(mockClient, {}).highlightBrushPoints(mockData).should.equal(extent.expectedOpacity); + var selectedRange = mockClient.chart.createAdjustedRange(); + var from = selectedRange[0].getTime(); + var to = selectedRange[1].getTime(); + renderer(mockClient, {}).highlightBrushPoints(mockData, from, to).should.equal(extent.expectedOpacity); }); }); }); diff --git a/tests/dbsize.test.js b/tests/dbsize.test.js new file mode 100644 index 00000000000..ce95f8652c0 --- /dev/null +++ b/tests/dbsize.test.js @@ -0,0 +1,315 @@ +'use strict'; + +require('should'); + +describe('Database Size', function() { + + var dataInRange = { dbstats: { dataSize: 1024 * 1024 * 137, indexSize: 1024 * 1024 * 48, fileSize: 1024 * 1024 * 256 } }; + var dataWarn = { dbstats: { dataSize: 1024 * 1024 * 250, indexSize: 1024 * 1024 * 100, fileSize: 1024 * 1024 * 360 } }; + var dataUrgent = { dbstats: { dataSize: 1024 * 1024 * 300, indexSize: 1024 * 1024 * 150, fileSize: 1024 * 1024 * 496 } }; + + var env = require('../env')(); + + it('display database size in range', function(done) { + var sandbox = require('../lib/sandbox')(); + var ctx = { + settings: {} + , language: require('../lib/language')() + }; + ctx.language.set('en'); + ctx.levels = require('../lib/levels'); + + var sbx = sandbox.clientInit(ctx, Date.now(), dataInRange); + + sbx.offerProperty = function mockedOfferProperty (name, setter) { + name.should.equal('dbsize'); + var result = setter(); + result.display.should.equal('37%'); + result.status.should.equal('current'); + done(); + }; + + var dbsize = require('../lib/plugins/dbsize')(ctx); + dbsize.setProperties(sbx); + + }); + + // ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~. + + it('display database size warning', function(done) { + var sandbox = require('../lib/sandbox')(); + var ctx = { + settings: {} + , language: require('../lib/language')() + }; + ctx.language.set('en'); + ctx.levels = require('../lib/levels'); + + var sbx = sandbox.clientInit(ctx, Date.now(), dataWarn); + + sbx.offerProperty = function mockedOfferProperty (name, setter) { + name.should.equal('dbsize'); + var result = setter(); + result.display.should.equal('70%'); + result.status.should.equal('warn'); + done(); + }; + + var dbsize = require('../lib/plugins/dbsize')(ctx); + + dbsize.setProperties(sbx); + + }); + + // ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~. + + it('display database size urgent', function(done) { + var sandbox = require('../lib/sandbox')(); + var ctx = { + settings: {} + , language: require('../lib/language')() + }; + ctx.language.set('en'); + ctx.levels = require('../lib/levels'); + + var sbx = sandbox.clientInit(ctx, Date.now(), dataUrgent); + + sbx.offerProperty = function mockedOfferProperty (name, setter) { + name.should.equal('dbsize'); + var result = setter(); + result.display.should.equal('90%'); + result.status.should.equal('urgent'); + done(); + }; + + var dbsize = require('../lib/plugins/dbsize')(ctx); + dbsize.setProperties(sbx); + + }); + + // ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~. + + it('display database size warning notiffication', function(done) { + var sandbox = require('../lib/sandbox')(); + var ctx = { + settings: {} + , language: require('../lib/language')() + , notifications: require('../lib/notifications')(env, ctx) + }; + ctx.notifications.initRequests(); + ctx.language.set('en'); + ctx.levels = require('../lib/levels'); + + var sbx = sandbox.clientInit(ctx, Date.now(), dataWarn); + sbx.extendedSettings = { 'enableAlerts': 'TRUE' }; + + var dbsize = require('../lib/plugins/dbsize')(ctx); + + dbsize.setProperties(sbx); + dbsize.checkNotifications(sbx); + + var notif = ctx.notifications.findHighestAlarm('Database Size'); + notif.level.should.equal(ctx.levels.WARN); + notif.title.should.equal('Warning Database Size near its limits!'); + notif.message.should.equal('Database size is 350 MiB out of 496 MiB. Please backup and clean up database!'); + done(); + }); + + // ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~. + + it('display database size urgent notiffication', function(done) { + var sandbox = require('../lib/sandbox')(); + var ctx = { + settings: {} + , language: require('../lib/language')() + , notifications: require('../lib/notifications')(env, ctx) + }; + ctx.notifications.initRequests(); + ctx.language.set('en'); + ctx.levels = require('../lib/levels'); + + var sbx = sandbox.clientInit(ctx, Date.now(), dataUrgent); + sbx.extendedSettings = { 'enableAlerts': 'TRUE' }; + + var dbsize = require('../lib/plugins/dbsize')(ctx); + + dbsize.setProperties(sbx); + dbsize.checkNotifications(sbx); + + var notif = ctx.notifications.findHighestAlarm('Database Size'); + notif.level.should.equal(ctx.levels.URGENT); + notif.title.should.equal('Urgent Database Size near its limits!'); + notif.message.should.equal('Database size is 450 MiB out of 496 MiB. Please backup and clean up database!'); + done(); + }); + + // ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~. + + it('set a pill to the database size in percent', function(done) { + var ctx = { + settings: {} + , pluginBase: { + updatePillText: function mockedUpdatePillText (plugin, options) { + options.value.should.equal('90%'); + options.labelClass.should.equal('plugicon-database'); + options.pillClass.should.equal('urgent'); + done(); + } + } + , language: require('../lib/language')() + }; + ctx.language.set('en'); + + var sandbox = require('../lib/sandbox')(); + var sbx = sandbox.clientInit(ctx, Date.now(), dataUrgent); + var dbsize = require('../lib/plugins/dbsize')(ctx); + dbsize.setProperties(sbx); + dbsize.updateVisualisation(sbx); + + }); + + // ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~. + + it('set a pill to the database size in MiB', function(done) { + var ctx = { + settings: { + extendedSettings: { + empty: false + , dbsize: { + inMib: true + } + } + } + , pluginBase: { + updatePillText: function mockedUpdatePillText (plugin, options) { + options.value.should.equal('450MiB'); + options.labelClass.should.equal('plugicon-database'); + options.pillClass.should.equal('urgent'); + done(); + } + } + , language: require('../lib/language')() + }; + ctx.language.set('en'); + + var sandbox = require('../lib/sandbox')(); + var sbx = sandbox.clientInit(ctx, Date.now(), dataUrgent); + var dbsize = require('../lib/plugins/dbsize')(ctx); + dbsize.setProperties(sbx.withExtendedSettings(dbsize)); + dbsize.updateVisualisation(sbx); + + }); + + // ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~. + + it('configure warn level percentage', function(done) { + + var ctx = { + settings: { + extendedSettings: { + empty: false + , dbsize: { + warnPercentage: 30 + } + } + } + , pluginBase: { + updatePillText: function mockedUpdatePillText (plugin, options) { + options.value.should.equal('37%'); + options.pillClass.should.equal('warn'); + done(); + } + } + , language: require('../lib/language')() + }; + ctx.language.set('en'); + + var sandbox = require('../lib/sandbox')(); + var sbx = sandbox.clientInit(ctx, Date.now(), dataInRange); + var dbsize = require('../lib/plugins/dbsize')(ctx); + dbsize.setProperties(sbx.withExtendedSettings(dbsize)); + dbsize.updateVisualisation(sbx); + }); + + // ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~. + + it('configure urgent level percentage', function(done) { + + var ctx = { + settings: { + extendedSettings: { + empty: false + , dbsize: { + warnPercentage: 30 + , urgentPercentage: 36 + } + } + } + , pluginBase: { + updatePillText: function mockedUpdatePillText (plugin, options) { + options.value.should.equal('37%'); + options.pillClass.should.equal('urgent'); + done(); + } + } + , language: require('../lib/language')() + }; + ctx.language.set('en'); + + var sandbox = require('../lib/sandbox')(); + var sbx = sandbox.clientInit(ctx, Date.now(), dataInRange); + var dbsize = require('../lib/plugins/dbsize')(ctx); + dbsize.setProperties(sbx.withExtendedSettings(dbsize)); + dbsize.updateVisualisation(sbx); + }); + + // ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~. + + it('hide the pill if there is no info regarding database size', function(done) { + var ctx = { + settings: {} + , pluginBase: { + updatePillText: function mockedUpdatePillText (plugin, options) { + options.hide.should.equal(true); + done(); + } + } + , language: require('../lib/language')() + }; + ctx.language.set('en'); + + var sandbox = require('../lib/sandbox')(); + var sbx = sandbox.clientInit(ctx, Date.now(), {}); + var dbsize = require('../lib/plugins/dbsize')(ctx); + dbsize.setProperties(sbx); + dbsize.updateVisualisation(sbx); + }); + + // ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~. + + it('should handle virtAsst requests', function(done) { + + var ctx = { + settings: {} + , language: require('../lib/language')() + }; + ctx.language.set('en'); + + var sandbox = require('../lib/sandbox')(); + var sbx = sandbox.clientInit(ctx, Date.now(), dataUrgent); + var dbsize = require('../lib/plugins/dbsize')(ctx); + dbsize.setProperties(sbx); + + dbsize.virtAsst.intentHandlers.length.should.equal(1); + + dbsize.virtAsst.intentHandlers[0].intentHandler(function next (title, response) { + title.should.equal('Database file size'); + response.should.equal('450 MiB. That is 90% of available database space.'); + + done(); + + }, [], sbx); + + }); + +}); diff --git a/tests/env.test.js b/tests/env.test.js index 90313dfd39f..7990b470692 100644 --- a/tests/env.test.js +++ b/tests/env.test.js @@ -2,7 +2,7 @@ require('should'); -describe('env', function ( ) { +describe('env', function () { it( 'show the right plugins', function () { process.env.SHOW_PLUGINS = 'iob'; process.env.ENABLE = 'iob cob'; @@ -68,4 +68,88 @@ describe('env', function ( ) { env.insecureUseHttp.should.be.false(); // not defined should be false env.secureHstsHeader.should.be.true(); }); + + describe( 'DISPLAY_UNITS', function () { + const MMOL = 'mmol'; + const MGDL = 'mg/dl'; + describe ( 'mmol', function () { + it( 'mmol => mmol', function () { + process.env.DISPLAY_UNITS = MMOL; + var env = require( '../env' )(); + env.settings.units.should.equal( MMOL ); + delete process.env.DISPLAY_UNITS; + } ); + + it( 'mmol/l => mmol', function () { + process.env.DISPLAY_UNITS = 'mmol/l'; + var env = require( '../env' )(); + env.settings.units.should.equal( MMOL ); + delete process.env.DISPLAY_UNITS; + } ); + + it( 'mmol/L => mmol', function () { + process.env.DISPLAY_UNITS = 'mmol/L'; + var env = require( '../env' )(); + env.settings.units.should.equal( MMOL ); + delete process.env.DISPLAY_UNITS; + } ); + + it( 'MMOL => mmol', function () { + process.env.DISPLAY_UNITS = 'MMOL'; + var env = require( '../env' )(); + env.settings.units.should.equal( MMOL ); + delete process.env.DISPLAY_UNITS; + } ); + } ); + + describe ( 'mg/dl', function () { + it( 'mg/dl => mg/dl', function () { + process.env.DISPLAY_UNITS = MGDL; + var env = require( '../env' )(); + env.settings.units.should.equal( MGDL ); + delete process.env.DISPLAY_UNITS; + } ); + + it( 'mg/dL => mg/dl', function () { + process.env.DISPLAY_UNITS = 'mg/dL'; + var env = require( '../env' )(); + env.settings.units.should.equal( MGDL ); + delete process.env.DISPLAY_UNITS; + } ); + + it( 'MG/DL => mg/dl', function () { + process.env.DISPLAY_UNITS = 'MG/DL'; + var env = require( '../env' )(); + env.settings.units.should.equal( MGDL ); + delete process.env.DISPLAY_UNITS; + } ); + + it( 'mgdl => mg/dl', function () { + process.env.DISPLAY_UNITS = 'mgdl'; + var env = require( '../env' )(); + env.settings.units.should.equal( MGDL ); + delete process.env.DISPLAY_UNITS; + } ); + } ); + + describe ( 'default: mg/dl', function () { + it( ' => mg/dl', function () { + var random; + while (!random || random.toLowerCase() === MGDL) + random = [...Array(~~(Math.random()*20)+1)].map(i=>(~~(Math.random()*36)).toString(36)).join(''); + + process.env.DISPLAY_UNITS = random; + var env = require( '../env' )(); + env.settings.units.should.equal( MGDL ); + delete process.env.DISPLAY_UNITS; + } ); + + it( ' => mg/dl', function () { + delete process.env.DISPLAY_UNITS; + var env = require( '../env' )(); + env.settings.units.should.equal( MGDL ); + delete process.env.DISPLAY_UNITS; + } ); + } ); + } ); }) diff --git a/tests/expressextensions.test.js b/tests/expressextensions.test.js new file mode 100644 index 00000000000..b65ebd8952b --- /dev/null +++ b/tests/expressextensions.test.js @@ -0,0 +1,33 @@ +'use strict'; + +require('should'); + +var extensionsMiddleware = require('../lib/middleware/express-extension-to-accept.js'); + +var acceptJsonRequests = extensionsMiddleware(['json']); + +describe('Express extension middleware', function ( ) { + + it('Valid json request should be given accept header for application/json', function () { + var entriesRequest = { + path: '/api/v1/entries.json', + url: '/api/v1/entries.json', + headers: {} + }; + + acceptJsonRequests(entriesRequest, {}, () => {}); + entriesRequest.headers.accept.should.equal('application/json'); + }); + + it('Invalid json request should NOT be given accept header', function () { + var invalidEntriesRequest = { + path: '/api/v1/entriesXjson', + url: '/api/v1/entriesXjson', + headers: {} + }; + + acceptJsonRequests(invalidEntriesRequest, {}, () => {}); + should(invalidEntriesRequest.headers.accept).not.be.ok; + }); + +}); diff --git a/tests/fixtures/default-server-settings.js b/tests/fixtures/default-server-settings.js index 113a5fa4aeb..ac3d31d25a0 100644 --- a/tests/fixtures/default-server-settings.js +++ b/tests/fixtures/default-server-settings.js @@ -33,4 +33,5 @@ module.exports = { } , extendedSettings: { } } + , runtimeState: 'loaded' }; \ No newline at end of file diff --git a/tests/mongo-storage.test.js b/tests/mongo-storage.test.js index df85766a29d..ee706906ff8 100644 --- a/tests/mongo-storage.test.js +++ b/tests/mongo-storage.test.js @@ -36,7 +36,7 @@ describe('mongo storage', function () { (function () { return require('../lib/storage/mongo-storage')(env, false, true); - }).should.throw('MongoDB connection string is missing. Please set MONGO_CONNECTION environment variable'); + }).should.throw('MongoDB connection string is missing. Please set MONGODB_URI environment variable'); done(); }); @@ -44,11 +44,17 @@ describe('mongo storage', function () { it('An invalid connection-string should throw an error.', function (done) { env.storageURI = 'This is not a MongoDB connection-string'; - (function () { - return require('../lib/storage/mongo-storage')(env, false, true); - }).should.throw(Error); - - done(); + (async function () { + try { + let foo = await require('../lib/storage/mongo-storage')(env, false, true); + false.should.be.true(); + } + catch (err) { + console.log('We have failed, this is good!'); + done(); + } + })(); + }); }); diff --git a/tests/profile.test.js b/tests/profile.test.js index 373f0479d9d..5928ccd2618 100644 --- a/tests/profile.test.js +++ b/tests/profile.test.js @@ -188,5 +188,199 @@ describe('Profile', function ( ) { dia.should.equal(9); }); + var multiProfileData = + [ + { + "startDate": "2015-06-25T00:00:00.000Z", + "defaultProfile": "20150625-1", + "store": { + "20150625-1": { + "dia": "4", + "timezone": moment.tz().zoneName(), //Assume these are in the localtime zone so tests pass when not on UTC time + "startDate": "1970-01-01T00:00:00.000Z", + 'sens': [ + { + 'time': '00:00', + 'value': 12 + }, + { + 'time': '02:00', + 'value': 13 + }, + { + 'time': '07:00', + 'value': 14 + } + ], + 'carbratio': [ + { + 'time': '00:00', + 'value': 16 + }, + { + 'time': '06:00', + 'value': 15 + }, + { + 'time': '14:00', + 'value': 17 + } + ], + 'carbs_hr': 30, + 'target_low': 4.5, + 'target_high': 8, + "units": "mmol", + "basal": [ + { + "time": "00:00", + "value": "0.5", + "timeAsSeconds": "0" + }, + { + "time": "09:00", + "value": "0.25", + "timeAsSeconds": "32400" + }, + { + "time": "12:30", + "value": "0.9", + "timeAsSeconds": "45000" + }, + { + "time": "17:00", + "value": "0.3", + "timeAsSeconds": "61200" + }, + { + "time": "20:00", + "value": "1", + "timeAsSeconds": "72000" + } + ] + } + }, + "units": "mmol", + "mills": "1435190400000" + }, + { + "startDate": "2015-06-21T00:00:00.000Z", + "defaultProfile": "20190621-1", + "store": { + "20190621-1": { + "dia": "4", + "timezone": moment.tz().zoneName(), //Assume these are in the localtime zone so tests pass when not on UTC time + "startDate": "1970-01-01T00:00:00.000Z", + 'sens': [ + { + 'time': '00:00', + 'value': 11 + }, + { + 'time': '02:00', + 'value': 10 + }, + { + 'time': '07:00', + 'value': 9 + } + ], + 'carbratio': [ + { + 'time': '00:00', + 'value': 12 + }, + { + 'time': '06:00', + 'value': 13 + }, + { + 'time': '14:00', + 'value': 14 + } + ], + 'carbs_hr': 35, + 'target_low': 4.2, + 'target_high': 9, + "units": "mmol", + "basal": [ + { + "time": "00:00", + "value": "0.3", + "timeAsSeconds": "0" + }, + { + "time": "09:00", + "value": "0.4", + "timeAsSeconds": "32400" + }, + { + "time": "12:30", + "value": "0.5", + "timeAsSeconds": "45000" + }, + { + "time": "17:00", + "value": "0.6", + "timeAsSeconds": "61200" + }, + { + "time": "23:00", + "value": "0.7", + "timeAsSeconds": "82800" + } + ] + } + }, + "units": "mmol", + "mills": "1434844800000" + } + ]; + + var multiProfile = require('../lib/profilefunctions')(multiProfileData); + + var noon = new Date('2015-06-22 12:00:00').getTime(); + var threepm = new Date('2015-06-26 15:00:00').getTime(); + + it('should return profile units when configured', function () { + var value = multiProfile.getUnits(); + value.should.equal('mmol'); + }); + + + it('should know what the basal rate is at 12:00 with multiple profiles', function () { + var value = multiProfile.getBasal(noon); + value.should.equal(0.4); + }); + + it('should know what the basal rate is at 15:00 with multiple profiles', function () { + var value = multiProfile.getBasal(threepm); + value.should.equal(0.9); + }); + + it('should know what the carbratio is at 12:00 with multiple profiles', function () { + var carbRatio = multiProfile.getCarbRatio(noon); + carbRatio.should.equal(13); + }); + + it('should know what the carbratio is at 15:00 with multiple profiles', function () { + var carbRatio = multiProfile.getCarbRatio(threepm); + carbRatio.should.equal(17); + }); + + it('should know what the sensitivity is at 12:00 with multiple profiles', function () { + var dia = multiProfile.getSensitivity(noon); + dia.should.equal(9); + }); + + it('should know what the sensitivity is at 15:00 with multiple profiles', function () { + var dia = multiProfile.getSensitivity(threepm); + dia.should.equal(14); + }); + + + it('should select the correct profile for 15:00 with multiple profiles', function () { + var curProfile = multiProfile.getCurrentProfile(threepm); + curProfile.carbs_hr.should.equal(30); + }); }); \ No newline at end of file diff --git a/tests/profileeditor.test.js b/tests/profileeditor.test.js index 9c915027c84..42656b511af 100644 --- a/tests/profileeditor.test.js +++ b/tests/profileeditor.test.js @@ -4,7 +4,6 @@ require('should'); var _ = require('lodash'); var benv = require('benv'); var read = require('fs').readFileSync; -var serverSettings = require('./fixtures/default-server-settings'); var nowData = require('../lib/data/ddata')(); nowData.sgvs.push({ mgdl: 100, mills: Date.now(), direction: 'Flat', type: 'sgv' }); @@ -66,7 +65,7 @@ var exampleProfile = { var someData = { - '/api/v1/profile.json': [exampleProfile] + '/api/v1/profile.json?count=20': [exampleProfile] }; @@ -121,7 +120,8 @@ describe('Profile editor', function ( ) { client.init(); client.dataUpdate(nowData); - //var result = $('body').html(); + // var result = $('body').html(); + // console.log(result); //var filesys = require('fs'); //var logfile = filesys.createWriteStream('out.html', { flags: 'a'} ) //logfile.write($('body').html()); diff --git a/tests/reports.test.js b/tests/reports.test.js index 7d5a0eb7009..c77f87f2e8f 100644 --- a/tests/reports.test.js +++ b/tests/reports.test.js @@ -15,19 +15,19 @@ var nowData = { var someData = { '/api/v1/entries.json?find[date][$gte]=1438992000000&find[date][$lt]=1439078400000&count=10000': [{'_id':'55c697f9459cf1fa5ed71cd8','unfiltered':213888,'filtered':218560,'direction':'Flat','device':'dexcom','rssi':172,'sgv':208,'dateString':'Sat Aug 08 16:58:44 PDT 2015','type':'sgv','date':1439078324000,'noise':1},{'_id':'55c696cc459cf1fa5ed71cd7','unfiltered':217952,'filtered':220864,'direction':'Flat','device':'dexcom','rssi':430,'sgv':212,'dateString':'Sat Aug 08 16:53:45 PDT 2015','type':'sgv','date':1439078025000,'noise':1},{'_id':'55c5d0c6459cf1fa5ed71a04','device':'dexcom','scale':1.1,'dateString':'Sat Aug 08 02:48:05 PDT 2015','date':1439027285000,'type':'cal','intercept':31102.323470336833,'slope':776.9097574914869},{'_id':'55c5d0c5459cf1fa5ed71a03','device':'dexcom','dateString':'Sat Aug 08 02:48:03 PDT 2015','mbg':120,'date':1439027283000,'type':'mbg'}], - '/api/v1/treatments.json?find[created_at][$gte]=2015-08-08T00:00:00.000Z&find[created_at][$lt]=2015-08-09T00:00:00.000Z': [{'enteredBy':'Dad','eventType':'Correction Bolus','glucose':201,'glucoseType':'Finger','insulin':0.65,'units':'mg/dl','created_at':'2015-08-08T23:22:00.000Z','_id':'55c695628a00a3c97a6611ed'},{'enteredBy':'Mom ','eventType':'Correction Bolus','glucose':163,'glucoseType':'Sensor','insulin':0.7,'units':'mg/dl','created_at':'2015-08-08T22:53:11.021Z','_id':'55c68857cd6dd2036036705f'}], + '/api/v1/treatments.json?find[created_at][$gte]=2015-08-08T00:00:00.000Z&find[created_at][$lt]=2015-08-09T00:00:00.000Z&count=1000': [{'enteredBy':'Dad','eventType':'Correction Bolus','glucose':201,'glucoseType':'Finger','insulin':0.65,'units':'mg/dl','created_at':'2015-08-08T23:22:00.000Z','_id':'55c695628a00a3c97a6611ed'},{'enteredBy':'Mom ','eventType':'Correction Bolus','glucose':163,'glucoseType':'Sensor','insulin':0.7,'units':'mg/dl','created_at':'2015-08-08T22:53:11.021Z','_id':'55c68857cd6dd2036036705f'}], '/api/v1/entries.json?find[date][$gte]=1439078400000&find[date][$lt]=1439164800000&count=10000': [{'_id':'55c7e85f459cf1fa5ed71dc8','unfiltered':183520,'filtered':193120,'direction':'NOT COMPUTABLE','device':'dexcom','rssi':161,'sgv':149,'dateString':'Sun Aug 09 16:53:40 PDT 2015','type':'sgv','date':1439164420000,'noise':1},{'_id':'55c7e270459cf1fa5ed71dc7','unfiltered':199328,'filtered':192608,'direction':'Flat','device':'dexcom','rssi':161,'sgv':166,'dateString':'Sun Aug 09 16:28:40 PDT 2015','type':'sgv','date':1439162920000,'noise':1}], - '/api/v1/treatments.json?find[created_at][$gte]=2015-08-09T00:00:00.000Z&find[created_at][$lt]=2015-08-10T00:00:00.000Z': [{'enteredBy':'Dad','eventType':'Snack Bolus','carbs':18,'insulin':1.1,'created_at':'2015-08-09T22:41:56.253Z','_id':'55c7d734270fbd97191013c2'},{'enteredBy':'Dad','eventType':'Carb Correction','carbs':5,'created_at':'2015-08-09T21:39:13.995Z','_id':'55c7c881270fbd97191013b4'}], + '/api/v1/treatments.json?find[created_at][$gte]=2015-08-09T00:00:00.000Z&find[created_at][$lt]=2015-08-10T00:00:00.000Z&count=1000': [{'enteredBy':'Dad','eventType':'Snack Bolus','carbs':18,'insulin':1.1,'created_at':'2015-08-09T22:41:56.253Z','_id':'55c7d734270fbd97191013c2'},{'enteredBy':'Dad','eventType':'Carb Correction','carbs':5,'created_at':'2015-08-09T21:39:13.995Z','_id':'55c7c881270fbd97191013b4'}], '/api/v1/entries.json?find[date][$gte]=1439164800000&find[date][$lt]=1439251200000&count=10000': [{'_id':'55c93af4459cf1fa5ed71ecc','unfiltered':193248,'filtered':188384,'direction':'NOT COMPUTABLE','device':'dexcom','rssi':194,'sgv':193,'dateString':'Mon Aug 10 16:58:36 PDT 2015','type':'sgv','date':1439251116000,'noise':1},{'_id':'55c939d8459cf1fa5ed71ecb','unfiltered':189888,'filtered':184960,'direction':'NOT COMPUTABLE','device':'dexcom','rssi':931,'sgv':188,'dateString':'Mon Aug 10 16:53:38 PDT 2015','type':'sgv','date':1439250818000,'noise':1}], - '/api/v1/treatments.json?find[created_at][$gte]=2015-08-10T00:00:00.000Z&find[created_at][$lt]=2015-08-11T00:00:00.000Z': [{'enteredBy':'Mom ','eventType':'Snack Bolus','glucose':180,'glucoseType':'Sensor','carbs':18,'insulin':1.9,'units':'mg/dl','created_at':'2015-08-10T23:53:31.970Z','_id':'55c9397b865550df020e3560'},{'enteredBy':'Mom ','eventType':'Meal Bolus','glucose':140,'glucoseType':'Finger','carbs':50,'insulin':3.4,'units':'mg/dl','created_at':'2015-08-10T20:41:23.516Z','_id':'55c90c73865550df020e3539'}], + '/api/v1/treatments.json?find[created_at][$gte]=2015-08-10T00:00:00.000Z&find[created_at][$lt]=2015-08-11T00:00:00.000Z&count=1000': [{'enteredBy':'Mom ','eventType':'Snack Bolus','glucose':180,'glucoseType':'Sensor','carbs':18,'insulin':1.9,'units':'mg/dl','created_at':'2015-08-10T23:53:31.970Z','_id':'55c9397b865550df020e3560'},{'enteredBy':'Mom ','eventType':'Meal Bolus','glucose':140,'glucoseType':'Finger','carbs':50,'insulin':3.4,'units':'mg/dl','created_at':'2015-08-10T20:41:23.516Z','_id':'55c90c73865550df020e3539'}], '/api/v1/entries.json?find[date][$gte]=1439251200000&find[date][$lt]=1439337600000&count=10000': [{'_id':'55ca8c6e459cf1fa5ed71fe2','unfiltered':174080,'filtered':184576,'direction':'FortyFiveDown','device':'dexcom','rssi':169,'sgv':156,'dateString':'Tue Aug 11 16:58:32 PDT 2015','type':'sgv','date':1439337512000,'noise':1},{'_id':'55ca8b42459cf1fa5ed71fe1','unfiltered':180192,'filtered':192768,'direction':'FortyFiveDown','device':'dexcom','rssi':182,'sgv':163,'dateString':'Tue Aug 11 16:53:32 PDT 2015','type':'sgv','date':1439337212000,'noise':1}], - '/api/v1/treatments.json?find[created_at][$gte]=2015-08-11T00:00:00.000Z&find[created_at][$lt]=2015-08-12T00:00:00.000Z': [{'created_at':'2015-08-11T23:37:00.000Z','eventType':'Snack Bolus','carbs':18,'_id':'55ca8644ca3c57683d19c211'},{'enteredBy':'Mom ','eventType':'Snack Bolus','glucose':203,'glucoseType':'Sensor','insulin':1,'preBolus':15,'units':'mg/dl','created_at':'2015-08-11T23:22:00.000Z','_id':'55ca8644ca3c57683d19c210'}], + '/api/v1/treatments.json?find[created_at][$gte]=2015-08-11T00:00:00.000Z&find[created_at][$lt]=2015-08-12T00:00:00.000Z&count=1000': [{'created_at':'2015-08-11T23:37:00.000Z','eventType':'Snack Bolus','carbs':18,'_id':'55ca8644ca3c57683d19c211'},{'enteredBy':'Mom ','eventType':'Snack Bolus','glucose':203,'glucoseType':'Sensor','insulin':1,'preBolus':15,'units':'mg/dl','created_at':'2015-08-11T23:22:00.000Z','_id':'55ca8644ca3c57683d19c210'}], '/api/v1/entries.json?find[date][$gte]=1439337600000&find[date][$lt]=1439424000000&count=10000': [{'_id':'55cbddee38a8d88ad1b48647','unfiltered':165760,'filtered':167488,'direction':'Flat','device':'dexcom','rssi':165,'sgv':157,'dateString':'Wed Aug 12 16:58:28 PDT 2015','type':'sgv','date':1439423908000,'noise':1},{'_id':'55cbdccc38a8d88ad1b48644','unfiltered':167456,'filtered':169312,'direction':'Flat','device':'dexcom','rssi':168,'sgv':159,'dateString':'Wed Aug 12 16:53:28 PDT 2015','type':'sgv','date':1439423608000,'noise':1}], - '/api/v1/treatments.json?find[created_at][$gte]=2015-08-12T00:00:00.000Z&find[created_at][$lt]=2015-08-13T00:00:00.000Z': [{'enteredBy':'Dad','eventType':'Correction Bolus','insulin':0.8,'created_at':'2015-08-12T23:21:08.907Z','_id':'55cbd4e47e726599048a3f91'},{'enteredBy':'Dad','eventType':'Note','notes':'Milk now','created_at':'2015-08-12T21:23:00.000Z','_id':'55cbba4e7e726599048a3f79'}], + '/api/v1/treatments.json?find[created_at][$gte]=2015-08-12T00:00:00.000Z&find[created_at][$lt]=2015-08-13T00:00:00.000Z&count=1000': [{'enteredBy':'Dad','eventType':'Correction Bolus','insulin':0.8,'created_at':'2015-08-12T23:21:08.907Z','_id':'55cbd4e47e726599048a3f91'},{'enteredBy':'Dad','eventType':'Note','notes':'Milk now','created_at':'2015-08-12T21:23:00.000Z','_id':'55cbba4e7e726599048a3f79'}], '/api/v1/entries.json?find[date][$gte]=1439424000000&find[date][$lt]=1439510400000&count=10000': [{'_id':'55cd2f6738a8d88ad1b48ca1','unfiltered':209792,'filtered':229344,'direction':'SingleDown','device':'dexcom','rssi':436,'sgv':205,'dateString':'Thu Aug 13 16:58:24 PDT 2015','type':'sgv','date':1439510304000,'noise':1},{'_id':'55cd2e3b38a8d88ad1b48c95','unfiltered':220928,'filtered':237472,'direction':'FortyFiveDown','device':'dexcom','rssi':418,'sgv':219,'dateString':'Thu Aug 13 16:53:24 PDT 2015','type':'sgv','date':1439510004000,'noise':1}], - '/api/v1/treatments.json?find[created_at][$gte]=2015-08-13T00:00:00.000Z&find[created_at][$lt]=2015-08-14T00:00:00.000Z': [{'enteredBy':'Mom ','eventType':'Correction Bolus','glucose':250,'glucoseType':'Sensor','insulin':0.75,'units':'mg/dl','created_at':'2015-08-13T23:45:56.927Z','_id':'55cd2c3497fa97ac5d8bc53b'},{'enteredBy':'Mom ','eventType':'Correction Bolus','glucose':198,'glucoseType':'Sensor','insulin':1.1,'units':'mg/dl','created_at':'2015-08-13T23:11:00.293Z','_id':'55cd240497fa97ac5d8bc535'}], + '/api/v1/treatments.json?find[created_at][$gte]=2015-08-13T00:00:00.000Z&find[created_at][$lt]=2015-08-14T00:00:00.000Z&count=1000': [{'enteredBy':'Mom ','eventType':'Correction Bolus','glucose':250,'glucoseType':'Sensor','insulin':0.75,'units':'mg/dl','created_at':'2015-08-13T23:45:56.927Z','_id':'55cd2c3497fa97ac5d8bc53b'},{'enteredBy':'Mom ','eventType':'Correction Bolus','glucose':198,'glucoseType':'Sensor','insulin':1.1,'units':'mg/dl','created_at':'2015-08-13T23:11:00.293Z','_id':'55cd240497fa97ac5d8bc535'}], '/api/v1/entries.json?find[date][$gte]=1439510400000&find[date][$lt]=1439596800000&count=10000': [{'_id':'55ce80e338a8d88ad1b49397','unfiltered':179936,'filtered':202080,'direction':'SingleDown','device':'dexcom','rssi':179,'sgv':182,'dateString':'Fri Aug 14 16:58:20 PDT 2015','type':'sgv','date':1439596700000,'noise':1},{'_id':'55ce7fb738a8d88ad1b4938d','unfiltered':192288,'filtered':213792,'direction':'SingleDown','device':'dexcom','rssi':180,'sgv':197,'dateString':'Fri Aug 14 16:53:20 PDT 2015','type':'sgv','date':1439596400000,'noise':1}], - '/api/v1/treatments.json?find[created_at][$gte]=2015-08-14T00:00:00.000Z&find[created_at][$lt]=2015-08-15T00:00:00.000Z': [{'enteredBy':'Dad','eventType':'Site Change','glucose':268,'glucoseType':'Finger','insulin':1.75,'units':'mg/dl','created_at':'2015-08-14T00:00:00.000Z','_id':'55ce78fe925aa80e7071e5d6'},{'enteredBy':'Mom ','eventType':'Meal Bolus','glucose':89,'glucoseType':'Finger','carbs':54,'insulin':3.15,'units':'mg/dl','created_at':'2015-08-14T21:00:00.000Z','_id':'55ce59bb925aa80e7071e5ba'}], + '/api/v1/treatments.json?find[created_at][$gte]=2015-08-14T00:00:00.000Z&find[created_at][$lt]=2015-08-15T00:00:00.000Z&count=1000': [{'enteredBy':'Dad','eventType':'Site Change','glucose':268,'glucoseType':'Finger','insulin':1.75,'units':'mg/dl','created_at':'2015-08-14T00:00:00.000Z','_id':'55ce78fe925aa80e7071e5d6'},{'enteredBy':'Mom ','eventType':'Meal Bolus','glucose':89,'glucoseType':'Finger','carbs':54,'insulin':3.15,'units':'mg/dl','created_at':'2015-08-14T21:00:00.000Z','_id':'55ce59bb925aa80e7071e5ba'}], '/api/v1/entries.json?find[date][$gte]=1439596800000&find[date][$lt]=1439683200000&count=10000': [{'_id':'55cfd25f38a8d88ad1b49931','unfiltered':283136,'filtered':304768,'direction':'SingleDown','device':'dexcom','rssi':185,'sgv':306,'dateString':'Sat Aug 15 16:58:16 PDT 2015','type':'sgv','date':1439683096000,'noise':1},{'_id':'55cfd13338a8d88ad1b4992e','unfiltered':302528,'filtered':312576,'direction':'FortyFiveDown','device':'dexcom','rssi':179,'sgv':329,'dateString':'Sat Aug 15 16:53:16 PDT 2015','type':'sgv','date':1439682796000,'noise':1}], '/api/v1/food/regular.json': [{'_id':'552ece84a6947ea011db35bb','type':'food','category':'Zakladni','subcategory':'Sladkosti','name':'Bebe male','portion':18,'carbs':12,'gi':1,'unit':'pcs','created_at':'2015-04-15T20:48:04.966Z'}], '/api/v1/treatments.json?find[eventType]=/BG Check/i&find[created_at][$gte]=2015-08-08T00:00:00.000Z&find[created_at][$lt]=2015-09-07T23:59:59.000Z': [ @@ -268,7 +268,7 @@ describe('reports', function ( ) { result.indexOf('50 g').should.be.greaterThan(-1); // daytoday result.indexOf('TDD average: 2.9U').should.be.greaterThan(-1); // daytoday result.indexOf('
0%100%0%264.7%6In Range: 47.6%1016 (100%)
+ + + + +
+ + + + + +

Oops - Nightscout is having trouble

+ +

Don't panic, we can work this out! This happens to the best of us.

+

Check the errors below and then refer to the + troubleshooting documentation.

+ +

Errors occurred during startup:

+
<%- errors %>
+
+ + + + diff --git a/views/foodindex.html b/views/foodindex.html index d42eb16a50b..7168897467f 100644 --- a/views/foodindex.html +++ b/views/foodindex.html @@ -24,30 +24,17 @@ - + - + <% include preloadCSS %> - + + <%- include('partials/toolbar') %> -
X
- - -
-
- Status: Not loaded -
-

Nightscout

-
-

Food Editor

-
-
- -
Your database @@ -121,12 +108,12 @@

Food Editor

- Authentication status: -
- - - - + + <%- include('partials/authentication-status') %> + + + + diff --git a/views/frame.html b/views/frame.html new file mode 100644 index 00000000000..aff6ea0d6ce --- /dev/null +++ b/views/frame.html @@ -0,0 +1,54 @@ +<% + +let urlArray = []; +let nameArray = []; + +for (let i = 0; i <= 8; i++) { + let u = settings['frameUrl' + i]; + let n = settings['frameName' + i] || " "; + if (u) { + urlArray.push(u); + nameArray.push(n); + } +} + +const sitesPerRow = urlArray.length > 3 ? Math.round(urlArray.length / 2) : urlArray.length; +const rows = urlArray.length > 3 ? 2 : 1; + +%> + + Nightscout multiframe view + + + + + + <% let s = 0; + for (let r = 1; r <= rows; r++) { + %> + <% for (let sp = 0; sp < sitesPerRow; sp++) { + let pointer = sp + s; + %> + <% } %> + + + <% for (let sp = 0; sp < sitesPerRow; sp++) { + let pointer = sp + s; + %> + <% } %> + + <% s += sitesPerRow; } %> +
<%= nameArray[pointer] %>
+ + + \ No newline at end of file diff --git a/views/index.html b/views/index.html index b80e11ddd42..8e60b30f471 100644 --- a/views/index.html +++ b/views/index.html @@ -1,706 +1,751 @@ - - manifest="appcache/nightscout-<%= locals.cachebuster %>.appcache" - <% } %>> - - - - - - - Nightscout - - - - - - - - - - - - - - - - - - - - - - - - - -<% include preloadCSS %> - - -
-
-

-

Loading the client

-
-
-
-
-
-
-
-
-
- -
Nightscout
-
-
- -
-
-
- - -
-
-
- -
-
-
---
-
-
-
-
-
- -
    -
  • Hours:
  • -
  • 2
  • -
  • 3
  • -
  • 4
  • -
  • 6
  • -
  • 12
  • -
  • 24
  • -
  • ...
  • -
-
- -
-
-
-
+ + + <% include preloadCSS %> + + + +
+
+

+

Loading the client

+
+
+
+
+
+
+
+
+ <%- include('partials/toolbar') %> + +
+ +
+
+
+ + +
+
+
+ +
+
+
---
+
+
+
+
+ +
    +
  • Hours:
  • +
  • 2
  • +
  • 3
  • +
  • 4
  • +
  • 6
  • +
  • 12
  • +
  • 24
  • +
  • ...
  • +
+
+ +
+
+
+
+
+ +
+
+ +
+ Settings +
+
Units
+
+
+
+
+
Date format
+
+
+
+
+
Language
+
+ +
+
+
+
Scale
+
+ +
+
+
+
Render Basal
+
+ +
+
+
+
Render Bolus Amount
+
+ +
+
+ +
+
Enable Alarms
+
+
+
+
+
+ + + mins +
+
+ + + mins +
+
+
+
+
Night Mode
+
+
+
+
Edit Mode
+
+
+
+
Show Raw BG Data
+
+
+
+
+
+
Custom Title
+
+
+
+
Theme
+
+
+
+
+
+
Show Plugins
+
+
-
- - -
- Settings -
-
Units
-
-
-
-
-
Date format
-
-
-
-
-
Language
-
- -
-
-
-
Scale
-
- -
-
-
-
Render Basal
-
- -
-
-
-
Enable Alarms
-
-
-
-
-
- - - mins -
-
- - - mins -
-
-
-
-
Night Mode
-
-
-
-
Edit Mode
-
-
-
-
Show Raw BG Data
-
-
-
-
-
-
Custom Title
-
-
-
-
Theme
-
-
-
-
-
-
Show Plugins
-
-
- - - -
- - -
- About -
-
version
-
head
-

-

License: AGPL
-
Copyright © 2017 Nightscout contributors
-

- -
- + + + <%- include('partials/authentication-status') %> + +
+ About +
+
version
+
head
+

+

License: AGPL
+
Copyright © 2017 Nightscout contributors
+

+ +
+ +
+ +
+
+
+ Log a Treatment + + + +
+ Targets + + +
+ +
+ Glucose Reading + + + + +
+ + + + + +
+ + + +
-
- -
- Log a Treatment - - - -
- Targets - - -
- -
- Glucose Reading - - - - -
-
- - - -
- - - - - - - - - - -
- - - -
- Event Time - - - - -
- - -
- + + + + + + + + + + +
+ + + +
+ Event Time + + + +
-
-
-
- - Bolus Wizard - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - BG: - - - - -
- - - - - - - - - - 0.00 -
- Quickpick: -
- -
- - or - - Add from database - - -
-
-
- - - Carbs: - - g - - - -
- - - COB: - - g - - - -
- - - IOB: - - 0.00 -
- - Other correction: - - -
- - Rounding: - - 0.00 -
- - Calculation is in target range. -
- - - Insulin needed: - - 0.00 -
- - Carbs needed: - - - -
- - Basal rate: - - -
-
- + +
+
+
+ +
+
+
+ + Bolus Wizard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + BG: + + + + +
+ + + + + + + + + + 0.00 +
+ Quickpick:
- +
+ + or + + Add from database + + +
+
+
+ + + Carbs: + + g + + + +
+ + + COB: + + g + + + +
+ + + IOB: + + 0.00 +
+ + Other correction: + + +
+ + Rounding: + + 0.00 +
+ + Calculation is in target range. +
+ + + Insulin needed: + + 0.00 +
+ + Carbs needed: + + + +
+ + Basal rate: + + +
+
+ +
+ +
- - - -
+ + + +
- - - -
- Event Time: - - - - - - -
- -
- -
- - + + + +
+ Event Time: + + + + + +
+ +
+ + + +
-
- - -
+
+ + +
+ + + + + + + + - - - - diff --git a/views/nightscout.appcache b/views/nightscout.appcache deleted file mode 100644 index 3823f894e5f..00000000000 --- a/views/nightscout.appcache +++ /dev/null @@ -1,37 +0,0 @@ -CACHE MANIFEST - -/images/launch.png -/images/apple-touch-icon-57x57.png -/images/apple-touch-icon-60x60.png -/images/apple-touch-icon-72x72.png -/images/apple-touch-icon-76x76.png -/images/apple-touch-icon-114x114.png -/images/apple-touch-icon-120x120.png -/images/apple-touch-icon-144x144.png -/images/apple-touch-icon-152x152.png -/images/apple-touch-icon-180x180.png -/images/favicon-32x32.png -/images/android-chrome-192x192.png -/images/favicon-96x96.png -/images/favicon-16x16.png -/manifest.json -/images/favicon.ico -/images/mstile-144x144.png -/css/ui-darkness/jquery-ui.min.css?v=<%= locals.cachebuster %> -/css/jquery.tooltips.css?v=<%= locals.cachebuster %> -/audio/alarm.mp3 -/audio/alarm2.mp3 -/css/ui-darkness/images/ui-icons_ffffff_256x240.png -/css/ui-darkness/images/ui-icons_cccccc_256x240.png -/css/ui-darkness/images/ui-bg_inset-soft_25_000000_1x100.png -/css/ui-darkness/images/ui-bg_gloss-wave_25_333333_500x100.png -/css/main.css?v=<%= locals.cachebuster %> -/bundle/js/bundle.app.js?v=<%= locals.cachebuster %> -/bundle/js/bundle.clock.js?v=<%= locals.cachebuster %> -/bundle/js/bundle.report.js?v=<%= locals.cachebuster %> -/socket.io/socket.io.js?v=<%= locals.cachebuster %> -/js/client.js?v=<%= locals.cachebuster %> -/images/logo2.png - -NETWORK: -* diff --git a/views/partials/authentication-status.ejs b/views/partials/authentication-status.ejs new file mode 100644 index 00000000000..db969c906b1 --- /dev/null +++ b/views/partials/authentication-status.ejs @@ -0,0 +1,3 @@ +
+ Authentication status: +
\ No newline at end of file diff --git a/views/partials/toolbar.ejs b/views/partials/toolbar.ejs new file mode 100644 index 00000000000..b98f2756c3d --- /dev/null +++ b/views/partials/toolbar.ejs @@ -0,0 +1,34 @@ +
+

Nightscout

+ + <%if (type !== 'index') { %> + X + <% } %> + + <%if (type === 'food') { %> +
+ Status: Not loaded +
+ <% } %> + <%if (type === 'profile') { %> +
+ Status: Not loaded +
+ <% } %> + <%if (type === 'index') { %> + + <% } %> +
+ +<%if (title) { %> +
+

<%= title %>

+
+<% } %> \ No newline at end of file diff --git a/views/profileindex.html b/views/profileindex.html index d64f1300917..d915d0c8cc8 100644 --- a/views/profileindex.html +++ b/views/profileindex.html @@ -25,26 +25,15 @@ - + - + <% include preloadCSS %> - -
X
- -
-
- Status: Not loaded -
-

Nightscout

-
- -
-

Profile Editor

-
+ + <%- include('partials/toolbar') %>
@@ -168,18 +157,17 @@

Profile Editor

- Authentication status: - -

Status: Not loaded

+ <%- include('partials/authentication-status') %> + - - - + + + diff --git a/views/reportindex.html b/views/reportindex.html index 5fa745ce34c..ea1284b6cd4 100644 --- a/views/reportindex.html +++ b/views/reportindex.html @@ -1,39 +1,40 @@ - - Nightscout reporting + + Nightscout Reporting + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + <% include preloadCSS %> + + + + <%- include('partials/toolbar') %> - - - <% include preloadCSS %> - - - -
X
- -

Nightscout reporting

-
    -
+
    +
+
@@ -48,7 +49,7 @@ Last monthLast 3 months - + - - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + +
Notes contain:
- Event Type: -
- Mo - Tu - We - Th - Fr - Sa - Su -
- Target bg range bottom: - - top: - -
- Order: - - - -   - - -
+ Event Type: +
+ + + + + + + +
+ Target BG range bottom: + + top: + +
+ Order: + + + +   + + +

+
-
- Authentication status: + <%- include('partials/authentication-status') %> - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/views/service-worker.js b/views/service-worker.js new file mode 100644 index 00000000000..d52441d303a --- /dev/null +++ b/views/service-worker.js @@ -0,0 +1,175 @@ +'use strict'; + +var CACHE = '<%= locals.cachebuster %>'; + +const CACHE_LIST = [ + '/images/launch.png', + '/images/apple-touch-icon-57x57.png', + '/images/apple-touch-icon-60x60.png', + '/images/apple-touch-icon-72x72.png', + '/images/apple-touch-icon-76x76.png', + '/images/apple-touch-icon-114x114.png', + '/images/apple-touch-icon-120x120.png', + '/images/apple-touch-icon-144x144.png', + '/images/apple-touch-icon-152x152.png', + '/images/apple-touch-icon-180x180.png', + '/images/favicon-32x32.png', + '/images/android-chrome-192x192.png', + '/images/favicon-96x96.png', + '/images/favicon-16x16.png', + '/manifest.json', + '/images/favicon.ico', + '/images/mstile-144x144.png', + '/css/ui-darkness/jquery-ui.min.css', + '/css/jquery.tooltips.css', + '/css/ui-darkness/images/ui-icons_ffffff_256x240.png', + '/css/ui-darkness/images/ui-icons_cccccc_256x240.png', + '/css/ui-darkness/images/ui-bg_inset-soft_25_000000_1x100.png', + '/css/ui-darkness/images/ui-bg_gloss-wave_25_333333_500x100.png', + '/css/main.css', + '/bundle/js/bundle.app.js', + '/bundle/js/bundle.clock.js', + '/bundle/js/bundle.report.js', + '/socket.io/socket.io.js', + '/js/client.js', + '/images/logo2.png' +]; + +function returnRangeRequest(request) { + return caches + .open(CACHE) + .then((cache) => { + return cache.match(request.url); + }) + .then((res) => { + if (!res) { + return fetch(request) + .then(res => { + const clonedRes = res.clone(); + return caches + .open(CACHE) + .then(cache => cache.put(request, clonedRes)) + .then(() => res); + }) + .then(res => { + return res.arrayBuffer(); + }); + } + return res.arrayBuffer(); + }) + .then((arrayBuffer) => { + const bytes = /^bytes=(\d+)-(\d+)?$/g.exec( + request.headers.get('range') + ); + if (bytes) { + const start = Number(bytes[1]); + const end = Number(bytes[2]) || arrayBuffer.byteLength - 1; + return new Response(arrayBuffer.slice(start, end + 1), { + status: 206, + statusText: 'Partial Content', + headers: [ + ['Content-Range', `bytes ${start}-${end}/${arrayBuffer.byteLength}`] + ] + }); + } else { + return new Response(null, { + status: 416, + statusText: 'Range Not Satisfiable', + headers: [['Content-Range', `*/${arrayBuffer.byteLength}`]] + }); + } + }); +} + +// Open a cache and `put()` the assets to the cache. +// Return a promise resolving when all the assets are added. +function precache() { + return caches.open(CACHE) + .then((cache) => { + // if any cache requests fail, don't interrupt other requests in progress + return Promise.allSettled( + CACHE_LIST.map((url) => { + // `no-store` in case of partial content responses and + // because we're making our own cache + let request = new Request(url, { cache: 'no-store' }); + return fetch(request).then((response) => { + // console.log('Caching response', url, response); + cache.put(url, response); + }).catch((err) => { + console.log('Could not precache asset', url, err); + }); + }) + ); + }); +} + +// Try to read the requested resource from cache. +// If the requested resource does not exist in the cache, fetch it from +// network and cache the response. +function fromCache(request) { + return caches.open(CACHE).then((cache) => { + return cache.match(request).then((matching) => { + console.log(matching); + if(matching){ + return matching; + } + + return fetch(request).then((response) => { + // console.log('Response from network is:', response); + cache.put(request, response.clone()); + return response; + }).catch((error) => { + // This catch() will handle exceptions thrown from the fetch() operation. + // Note that a HTTP error response (e.g. 404) will NOT trigger an exception. + // It will return a normal response object that has the appropriate error code set. + console.error('Fetching failed:', error); + + throw error; + }); + }); + }); +} + +// On install, cache some resources. +self.addEventListener('install', (evt) => { + // console.log('The service worker is being installed.'); + self.skipWaiting(); + evt.waitUntil(precache()); +}); + +function inCache(request) { + let found = false; + CACHE_LIST.forEach((e) => { + if (request.url.endsWith(e)) { + found = true; + } + }); + return found; +} + +self.addEventListener('fetch', (evt) => { + if (!evt.request.url.startsWith(self.location.origin) || CACHE === 'developmentMode' || !inCache(evt.request) || evt.request.method !== 'GET') { + //console.log('Skipping cache for ', evt.request.url); + return void evt.respondWith(fetch(evt.request)); + } + if (evt.request.headers.get('range')) { + evt.respondWith(returnRangeRequest(evt.request)); + } else { + evt.respondWith(fromCache(evt.request)); + } +}); + +self.addEventListener('activate', (event) => { + event.waitUntil( + caches.keys().then((cacheNames) => { + return Promise.all( + cacheNames.map((cacheName) => { + if (cacheName !== CACHE) { + // console.log('Deleting out of date cache:', cacheName); + return caches.delete(cacheName); + } + }) + ); + })); + +}); diff --git a/views/translationsindex.html b/views/translationsindex.html index 4145f3d1db0..6543bb06259 100644 --- a/views/translationsindex.html +++ b/views/translationsindex.html @@ -23,19 +23,18 @@ + <% include preloadCSS %> - -
X
+ + <%- include('partials/toolbar') %> -

Nightscout translations

-
- Authentication status: + <%- include('partials/authentication-status') %>