diff --git a/.eslintignore b/.eslintignore index c911e25..414a0ad 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,7 +4,6 @@ webExtensionApis/study/api.js webExtensionApis/study/stubApi.js package-lock.json # do not lint/format bundled util libraries -test-addon/src/privileged/prefs/ test-addon/src/privileged/study/ # makes sure that eslintrc.js gets linted/formatted !.eslintrc.js diff --git a/.spelling b/.spelling index 5aa1111..b7440a4 100644 --- a/.spelling +++ b/.spelling @@ -143,8 +143,8 @@ studyInfo studyInfoObject studyName studySetup -studyType -studyTypesEnum +telemetryPipeline +telemetryPipelinesEnum StudyUtils studyUtils StudyUtils.jsm diff --git a/README.md b/README.md index e020aed..6e619f3 100644 --- a/README.md +++ b/README.md @@ -1,114 +1,46 @@ -| [WebExtensions API:s](./docs/api.md) | [Small example](./examples/small-study/) | [(Full) WebExtension template](https://github.com/mozilla/shield-studies-addon-template/) | [Engineering your add-on](#engineering-your-own-study-add-on) | [Shield - Mozilla Wiki](https://wiki.mozilla.org/Firefox/Shield) | -| ------------------------------------ | ---------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------- | +| [WebExtensions API:s](./docs/api.md) | [Engineering your add-on](#engineering-your-own-study-add-on) | +| ------------------------------------ | ------------------------------------------------------------- | # Shield Studies Add-on Utils [![CircleCI badge](https://img.shields.io/circleci/project/github/mozilla/shield-studies-addon-utils/master.svg?label=CircleCI)](https://circleci.com/gh/mozilla/shield-studies-addon-utils/) +## Features + This is the home of the [`shield-studies-addon-utils` npm package](https://www.npmjs.com/package/shield-studies-addon-utils), which provides: -* WebExtensionExperiment API's +### `shield-study` telemetry + +Validate and send `shield-study`, `shield-study-addon` Telemetry, allowing experiments to submit experiment-scoped stringified key-value pairs that are directly available for analysis. - * `browser.study` +### Pioneer telemetry -* Additional useful testing interface +Validate, encrypt and send `shield-study`, `shield-study-addon` Pioneer Telemetry. - * `browser.studyDebug` +### Other telemetry helpers -* Scripts: +Validate telemetry payloads against JSON schemas and calculate the size of a ping before submitting it. - * `copyStudyUtils` shell command copying these files in your study add-on. +### Add-on test helpers -## Goals: +Helper classes and methods to write Selenium-based functional/unit tests for your study add-on. -Allows writing [Shield and Pioneer Add-on Experiments](https://mana.mozilla.org/wiki/display/FIREFOX/Pref-Flip+and+Add-On+Experiments) that manage their own life-cycle. +### Survey URLs helper -* **assign variations**: deterministic, persistent variation assignments for A/B multi-variant studies. -* **startup/shutdown/disable/uninstall**: has strong opinions about business logic for Telemetry around startup, shutdown -* **expiration**: helps handle study expiration by storing first run timestamp in a preference -* **eligibility**: consistent handling of post-install / first run eligiblity -* **telemetry helpers** make it easier to send correctly formatted `shield-study`, `shield-study-addon` Telemetry. -* **format survey URLs** and other 'post' and 'mid-study' URLs to have correct appended query arguments, to - * create flow-control logic during surveys - * proper version, study and other tracking variables +For formatting 'post' and 'mid-study' survey URLs to have correct appended query arguments in the format that matches the corresponding SurveyGizmo library elements ## Help and support Thinking about building a Study Add-on? Please read [the docs on Pref-Flip and Add-On Experiments](https://mana.mozilla.org/wiki/display/FIREFOX/Pref-Flip+and+Add-On+Experiments) first. -If you haven't checked out [the template](https://github.com/mozilla/shield-studies-addon-template) yet, do it. It contains a lot of best practices that helps study add-ons pass QA quicker. - -## Learn the API - -1. **Read** the API: [study api.md](./docs/api.md) - - Documentation of the API. Notice that there are - - * `functions`: async functions in the `browser.study`. - * `events`: webExtension events in the `browser.study` - * `types`: jsonschema draft-04 formats. - -2. **Explore** [`examples/small-study`](./examples/small-study/): - - * [`manifest.json`](./examples/small-study/src/manifest.json) - - Notice the `experiment_apis` section. This maps `browser.study` to the privileged API code. (See details below) - - * [`studySetup.js`](./examples/small-study/src/studySetup.js) - - Construct a `studySetup` usable by `browser.study.setup` - - * [`background.js`](./examples/small-study/src/background.js) - - Using the `browser.study` API within a small instrumented feature. - -3. **Create magic** using [mozilla/shield-studies-addon-template/](https://github.com/mozilla/shield-studies-addon-template/) to get started with an example study where `shield-studies-addon-utils` is already installed and configured. - -## Installing the Shield Studies Add-on Utils in your add-on - -1. Install the Package - - ```sh - npm install --save shield-studies-addon-utils - ``` - -2. Copy the files to your 'privileged' src directory - - ```sh - # copyStudyUtils is installed in `node_modules/.bin` - copyStudyUtils ./privileged --example - ``` - - Suggestion: make this part of your `package.json:scripts.postinstall` script. - -3. Set logging in `about:config` - - ``` - prefName: shieldStudy.logLevel - values: All|Trace|Debug|Info|Warn|Error - ``` +## Installing Shield Studies Add-on Utils in your add-on -Again, [the template](https://github.com/mozilla/shield-studies-addon-template) has this preconfigured already. - -## WebExtension APIs Provided by Shield Studies Add-on Utils - -### `browser.study.*` - -[`browser.study` API documentation](./webExtensionApis/study/api.md) - -Provides these capabilities: - -1. **deterministically decide variation for a client** (`setup`), i.e. based on a hash of non-PII user info, they will always get assigned to the same branch every time the study launches) -2. **Report study lifecycle data** using Telemetry configured. -3. **Report feature interaction and success data** using study-specific Telemetry (`sendTelemetry`). -4. **Registers/unregisters the study as an active experiment** (By annotating the Telemetry Environment, marking the user as special in the `main` ping). -5. **Validates setup using schema for study configuration**. -6. **Handles study endings** (`endStudy` method bundles lots of tasks in one, including appending survey URLs specified in Config.jsm with query strings/sending the user to a survey and uninstalling the add-on). - -To use in your study (long-version): +```sh +npm install --save shield-studies-addon-utils +``` -* `copyStudyUtils yourAddonSrc/privileged/` which copies `webExtensionApis/study/api.js` and `webExtensionApis/study/schema.json` to your add-on's source directory under `yourAddonSrc/privileged/study`, +* Run `copyStudyUtils yourAddonSrc/privileged/` which copies `webExtensionApis/study/api.js` and `webExtensionApis/study/schema.json` to your add-on's source directory under `yourAddonSrc/privileged/study`, * add the following to your add-on's manifest.json: ``` @@ -124,32 +56,31 @@ To use in your study (long-version): }, ``` -#### Data processing pipelines +## WebExtension APIs Provided by Shield Studies Add-on Utils -Depending on which data processing pipeline the study add-on is configured to use, the pings end up in different destinations: +### `browser.study.*` + +[`browser.study` API documentation](./webExtensionApis/study/api.md) + +#### Supported telemetry pipelines + +Depending on which telemetry pipeline is used, the pings end up in different destinations: * `shield` - The pings end up in the `shield-study` and `shield-study-addon` Telemetry buckets for instant access to submitted payloads via [STMO](https://sql.telemetry.mozilla.org/). * `pioneer` - The pings are encrypted and end up in the Pioneer processing pipeline. -* TBD: `custom-telemetry-events` - The pings end up in the ordinary destination for custom telemetry events (Not Yet Implemented) +* TODO: `event-telemetry` - The pings end up in the ordinary destination for event telemetry (Not Yet Implemented) ### `browser.studyDebug.*` [`browser.studyDebug` API documentation](./webExtensionApis/study/api.md) -Tools for writing tests, getting and resetting StudyUtils internals. +Used by the project-internal tests only. ## Engineering your own study add-on -* Check out [mozilla/shield-studies-addon-template/](https://github.com/mozilla/shield-studies-addon-template/) to start from. +* Check out [the official study add-on example](https://github.com/mozilla/normandy-nextgen-study-example) * Read [./docs/engineering.md](./docs/engineering.md) for development documentation aimed at study add-on engineers. -### DO NOT USE These Old Template Repositories - -Repositories that should not be used as templates for new studies: - -* NO. - A repository that was created in 2017 to help new Shield/Pioneer engineers to quickly get up and running with a Shield add-on, built upon an older and much more verbose add-on template. It's documentation has been ported to the official template repo. -* NO. - Despite its name, this repo is for static AMO consent pages and does not contain any template for Shield studies - ## Development on the Shield-Studies-Addon-Utils * Open an issue @@ -157,14 +88,18 @@ Repositories that should not be used as templates for new studies: * `npm test` must pass. * Read [./docs/development-on-the-utils.md](./docs/development-on-the-utils.md) for more in-depth development documentation. -## History of major versions +## History of recent major versions +* v6.0: Rip out most functionality, keeping only some high priority utils\* that neither the Normandy WebExtension API nor [the Nextgen study example](https://github.com/mozilla/normandy-nextgen-study-example) provides * v5.3: [Better study endings](https://github.com/mozilla/shield-studies-addon-utils/issues/246) and `browser.study.fullSurveyUrl()` * v5.2: Added Pioneer and Firefox 67 support * v5.1: Added preferences for testing overrides, study logger and other enhancements * v5: API exposed as a Web Extension Experiment. Minimal viable add-on example added. Test coverage improved. Test utils added. -* v4.1: Improved utils for common cases -* v4: First `.jsm` release for shipping studies as [legacy add-ons](https://developer.mozilla.org/Add-ons/Legacy_add_ons). Used packet format for PACKET version 3. (Jetpack / addon-sdk is not at all supported since v4 of this utils library) -* v3: Attempt to formalize on `shield-study` PACKET version 3. Jetpack based. Prototype used for `raymak/page-reload`. All work abandoned, and no formal npm release in this series. Work done at `v3-shield-packet-format` branch. LAST JETPACK (addon-sdk) RELEASE. -* v2: Code refactor to es6 `class` with event models. Added cli tooling. Packet format is still arbitrary and per-study. Jetpack based. Last used in studies in Q2 2017. -* v1: Initial work and thinking. Telemetry packets are rather arbitrary. Jetpack based. + +\* Some features that was handled in v5 has not been ported over to neither Normandy nor v6 of the utils: + +* expiry +* lifecycle telemetry (first seen, installed, exit etc) +* configurable endings (annotated exit telemetry and launching of exit surveys etc) +* telemetry testing flag specific to study telemetry (disable telemetry via about:config during testing instead) +* pref-controlled study-specific study logger (use ordinary add-on-scoped logging instead) diff --git a/bin/copyStudyUtils.js b/bin/copyStudyUtils.js index 9852340..c1258bc 100755 --- a/bin/copyStudyUtils.js +++ b/bin/copyStudyUtils.js @@ -9,7 +9,7 @@ const customHelp = ` # Additional hints ## cleanup - rm -rf /{study,prefs} + rm -rf /study `; function correctOutputDir(privilegedDirname) { diff --git a/docs/development-on-the-utils.md b/docs/development-on-the-utils.md index 42a2ab5..97d8573 100644 --- a/docs/development-on-the-utils.md +++ b/docs/development-on-the-utils.md @@ -5,110 +5,23 @@ **Contents** * [Development on the Utils](#development-on-the-utils) - * [Directory Highlights](#directory-highlights) - * [Build process overview: `npm run build`](#build-process-overview-npm-run-build) - * [Testing overview: `npm run test`](#testing-overview-npm-run-test) + * [Scripts](#scripts) * [Useful testing helpers.](#useful-testing-helpers) - * [FAQ](#faq) - * [File structure](#file-structure) * [Continuous Integration](#continuous-integration) * [Install cli to test Circle CI locally](#install-cli-to-test-circle-ci-locally) * [Validate Circle CI configuration](#validate-circle-ci-configuration) * [Run Circle CI locally (requires Docker)](#run-circle-ci-locally-requires-docker) * [NPM release routine](#npm-release-routine) +* [Misc](#misc) + * [Version history (continued from main readme)](#version-history-continued-from-main-readme) # Development on the Utils -## Directory Highlights +## Scripts -* `webExtensionApis/study` - -Firefox WebExtension Experiments APIs providing capabilities for study add-ons that are yet not available in the built-in WebExtension APIs - -* `testUtils/` - - Test utilities (helper classes to write functional/unit tests for your study add-on) - -* `examples/` - - Tested and verified example add-ons using the WebExtension Experiments APIs and test utilities - -``` -. -├── LICENSE -├── README.md -├── bin/ -├── docs/ -├── examples/ -│   └── small-study/ -├── misc/ -│   └── shield-study-helper-addon/ -├── package-lock.json -├── package.json -├── test/ -├── test-addon/ -├── testUtils/ -└── webExtensionApis/ - └── study/ - ├── api.js - ├── schema.json - ├── schema.yaml - ├── src/ - └── webpack.config.js -``` - -## Build process overview: `npm run build` - -Goal: create the `study/api.js` and `study/schema.json` files that implement the `browser.study` WEE interface, for use by WebExtension Add-ons. - -1. **Format** `eslint`, `prettier` all JavaScript code in all directories -2. **Bundle** `webExtensionApis/study/api.js`, the `browser.study` WEE interface. - -* `webpack` `study/src/*` into `study/api.js` - - * `study/src/index.js` contains the `getApi` call, as seen by webExtension add-ons. - * `study/src/studyUtils` is a conversion of the 'studyUtils.jsm' from v4, and contains most of the privileged code - * Tools for well-formatted Telemetry: - - * includes `ajv` for schema validation (for sending Telemetry) - * includes the Telemetry Parquet Shield Schemas from `shield-study-schemas/schemas-client/*` - -3. **Derive** `webExtensionApis/study/schema.json`, the `browser.study` WEE interface. - -Our toolchain for making schemas: `schema.yaml => {schema.json, api.md}` - -* `webExtensionApis/study/schema.yaml` is the canonical source. Using YAML allows easily multiline comments -* `npm run build:schema` - - - converts `schema.yaml => schema.json` - - validates that schema is probably a valid WEE schema. - - creates API docs `schema.yaml => docs/api.md` - -## Testing overview: `npm run test` - -(If you are looking for ideas about QA for your study add-on, see the FAQ.) - -Goal: Use `webdriver` to exercise the `browser.study` API to prove correctness. - -1. Builds and formats the API using `npm run build` -2. Copies the created WEE interface files into `test-addon/src/privileged/` -3. Build the `test-addon/` using `web-ext build`. This add-on creates a **detached panel**. Inside this panel is a context where `browser.study` will be useable. -4. Do tests: - - 1. `mocha` test runner uses files in `testUtils/` to - 2. Install the add-on (using `webdriver`) - 3. Switch context to the panel, so that we can exercise `browser.study`. The function that does this: `setupWebDriver` - 4. Run all tests. Most API tests are at: `test/functional/browser.study.api.js` - 5. Most tests are of this `Selenium`/`WebDriver`/`GeckoDriver` form: - - * run some async code in the panel context using `addonExec` - * in that code, exercise the `browser.study` API. - * callback with the results of `browser.study.setup()`, and/or `browser.studyDebug.getInternals()` as necessary. - * use `node` `assert` to check the called back result. - -**Note**: `browser.studyDebug.getInternals()` gets internals of the `studyUtils` singleton as needful. `browser.studyDebug` also allows other manipulation of the studyUtils singleton, for use by tests, and to induce states and reactions. +* `copyStudyUtils` shell command copying these files in your study add-on. ## Useful testing helpers. @@ -116,162 +29,9 @@ Goal: Use `webdriver` to exercise the `browser.study` API to prove correctness. * `SKIPLINT=1 npm run test` skips linting * `npm run test-only` skips build steps. -## FAQ - -* What's the deal with Webpack? - - * We want `api.js` to be one file, for ease of use by study authors - * We want the source to be broken up into logical pieces - * Firefox doesn't come with a usable JSONSchema library (`Schema.jsm` isn't very usable. - * We want Jsonschema validation to guard args, and to send Telemetry - * we use `webpack` to bundle src and AJV (jsonschema) into `api.js` - -* Why is testing so wack / smelly? - - * We don't know Firefox - - * We are ignorant about Mochitest, - * so we rebuilt a lot of things in Selenium / webDriver +## Troubleshooting error messages during execution of functional tests - * The things we are testing are mostly weird / hard add-on edge cases - * a lot of the code is to simulate weird things like add-on install / uninstall / startup / setup under weird combinations of conditions - -* What Telemetry is sent when? - - * firstrun only: `enter` - - * if (! allowEnroll) - - `ineligible` => `exit` then uninstall the add-on. - - * else: `install` - - * second and subsequent: - - * if (expired) - - `expire` => `exit` (then uninstall) - - * if (endStudy(reason)), then - - `ended-positive|ended-neutral|ended-negative` => `exit` - -* What is `allowEnroll` and other startup semantics? - - (See telemetry above) - - * IsFirstRun => user doesn't have the pref set for `{id}.firstRunTimestamp` - - * IF first run, then allowEnroll can make the user `ineligible` - -* Expiration - - * use [`browser.alarms`](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/alarms/create). See the `examples/small-study`. - * `browser.study.setup({expire: {days: 1}})` will help to calculate when to fire the alarm - -- Ending a study. - - * studies end when - - 1. you call `browser.study.endStudy` - 2. studies hit their `expire.days` after `firstRunTimestamp` - 3. user disables the study from `about:addons` - 4. Normandy revokes a study (which looks like `user-disable`, see #194) - - * In all cases (except the 'user-disable', see #194), the webExtension will see an `onEndStudy` if registered. It's up to the add-on to then open all endingUrls, and actually uninstall the study. - -- QA - - * put your 'jsm' files in `privileged` by convention. - * your add-on can use prefs to override the `testing` fields in a `studySetup` (to choose a variation). - * exercising all the study endings is hard. Ideas welcome. - * proving that your add-on doesn't regress performance is hard. Ideas welcome. - -## File structure - -``` -├── Dockerfile # Dockerfile possibly needed by CI -├── LICENSE -├── README.md -├── docs # Docs that were written for v4, needs updating to be relevant for v5 -│ ├── development-on-the-utils.md # Engineering docs for utils developers -│ ├── engineering.md # Engineering docs for study add-on developers -│ ├── survival.md # Doc that probably should be merged with engineering.md -│ └── tutorial.md # Doc that probably should be merged with engineering.md -├── examples # Should be: Tested and verified example add-ons using the WebExtension Experiments APIs and test utils -│ ├── minimal-viable-addon # <-- A place to put an example of a minimal viable add-on (if not the test-addon or the template will be used for this instead) -│ └── test-addon # Add-on used to test the apis and test utils -│ ├── bin -│ │ └── bundle-shield-studies-addon-utils.sh # The add-on's script for copying relevant files from the utils repo to the add-on (separate script instead of cramming this copying into package.json) -│ ├── dist # Where add-on builds are stored -│ │ └── shield_utils_test_add-on-1.0.0.zip -│ ├── src # The add-on / web extension that uses study utils -│ │ ├── background.js -│ │ ├── extension-page-for-tests # The extension page that pops up when running the test add-on - used by selenium to run extension-privileged js in the tests (for more info, see testUtils/executeJs.js -│ │ │ ├── index.html -│ │ │ └── page.js -│ │ ├── icons # An icon in the form of a shield -│ │ │ ├── LICENSE -│ │ │ └── shield-icon.svg -│ │ ├── manifest.json # The WebExtension manifest file -│ │ ├── privileged # WebExtension Experiments copied to the add-on by ../bin/bundle-shield-studies-addon-utils.sh (see further below for explanations) -│ │ │ ├── prefs -│ │ │ │ ├── api.js -│ │ │ │ └── schema.json -│ │ │ └── study -│ │ │ ├── api.js -│ │ │ └── schema.json -│ │ └── studySetup.js -│ ├── test -│ │ └── functional -│ │ ├── shield_utils_test.js -│ │ └── utils.js -│ └── web-ext-config.js -├── misc # Other possibly relevant helper utils / add-ons -│ └── shield-study-helper-addon # Legacy add-on that displays sent pings by add-ons using the util APIs -│ ├── addon -│ │ ├── bootstrap.js -│ │ ├── chrome.manifest -│ │ ├── install.rdf -│ │ └── webextension -│ │ ├── icon.png -│ │ ├── manifest.json -│ │ ├── qa.html -│ │ └── qa.js -│ ├── build.sh -│ ├── package-lock.json -│ ├── package.json -│ └── run-firefox.js -├── package-lock.json -├── package.json -├── testUtils # Test utils (helper classes to write functional/unit tests for your study add-on) -│ ├── executeJs.js -│ ├── nav.js -│ ├── pings.js -│ ├── setup.js -│ ├── ui.js -│ └── wip.js -└── webExtensionApis # Firefox WebExtension Experiments APIs providing capabilities for study add-ons that are yet not available in the built-in WebExtension APIs - ├── prefs # Allows your web extension add-on to set and read preferences. - │ ├── api.js - │ └── schema.json - └── study # The browser.study.* WebExtension API - see ./README.md for more information - ├── api.js # Built by webpack from the contents of the src/ directory - ├── schema.json # The WebExtension API schema - ├── src # Source code that gets bundled by webpack into api.js - │ ├── index.js # Exposes the WE API - │ ├── jsonschema.js # Logic for JSON schema validation - │ ├── sampling.js # Logic for choosing a variation - │ ├── schemas # Schemas used by this API - │ │ ├── index.js - │ │ ├── schema.studySetup.json - │ │ └── schema.weightedVariations.json - │ ├── studyUtils.js # The former StudyUtils.in.jsm file from v4 - │ └── studyUtilsBootstrap.js # The logic that was previously addon/bootstrap.js in the template repo - └── webpack.config.js # Webpack configuration for bundling/building the study API's api.js file - ->> tree -a -I 'node_modules|.git|.DS_Store' -``` +Sometimes Selenium just comes back with `JavascriptError: Error: An unexpected error occurred`. In these cases (and others) it may be useful to check the contents of `test/results/logs/geckodriver.log` for hints of what code was last attempted to be executed, then manually attempt to run that same lines of code in the browser console / add-on toolbox console. Unfortunately, web extension experiments are notorious for failing silently or with minimal information about the actual error. Use plenty of try/catch clauses and logging to track down what code is causing an error. Many times it may be incorrect invocations of web extension experiment API methods (or other methods) that may be causing poorly explained error messages. # Continuous Integration @@ -307,3 +67,13 @@ Note: Steps related to caching and uploading/storing artifacts will report as fa npx publish-please --dry-run npx publish-please + +# Misc + +## Version history (continued from main readme) + +* v4.1: Improved utils for common cases +* v4: First `.jsm` release for shipping studies as [legacy add-ons](https://developer.mozilla.org/Add-ons/Legacy_add_ons). Used packet format for PACKET version 3. (Jetpack / addon-sdk is not at all supported since v4 of this utils library) +* v3: Attempt to formalize on `shield-study` PACKET version 3. Jetpack based. Prototype used for `raymak/page-reload`. All work abandoned, and no formal npm release in this series. Work done at `v3-shield-packet-format` branch. LAST JETPACK (addon-sdk) RELEASE. +* v2: Code refactor to es6 `class` with event models. Added cli tooling. Packet format is still arbitrary and per-study. Jetpack based. Last used in studies in Q2 2017. +* v1: Initial work and thinking. Telemetry packets are rather arbitrary. Jetpack based. diff --git a/docs/engineering.md b/docs/engineering.md index 4cf879b..7ee34c0 100644 --- a/docs/engineering.md +++ b/docs/engineering.md @@ -1,6 +1,4 @@ -# Engineering Shield Study Add-ons - -There are many moving parts in engineering a Shield Study Add-on. This document describes general Shield Study Add-on engineering and is aimed at add-on engineers. (To improve the utils in this repo, see [Development on the Utils](./development-on-the-utils.md) instead). +# Engineering @@ -8,54 +6,25 @@ There are many moving parts in engineering a Shield Study Add-on. This document **Contents** -* [Help and support](#help-and-support) -* [Links](#links) -* [Writing tests for your study add-on](#writing-tests-for-your-study-add-on) -* [FAQ](#faq) -* [Other hints / guidelines](#other-hints--guidelines) +* [Engineering Study Add-ons](#engineering-study-add-ons) + * [Note: DO NOT USE These Old Template Repositories](#note-do-not-use-these-old-template-repositories) +* [Engineering the Utils](#engineering-the-utils) -## Help and support - -Thinking about building a Shield/Study Add-on? Go to #shield in Slack and discuss first (there may be quicker and cheaper ways to run your experiment without building an add-on). Building one already? Join #shield-engineering in Slack and ask away. - -If you haven't checked out [the template](https://github.com/mozilla/shield-studies-addon-template) yet, do it. It contains a lot of best practices that helps study add-ons pass QA quicker. - -## Links - -* [Shield article on Mozilla Wiki](https://wiki.mozilla.org/Firefox/Shield) -* [Shield Studies article on Mozilla Wiki](https://wiki.mozilla.org/Firefox/Shield/Shield_Studies) -* [WebExtension Experiment documentation](https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/index.html) - -## Writing tests for your study add-on - -[The template](https://github.com/mozilla/shield-studies-addon-template) includes examples of unit tests and functional tests. After cloning the template, remove the example tests except https://github.com/mozilla/shield-studies-addon-template/blob/develop/test/functional/0-study_utils_integration.js, which is meant to remain in your study-specific add-on since it verifies that the study utils integration is working as expected. - -Unit tests currently can ONLY test helper methods in static classes, like Feature in feature.js. The karma tests are run without any access to browser.\* web extension API:s (since we have no way for Karma to run in a privileged WebExtension context at the moment). Thus, make sure to only test static helper methods in unit tests. Other tests needs to be written as functional tests. (There IS a way to write functional tests that act like unit tests, probing the privileged web extension APIs more or less directly, but it is ugly: https://github.com/mozilla/shield-studies-addon-utils/issues/125#issuecomment-379180930) - -## FAQ - -> Q: Are there any re-usable patterns for common study use cases? - -Some are in [the template](https://github.com/mozilla/shield-studies-addon-template), but most of the time, they are only found throughout specific implementations. See https://github.com/mozilla/shield-studies-addon-utils/issues/239 for a growing list of study add-ons. - -(Study authors: please contribute back to the template or in other ways make useful patterns accessible for other study authors, thanks.) - -> Q: Is there any way to install my testing extension before starting the Browser? I want to observe the behavior of my extension when people start the browser with the extension installed. +## Engineering Study Add-ons -A: Not yet, but @glind started some work-in-progress code on https://github.com/mozilla/shield-studies-addon-utils/pull/245 - feel free to expand on it and see if you can get it to work. it would be a valuable contribution for others - see https://github.com/mozilla/shield-studies-addon-utils/issues/143. +Study add-on engineers, please refer to the Official Engineering Documentation: https://docs.telemetry.mozilla.org/cookbooks/client_guidelines.html -> Q: Since every time I receive "ADDON_UNINSTALL" after shutdown browser if I use "$web-ext run" to test my extension. I want to know whether the " browser.study.onEndStudy" would be triggered when user close the browser? or it just triggers the ExtensionAPI::onShutdown()? +Use the V5 branch of the utils (preferably starting from [mozilla/shield-studies-addon-template/](https://github.com/mozilla/shield-studies-addon-template/)) to create [Shield and Pioneer Add-on Experiments](https://mana.mozilla.org/wiki/display/FIREFOX/Pref-Flip+and+Add-On+Experiments) that manage their own life-cycle. -A The " browser.study.onEndStudy" should not be triggered when the user closes the browser - only when the extension has expired or the study has ended in some other way. If this is not the case, please report an issue against https://github.com/mozilla/shield-studies-addon-utils. +### Note: DO NOT USE These Old Template Repositories -> Q: I'm planning to send my custom ping back to server, do I need to apply any form or create any kind of scheme for my custom ping? +Repositories that should not be used as templates for new studies: -A: Use custom telemetry events if you have to roll your own pings. The fastest way for study add-ons however is to use `browser.study.sendTelemetry( payload )` to send telemetry (see this example: https://github.com/mozilla/shield-studies-addon-template/blob/develop/src/feature.js#L40-L42 - note that no telemetry is sent from privileged code - instead: use events to signal to the web extension layer to send the telemetry payloads). the telemetry will end up in shield study parquet. the compromise (for not having to submit a custom schema) is that the payload needs to be a flat object with string keys and string values. +* NO. - A repository that was created in 2017 to help new Shield/Pioneer engineers to quickly get up and running with a Shield add-on, built upon an older and much more verbose add-on template. It's documentation has been ported to the official template repo. +* NO. - Despite its name, this repo is for static AMO consent pages and does not contain any template for Shield studies -## Other hints / guidelines +## Engineering the Utils -* Use empty constructors in feature.js. No study-specific code should be instantiated in feature.js constructor methods. Leave constructors empty and instead instantiate feature logic feature.configure(). This way, we can ensure that there are no side-effects of the study add-on unless the study is confirmed to be eligible to run for the client. -* We put all the privileged code in `src/privileged` to make it easy for QA -* The 'Firefox privileged' modules cannot use webExtension API:s (`browserAction`, `management`, etc.). Use a `background.js` script (using messages and events) to co-ordinate multiple privileged modules. +To improve the utils in this repo, see [Development on the Utils](./development-on-the-utils.md). diff --git a/examples/small-study/.gitignore b/examples/small-study/.gitignore deleted file mode 100644 index 34112f8..0000000 --- a/examples/small-study/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -dist/* -node_modules/ diff --git a/examples/small-study/README.md b/examples/small-study/README.md deleted file mode 100644 index c515f0e..0000000 --- a/examples/small-study/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# An example `small-study` - -## files - -``` -. -├── README.md -├── dist/ # `web-ext build` output -├── package-lock.json -├── package.json -├── src/ -│   ├── studySetup.js # mostly declarative study config -│   ├── background.js # main script implementing addon -│   ├── icons/ -│   │   ├── LICENSE -│   │   └── shield-icon.svg -│   ├── manifest.json -│   └── privileged/ # `npm run bundle-utils` copies `browser.study` api here. -└── web-ext-config.js -``` - -## setup / install - -``` -npm install -g web-ext - -# rebuilds the utils from source then copies them in. -npm install -``` - -## start the study web extension experiment (WEE) - -``` -npm start # web-ext run -``` - -## short description flow and description - -1. `manifest.json` maps `experiment_apis` to make lazy getters at `browser.study` -2. Background loads - - * `studySetup.js`, a mostly declarative configuration for the study. - * `background.js` which runs both the feature (a button / browserAction) and the `browser.study` lifecycle events - -3. `background.js:StudyLifeCycleHandler` tracks a little logic. - - * `browser.study.onEndStudy` is watched BEFORE we setup - * `browser.study.setup(...)` does the setup, and handles the complex logic of startup / firstRun / shouldAllowEnroll - -## Next Steps - -1. Get help from the Weird Science Team (#shield on Slack) -2. Move on to the more complete [mozilla/shield-studies-addon-template] -3. Edit things, goof around, try other aspects of the API. diff --git a/examples/small-study/dist/.gitignore b/examples/small-study/dist/.gitignore deleted file mode 100644 index aca2417..0000000 --- a/examples/small-study/dist/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!*.gitignore diff --git a/examples/small-study/package-lock.json b/examples/small-study/package-lock.json deleted file mode 100644 index f415454..0000000 --- a/examples/small-study/package-lock.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "small-study", - "version": "1.0.0", - "lockfileVersion": 1 -} diff --git a/examples/small-study/package.json b/examples/small-study/package.json deleted file mode 100644 index b92c967..0000000 --- a/examples/small-study/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "small-study", - "version": "1.0.0", - "description": "A tiny example study using the studyUtils", - "main": "", - "scripts": { - "bundle-utils": "../../bin/copyStudyUtils.js src/privileged", - "postinstall": "npm run rebuild", - "rebuild": "(cd ../../ && npm run build) && npm run bundle-utils", - "start": "web-ext run" - }, - "author": "", - "license": "ISC", - "dependencies": {}, - "engines": { - "npm": "^6.1.0" - } -} diff --git a/examples/small-study/src/.eslintrc.js b/examples/small-study/src/.eslintrc.js deleted file mode 100644 index 8ef4351..0000000 --- a/examples/small-study/src/.eslintrc.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-env node */ - -"use strict"; - -module.exports = { - env: { - es6: true, - webextensions: true, - }, - rules: { - "no-console": "off", - }, -}; diff --git a/examples/small-study/src/background.js b/examples/small-study/src/background.js deleted file mode 100644 index 2cd81ca..0000000 --- a/examples/small-study/src/background.js +++ /dev/null @@ -1,164 +0,0 @@ -/* global getStudySetup */ - -/** - * Goal: Implement an instrumented feature using `browser.study` API - * - * Every runtime: - * - Prepare - * - * - listen for `onEndStudy` (study endings) - * - listen for `study.onReady` - * - * - Startup the feature - * - * - attempt to `browser.study.setup` the study using our studySetup - * - * - will fire EITHER - * - `endStudy` (`expired`, `ineligible`) - * - onReady - * - (see docs for `browser.study.setup`) - * - * - onReady: configure the feature to match the `variation` study selected - * - or, if we got an `onEndStudy` cleanup and uninstall. - * - * During the feature: - * - `sendTelemetry` to send pings - * - `endStudy` to force an ending (for positive or negative reasons!) - * - * Interesting things to try next: - * - `browser.study.validateJSON` your pings before sending - * - `endStudy` different endings in response to user action - * - force an override of setup.testing to choose branches. - * - */ - -class StudyLifeCycleHandler { - /** - * Listen to onEndStudy, onReady - * `browser.study.setup` fires onReady OR onEndStudy - * - * call `this.enableFeature` to actually do the feature/experience/ui. - */ - constructor() { - /* - * IMPORTANT: Listen for `onEndStudy` before calling `browser.study.setup` - * because: - * - `setup` can end with 'ineligible' due to 'allowEnroll' key in first session. - * - */ - browser.study.onEndStudy.addListener(this.handleStudyEnding.bind(this)); - browser.study.onReady.addListener(this.enableFeature.bind(this)); - } - - /** - * Cleanup - * - * (If you have privileged code, you might need to clean - * that up as well. - * See: https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/lifecycle.html - * - * @returns {undefined} - */ - async cleanup() { - // do whatever work your addon needs to clean up - } - - /** - * - * side effects - * - set up expiration alarms - * - make feature/experience/ui with the particular variation for this user. - * - * @param {object} studyInfo browser.study.studyInfo object - * - * @returns {undefined} - */ - async enableFeature(studyInfo) { - await browser.study.logger.log(["Enabling experiment", studyInfo]); - const { delayInMinutes } = studyInfo; - if (delayInMinutes !== undefined) { - const alarmName = `${browser.runtime.id}:studyExpiration`; - const alarmListener = async alarm => { - if (alarm.name === alarmName) { - browser.alarms.onAlarm.removeListener(alarmListener); - await browser.study.endStudy("expired"); - } - }; - browser.alarms.onAlarm.addListener(alarmListener); - browser.alarms.create(alarmName, { - delayInMinutes, - }); - } - feature.configure(studyInfo); - } - - /** handles `study:end` signals - * - * - opens 'ending' urls (surveys, for example) - * - calls cleanup - * - * @param {object} ending An ending result - * - * @returns {undefined} - */ - async handleStudyEnding(ending) { - await browser.study.logger.log([`Study wants to end:`, ending]); - for (const url of ending.urls) { - await browser.tabs.create({ url }); - } - switch (ending.endingName) { - // could have different actions depending on positive / ending names - default: - await browser.study.logger.log(`The ending: ${ending.endingName}`); - await this.cleanup(); - break; - } - // actually remove the addon. - await browser.study.logger.log("About to actually uninstall"); - return browser.management.uninstallSelf(); - } -} - -/* An example feature singleton, demonstrating Telemetry and some endings */ -class ButtonFeature { - constructor() {} - - async configure(studyInfo) { - let clicksInSession = 0; - browser.browserAction.setBadgeText({ text: "" + clicksInSession }); - - browser.browserAction.onClicked.addListener(() => { - clicksInSession++; - browser.browserAction.setBadgeText({ text: "" + clicksInSession }); - - // see the telemetry appear in `about:Telemetry`, as string:string - browser.study.sendTelemetry({ clicksInSession: "" + clicksInSession }); - if (clicksInSession >= 3) { - browser.study.endStudy("user-used-the-feature"); - } - }); - await browser.study.logger.log([ - `Setting the browser action title to the variation name: '${ - studyInfo.variation.name - }'`, - ]); - await browser.browserAction.setTitle({ title: studyInfo.variation.name }); - } -} - -// construct. will be configured after setup. -const feature = new ButtonFeature(); - -/** - * Run every startup to get config and instantiate the feature - * - * @returns {undefined} - */ -async function onEveryExtensionLoad() { - new StudyLifeCycleHandler(); - - const studySetup = await getStudySetup(); - await browser.study.logger.log(["Study setup: ", studySetup]); - await browser.study.setup(studySetup); -} -onEveryExtensionLoad(); diff --git a/examples/small-study/src/icons/LICENSE b/examples/small-study/src/icons/LICENSE deleted file mode 100644 index fcd8e26..0000000 --- a/examples/small-study/src/icons/LICENSE +++ /dev/null @@ -1 +0,0 @@ -All icons are public domain and came from https://openclipart.org/. diff --git a/examples/small-study/src/icons/shield-icon.svg b/examples/small-study/src/icons/shield-icon.svg deleted file mode 100644 index 3ad3e5f..0000000 --- a/examples/small-study/src/icons/shield-icon.svg +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - Openclipart - - - Shield Icon - 2010-09-19T03:15:30 - Here is an icon depicting a shield bearing a star. Use it to depict security, strength etc. Easily modifiable to incorporate a different emblem such as a sword. Enjoy! - https://openclipart.org/detail/85567/shield-icon-by-marricklip14 - - - marricklip14 - - - - - Emblem - Icon Star - Security - Shield - Strength - - - - - - - - - - - diff --git a/examples/small-study/src/manifest.json b/examples/small-study/src/manifest.json deleted file mode 100644 index aeb592a..0000000 --- a/examples/small-study/src/manifest.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "A Small Shield Add-on", - "description": "Demo of shield-studies-addon-utils", - "version": "1.0.0", - "manifest_version": 2, - "hidden": true, - "applications": { - "gecko": { - "id": "shield-utils-small-study-demo@shield.mozilla.org", - "strict_min_version": "60.0" - } - }, - "experiment_apis": { - "study": { - "schema": "./privileged/study/schema.json", - "parent": { - "scopes": ["addon_parent"], - "script": "./privileged/study/api.js", - "paths": [["study"]] - } - } - }, - "permissions": ["storage", "alarms"], - "background": { - "scripts": ["studySetup.js", "background.js"] - }, - "icons": { - "48": "icons/shield-icon.svg" - }, - "browser_action": { - "browser_style": true, - "default_icon": "icons/shield-icon.svg", - "default_title": "Test" - } -} diff --git a/examples/small-study/src/privileged/.gitignore b/examples/small-study/src/privileged/.gitignore deleted file mode 100644 index 8c6859a..0000000 --- a/examples/small-study/src/privileged/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# ignore APIs that are bundled from shield-studies-addon-utils -study/ - diff --git a/examples/small-study/src/studySetup.js b/examples/small-study/src/studySetup.js deleted file mode 100644 index f1610c5..0000000 --- a/examples/small-study/src/studySetup.js +++ /dev/null @@ -1,175 +0,0 @@ -/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "getStudySetup" }]*/ - -/** - * Overview: - * - * - constructs a well-formatted `studySetup` for use by `browser.study.setup` - * - mostly declarative, except that some fields are set at runtime - * asynchronously. - * - * Advanced features: - * - testing overrides from preferences - * - expiration time - * - some user defined endings. - * - study defined 'shouldAllowEnroll' logic. - */ - -/** Base for studySetup, as used by `browser.study.setup`. - * - * Will be augmented by 'getStudySetup' - */ -const baseStudySetup = { - // used for activeExperiments tagging (telemetryEnvironment.setActiveExperiment) - activeExperimentName: browser.runtime.id, - - // use either "shield" or "pioneer" telemetry semantics and data pipelines - studyType: "shield", - - // telemetry - telemetry: { - // Actually submit the pings to Telemetry. [default if omitted: false] - send: true, - // Marks pings with testing=true. Set flag to `true` for pings are meant to be seen by analysts [default if omitted: false] - removeTestingFlag: false, - // Keep an internal telemetry archive. Useful for verifying payloads of Pioneer studies without risking actually sending any unencrypted payloads [default if omitted: false] - internalTelemetryArchive: false, - }, - - // endings with urls - endings: { - /** normandy-defined endings - https://firefox-source-docs.mozilla.org/toolkit/components/normandy/normandy/data-collection.html */ - "install-failure": { - baseUrls: [], - }, - "individual-opt-out": { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=individual-opt-out", - ], - }, - "general-opt-out": { - baseUrls: [], - }, - "recipe-not-seen": { - baseUrls: [], - }, - uninstalled: { - baseUrls: [], - }, - "uninstalled-sideload": { - baseUrls: [], - }, - unknown: { - baseUrls: [], - }, - /** study-utils-defined endings */ - "user-disable": { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=user-disable", - ], - }, - ineligible: { - baseUrls: [], - }, - expired: { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=expired", - ], - }, - - /** Study specific endings */ - "user-used-the-feature": { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=user-used-the-feature", - ], - category: "ended-positive", - }, - "hated-the-feature": { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=hated-the-feature", - ], - category: "ended-negative", - }, - }, - - // Study branches and sample weights, overweighing feature branches - weightedVariations: [ - { - name: "feature-active", - weight: 1.5, - }, - { - name: "feature-passive", - weight: 1.5, - }, - { - name: "control", - weight: 1, - }, - ], - - // maximum time that the study should run, from the first run - expire: { - days: 14, - }, -}; - -/** - * Determine, based on common and study-specific criteria, if enroll (first run) - * should proceed. - * - * False values imply that *during first run only*, we should endStudy(`ineligible`) - * - * Add your own enrollment criteria as you see fit. - * - * (Guards against Normandy or other deployment mistakes or inadequacies). - * - * This implementation caches in local storage to speed up second run. - * - * @param {object} studySetup A complete study setup object - * @returns {Promise} answer An boolean answer about whether the user should be - * allowed to enroll in the study - */ -async function cachingFirstRunShouldAllowEnroll(studySetup) { - // Cached answer. Used on 2nd run - let allowed = await browser.storage.local.get("allowedEnrollOnFirstRun"); - if (allowed.allowedEnrollOnFirstRun === true) return true; - - /* - First run, we must calculate the answer. - If false, the study will endStudy with 'ineligible' during `setup` - */ - - // could have other reasons to be eligible, such add-ons, prefs - const dataPermissions = await browser.study.getDataPermissions(); - if (studySetup.studyType === "shield") { - allowed = dataPermissions.shield; - } - if (studySetup.studyType === "pioneer") { - allowed = dataPermissions.pioneer; - } - - // cache the answer - await browser.storage.local.set({ allowedEnrollOnFirstRun: allowed }); - return allowed; -} - -/** - * Augment declarative studySetup with any necessary async values - * - * @return {object} studySetup A complete study setup object - */ -async function getStudySetup() { - // shallow copy - const studySetup = Object.assign({}, baseStudySetup); - - studySetup.allowEnroll = await cachingFirstRunShouldAllowEnroll(studySetup); - - const testingOverrides = await browser.study.getTestingOverrides(); - studySetup.testing = { - variationName: testingOverrides.variationName, - firstRunTimestamp: testingOverrides.firstRunTimestamp, - expired: testingOverrides.expired, - }; - - return studySetup; -} diff --git a/examples/small-study/web-ext-config.js b/examples/small-study/web-ext-config.js deleted file mode 100644 index fbce17b..0000000 --- a/examples/small-study/web-ext-config.js +++ /dev/null @@ -1,20 +0,0 @@ -/* eslint-env node */ - -const defaultConfig = { - // Global options: - sourceDir: "./src/", - artifactsDir: "./dist/", - ignoreFiles: [".DS_Store"], - // Command options: - build: { - overwriteDest: true, - }, - run: { - firefox: process.env.FIREFOX_BINARY || "nightly", - browserConsole: true, - startUrl: ["about:debugging"], - pref: ["shieldStudy.logLevel=All"], - }, -}; - -module.exports = defaultConfig; diff --git a/misc/shield-study-helper-addon/.gitignore b/misc/shield-study-helper-addon/.gitignore deleted file mode 100644 index 99a4a1c..0000000 --- a/misc/shield-study-helper-addon/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -*.xpi diff --git a/misc/shield-study-helper-addon/addon/bootstrap.js b/misc/shield-study-helper-addon/addon/bootstrap.js deleted file mode 100644 index 16490e2..0000000 --- a/misc/shield-study-helper-addon/addon/bootstrap.js +++ /dev/null @@ -1,95 +0,0 @@ -"use strict"; - -/* global __SCRIPT_URI_SPEC__, Feature, studyUtils, config */ -/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "(startup|shutdown|install|uninstall)" }]*/ - -async function getTelemetryPings(options) { - // type is String or Array - const { n, timestamp, headersOnly } = options; - let { type } = options; - Components.utils.import("resource://gre/modules/TelemetryArchive.jsm"); - // {type, id, timestampCreated} - let pings = await TelemetryArchive.promiseArchivedPingList(); - if (type) { - if (!(type instanceof Array)) { - type = [type]; // Array-ify if it's a string - } - } - if (type) pings = pings.filter(p => type.includes(p.type)); - if (timestamp) pings = pings.filter(p => p.timestampCreated > timestamp); - - pings.sort((a, b) => b.timestampCreated - a.timestampCreated); - if (n) pings = pings.slice(0, n); - const pingData = headersOnly - ? pings - : pings.map(ping => TelemetryArchive.promiseArchivedPingById(ping.id)); - return Promise.all(pingData); -} - -async function pingsReport() { - async function getPings() { - const ar = ["shield-study", "shield-study-addon"]; - return getTelemetryPings({ type: ar }); - } - - const pings = (await getPings()).reverse(); - if (pings.length === 0) { - return { report: "No pings found" }; - } - const p0 = pings[0].payload; - // print common fields - const report = - ` -// common fields - -branch ${p0.branch} // should describe Question text -study_name ${p0.study_name} -addon_version ${p0.addon_version} -version ${p0.version} - -` + - pings - .map( - (p, i) => `${i} ${p.creationDate} ${p.payload.type} -${JSON.stringify(p.payload.data, null, 2)} - -`, - ) - .join("\n"); - - return { report }; - // pings.forEach(p=>{ - // console.log(p.creationDate, p.payload.type); - // console.log(JSON.stringify(p.payload.data,null,2)) - // }) -} - -async function listenFromWebExtension(msg, sender, sendResponse) { - // await pingsReport(); - console.log(`got ${msg}`); - // pingsReport().then( - // r=>{ - // console.log(`sendResponse! ${JSON.stringify({report: r})}`); - // sendResponse({report: r}) - // } - // ); - - // NOT FINE. - // const a = await Promise.resolve({"report": "A report"}) - // sendResponse(a); - // sendResponse(Promise.resolve({"report": "A report"})); - sendResponse(Promise.resolve(pingsReport())); - // sendResponse(pingsReport().then(r=>{"report": r})); - return false; -} - -async function startup(addonData) { - console.log("starting up debugger"); - const webExtension = addonData.webExtension; - webExtension.startup().then(api => { - const { browser } = api; - // messages intended for shieldn: {shield:true,msg=[info|endStudy|telemetry],data=data} - browser.runtime.onMessage.addListener(listenFromWebExtension); - // other message handlers from your addon, if any - }); -} diff --git a/misc/shield-study-helper-addon/addon/chrome.manifest b/misc/shield-study-helper-addon/addon/chrome.manifest deleted file mode 100644 index 7bd5f84..0000000 --- a/misc/shield-study-helper-addon/addon/chrome.manifest +++ /dev/null @@ -1 +0,0 @@ -content qa-shield-study-helper-icons ./webextension/ diff --git a/misc/shield-study-helper-addon/addon/install.rdf b/misc/shield-study-helper-addon/addon/install.rdf deleted file mode 100644 index 83ed216..0000000 --- a/misc/shield-study-helper-addon/addon/install.rdf +++ /dev/null @@ -1,32 +0,0 @@ - - - - @qa-shield-study-helper - 2 - true - true - true - false - 1.0.0 - QA Shield Study Ping and Config Helper - Display pings and other useful things for shield-study addons - - glind@mozilla.com - chrome://qa-shield-study-helper-icons/content/icon.png - - - {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - 55.0 - * - - - - - - {aa3c5121-dab2-40e2-81ca-7ea25febc110} - 55.0 - * - - - - diff --git a/misc/shield-study-helper-addon/addon/webextension/.eslintrc.json b/misc/shield-study-helper-addon/addon/webextension/.eslintrc.json deleted file mode 100644 index 5c7cc9e..0000000 --- a/misc/shield-study-helper-addon/addon/webextension/.eslintrc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "env": { - "browser": true, - "es6": true, - "webextensions": true - }, - "extends": ["eslint:recommended"], - "rules": { - "no-console": "warn" - } -} diff --git a/misc/shield-study-helper-addon/addon/webextension/icon.png b/misc/shield-study-helper-addon/addon/webextension/icon.png deleted file mode 100644 index c70ca4e..0000000 Binary files a/misc/shield-study-helper-addon/addon/webextension/icon.png and /dev/null differ diff --git a/misc/shield-study-helper-addon/addon/webextension/manifest.json b/misc/shield-study-helper-addon/addon/webextension/manifest.json deleted file mode 100644 index b8aad45..0000000 --- a/misc/shield-study-helper-addon/addon/webextension/manifest.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "QA Shield Study button", - "version": "1.0.0", - "manifest_version": 2, - "browser_action": { - "browser_style": true, - "default_title": "QA Shield Study", - "default_popup": "qa.html", - "default_icon": { - "64": "icon.png" - } - }, - "icons": { - "64": "icon.png" - } -} diff --git a/misc/shield-study-helper-addon/addon/webextension/qa.html b/misc/shield-study-helper-addon/addon/webextension/qa.html deleted file mode 100644 index 91bd022..0000000 --- a/misc/shield-study-helper-addon/addon/webextension/qa.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - -
Ran at:
-
-    Here is the report
-  
- - - - diff --git a/misc/shield-study-helper-addon/addon/webextension/qa.js b/misc/shield-study-helper-addon/addon/webextension/qa.js deleted file mode 100644 index d9f3142..0000000 --- a/misc/shield-study-helper-addon/addon/webextension/qa.js +++ /dev/null @@ -1,41 +0,0 @@ -const PLACEHOLDER = ` - -PLACEHOLDER PING REPORT - -A full new report that -has a bunch of pings and stuff - -`; - -function printReport(text) { - console.log(`about to replace: ${text}`); - document.querySelector("#timestamp").textContent = `${new Date()}`; - document.querySelector("#qa").textContent = text; -} - -async function tryReportFromFirefox() { - console.log(`has browser runtime? ${browser.runtime}`); - if (browser.runtime) { - const reply = await browser.runtime.sendMessage("qa-report"); - console.log("got reply!", reply); - if (reply) { - printReport(reply.report); - //console.log("response from legacy add-on: " + reply.content); - } - } -} - -function startup() { - printReport(PLACEHOLDER); - console.log("asking firefox"); - tryReportFromFirefox(); -} - -/* - -page starts up. -- attempt to get text from firefox -- once it arrives, insert it. -*/ - -document.addEventListener("DOMContentLoaded", startup); diff --git a/misc/shield-study-helper-addon/build.sh b/misc/shield-study-helper-addon/build.sh deleted file mode 100755 index a2d684b..0000000 --- a/misc/shield-study-helper-addon/build.sh +++ /dev/null @@ -1,21 +0,0 @@ - -echo "$@" - -set -eu -#set -o xtrace - -BASE_DIR="$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")" -#TMP_DIR="$(mktemp -d)" -#DEST="${TMP_DIR}/addon" -ADDON_VERSION=$(node -p -e "require('./package.json').version"); -ADDON_ID=$(node -p -e "require('./package.json').addon.id") -XPI_NAME="${ADDON_ID}-${ADDON_VERSION}".xpi - -pushd addon > /dev/null -zip -r "../${XPI_NAME}" . -popd > /dev/null - -rm -f linked-addon.xpi -ln -s "${XPI_NAME}" linked-addon.xpi -echo "SUCCESS: xpi at ${XPI_NAME}" -echo "SUCCESS: symlinked xpi at linked-addon.xpi" diff --git a/misc/shield-study-helper-addon/package-lock.json b/misc/shield-study-helper-addon/package-lock.json deleted file mode 100644 index 5a8f949..0000000 --- a/misc/shield-study-helper-addon/package-lock.json +++ /dev/null @@ -1,244 +0,0 @@ -{ - "name": "shield-study-helper-addon", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "core-js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", - "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "es6-promise": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", - "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "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.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "jszip": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.4.tgz", - "integrity": "sha512-z6w8iYIxZ/fcgul0j/OerkYnkomH8BZigvzbxVmr2h5HkZUrPtk2kjYtLkqR9wwQxEP6ecKNoKLsbhd18jfnGA==", - "dev": true, - "requires": { - "core-js": "2.3.0", - "es6-promise": "3.0.2", - "lie": "3.1.1", - "pako": "1.0.6", - "readable-stream": "2.0.6" - } - }, - "lie": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", - "dev": true, - "requires": { - "immediate": "3.0.6" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.8" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "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=", - "dev": true - }, - "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "7.1.2" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "selenium-webdriver": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", - "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", - "dev": true, - "requires": { - "jszip": "3.1.4", - "rimraf": "2.6.2", - "tmp": "0.0.30", - "xml2js": "0.4.19" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "tmp": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", - "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", - "dev": true, - "requires": { - "os-tmpdir": "1.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "dev": true, - "requires": { - "sax": "1.2.4", - "xmlbuilder": "9.0.4" - } - }, - "xmlbuilder": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz", - "integrity": "sha1-UZy0ymhtAFqEINNJbz8MruzKWA8=", - "dev": true - } - } -} diff --git a/misc/shield-study-helper-addon/package.json b/misc/shield-study-helper-addon/package.json deleted file mode 100644 index baa9b24..0000000 --- a/misc/shield-study-helper-addon/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "shield-study-helper-addon", - "version": "1.0.0", - "description": "", - "main": "bootstrap.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "build": "bash build.sh", - "prefirefox": "npm run build", - "firefox": "XPI=linked-addon.xpi node run-firefox.js" - }, - "author": "", - "license": "ISC", - "devDependencies": { - "selenium-webdriver": "^3.6.0" - }, - "addon": { - "id": "@qa-shield-study-helper" - } -} diff --git a/misc/shield-study-helper-addon/run-firefox.js b/misc/shield-study-helper-addon/run-firefox.js deleted file mode 100644 index 6dbacc0..0000000 --- a/misc/shield-study-helper-addon/run-firefox.js +++ /dev/null @@ -1,59 +0,0 @@ -/* eslint-env node */ - -/* This file is a helper script that will install the extension from the .xpi - * file and setup useful preferences for debugging. This is the same setup - * that the automated Selenium-Webdriver/Mocha tests run, except in this case - * we can manually interact with the browser. - * NOTE: If changes are made, they will not be reflected in the browser upon - * reloading, as the .xpi file has not been recreated. - */ - -require("geckodriver"); - -// Note: Geckodriver already has quite a good set of default preferences -// for disabling various items. -// https://github.com/mozilla/geckodriver/blob/master/src/marionette.rs -const FIREFOX_PREFERENCES = { - // Ensure e10s is turned on. - "browser.tabs.remote.autostart": true, - "browser.tabs.remote.autostart.1": true, - "browser.tabs.remote.autostart.2": true, - // These are good to have set up if you're debugging tests with the browser - // toolbox. - "devtools.chrome.enabled": true, - "devtools.debugger.remote-enabled": true, - "devtools.debugger.prompt-connection": false, - "general.warnOnAboutConfig": false, - - "extensions.legacy.enabled": true, - - // WARNING: also of interest, gecko webdriver sets many prefs at: - // https://dxr.mozilla.org/mozilla-central/source/testing/geckodriver/src/prefs.rs - // INCLUDING - // ("toolkit.telemetry.server", Pref::new("https://%(server)s/dummy/telemetry/")), -}; - -// Re-usable test methods from shield-studies-addon-utils -const { nav } = require("../../testUtils/nav"); -const { setup } = require("../../testUtils/setup"); - -const utils = { - FIREFOX_PREFERENCES, - nav, - setup, -}; - -(async() => { - try { - console.log("Starting up firefox"); - const driver = await utils.setup.promiseSetupDriver( - utils.FIREFOX_PREFERENCES, - ); - console.log("Load temporary addon."); - await utils.setup.installAddon(driver); - // navigate to a regular page - utils.nav.gotoURL(driver, "about:debugging"); - } catch (e) { - console.error(e); // eslint-disable-line no-console - } -})(); diff --git a/package-lock.json b/package-lock.json index 9e2a581..fdb266b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,66 @@ { "name": "shield-studies-addon-utils", - "version": "5.3.0", + "version": "6.0.0", "lockfileVersion": 1, "requires": true, "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==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + } + } + }, + "@babel/polyfill": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.7.0.tgz", + "integrity": "sha512-/TS23MVvo34dFmf8mwCisCbWGrfhbiWZSwBo6HkADTBhUa2Q/jWltyY/tpofz/b6/RIhqaqQcquptCirqIhOaQ==", + "dev": true, + "requires": { + "core-js": "^2.6.5", + "regenerator-runtime": "^0.13.2" + } + }, + "@babel/runtime": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.7.tgz", + "integrity": "sha512-uCnC2JEVAu8AKB5do1WRIsvrdJ0flYx/A/9f/6chdacnEZ7LmavjdsDXr5ksYBegxtuTPR5Va9/+13QF/kFkCA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "@babel/runtime-corejs2": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.7.7.tgz", + "integrity": "sha512-P91T3dFYQL7aj44PxOMIAbo66Ag3NbmXG9fseSYaXxapp3K9XTct5HU9IpTOm2D0AoktKusgqzN5YcSxZXEKBQ==", + "dev": true, + "requires": { + "core-js": "^2.6.5", + "regenerator-runtime": "^0.13.2" + } + }, "@cliqz-oss/firefox-client": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@cliqz-oss/firefox-client/-/firefox-client-0.3.1.tgz", @@ -40,10 +97,46 @@ } } }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@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/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, "@types/node": { - "version": "10.3.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.5.tgz", - "integrity": "sha512-6lRwZN0Y3TuglwaaZN2XPocobmzLlhxcqDjKFjNYSsXG/TFAGYkCqkzZh4+ms8iTHHQE6gJXLHPV7TziVGeWhg==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.1.1.tgz", + "integrity": "sha512-hx6zWtudh3Arsbl3cXay+JnkvVgCKzCWKv42C9J01N2T2np4h8w5X8u6Tpz5mj38kE3M9FM0Pazx8vKFFMnjLQ==", "dev": true }, "JSONSelect": { @@ -52,12 +145,6 @@ "integrity": "sha1-QVQYpSbTP+MddLTe+jyDbUhewgM=", "dev": true }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, "acorn": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", @@ -82,9 +169,9 @@ } }, "adbkit": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/adbkit/-/adbkit-2.11.0.tgz", - "integrity": "sha512-j2vUhEeZmCiqBP+p77CpPWQTcT20rOmSmRHFUTZUwUpxzeCd3fXop4NAGYztSY9/FNU4bT/qqvYQ4EZKuCXhfA==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/adbkit/-/adbkit-2.11.1.tgz", + "integrity": "sha512-hDTiRg9NX3HQt7WoDAPCplUpvzr4ZzQa2lq7BdTTJ/iOZ6O7YNAs6UYD8sFAiBEcYHDRIyq3cm9sZP6uZnhvXw==", "dev": true, "requires": { "adbkit-logcat": "^1.1.0", @@ -120,50 +207,84 @@ } }, "addons-linter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-1.0.0.tgz", - "integrity": "sha512-6cC0Jcf0vMVgE86TV4A1lfjx78Fp0JltA1UH2icz/cALWMMfDZrD7YpB4dMrpobclsbKFPHexNOYhS4efAc5ng==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-1.19.0.tgz", + "integrity": "sha512-pnfrdQqatZeEnBcRcMq9KWZJRmS9YiPyWu3gZbJl12Ee3dUlvke+2C0DcYhNfm4hciRB4wrr4OiQTYAXh1CyzA==", "dev": true, "requires": { - "ajv": "6.5.0", - "ajv-merge-patch": "3.0.0", - "babel-register": "6.26.0", - "chalk": "2.4.0", - "cheerio": "1.0.0-rc.2", + "ajv": "6.10.2", + "ajv-merge-patch": "4.1.0", + "chalk": "2.4.2", + "cheerio": "1.0.0-rc.3", "columnify": "1.5.4", - "common-tags": "1.7.2", - "crx-parser": "0.1.2", - "deepmerge": "2.1.0", - "dispensary": "0.18.0", - "doctoc": "1.3.1", - "es6-promisify": "5.0.0", - "eslint": "4.19.1", + "common-tags": "1.8.0", + "deepmerge": "4.2.2", + "dispensary": "0.48.1", + "es6-promisify": "6.0.2", + "eslint": "5.16.0", "eslint-plugin-no-unsafe-innerhtml": "1.0.16", - "esprima": "3.1.3", - "first-chunk-stream": "2.0.0", - "fluent-syntax": "^0.7.0", - "glob": "7.1.2", - "is-mergeable-object": "1.1.0", + "eslint-visitor-keys": "1.1.0", + "espree": "6.1.2", + "esprima": "4.0.1", + "first-chunk-stream": "3.0.0", + "fluent-syntax": "0.13.0", + "fsevents": "2.1.2", + "glob": "7.1.6", + "is-mergeable-object": "1.1.1", "jed": "1.1.1", - "os-locale": "2.1.0", - "pino": "4.16.1", - "po2json": "0.4.5", - "postcss": "6.0.19", - "probe-image-size": "4.0.0", - "relaxed-json": "1.0.1", - "semver": "5.5.0", - "shelljs": "0.8.1", - "snyk": "^1.78.1", - "source-map-support": "0.5.6", - "strip-bom-stream": "3.0.0", + "mdn-browser-compat-data": "1.0.1", + "os-locale": "4.0.0", + "pino": "5.14.0", + "postcss": "7.0.24", + "probe-image-size": "5.0.0", + "regenerator-runtime": "0.13.3", + "relaxed-json": "1.0.3", + "semver": "6.3.0", + "source-map-support": "0.5.16", + "strip-bom-stream": "4.0.0", "tosource": "1.0.0", - "upath": "1.0.5", - "whatwg-url": "6.4.1", - "xmldom": "0.1.27", - "yargs": "11.0.0", - "yauzl": "2.9.1" + "upath": "1.2.0", + "whatwg-url": "7.1.0", + "yargs": "14.0.0", + "yauzl": "2.10.0" }, "dependencies": { + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "dev": true + }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true + }, + "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-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "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", @@ -173,10 +294,16 @@ "color-convert": "^1.9.0" } }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, "chalk": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", - "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "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", @@ -184,208 +311,690 @@ "supports-color": "^5.3.0" } }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, - "shelljs": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", - "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "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" + } + } } }, - "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 + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } }, - "source-map-support": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", - "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "ms": "^2.1.1" } }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "esutils": "^2.0.2" } }, - "upath": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.5.tgz", - "integrity": "sha512-qbKn90aDQ0YEwvXoLqj0oiuUYroLX2lVHZ+b+xwjozFasAOC4GneDq5+OaIG5Zj+jFmbz/uO+f7a9qxjktJQww==", + "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 }, - "yargs": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", - "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", + "es6-promisify": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.0.2.tgz", + "integrity": "sha512-eO6vFm0JvqGzjWIQA6QVKjxpmELfhWbDUWHm1rPfIbn55mhKPiAa5xpLmQWJrNa629ZIeQ8ZvMAi13kvrjK6Mg==", + "dev": true + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "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==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } - } - } - }, - "adm-zip": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz", - "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==", - "dev": true - }, - "agent-base": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz", - "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "ajv": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.0.tgz", - "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0", - "uri-js": "^4.2.1" - } - }, - "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", - "dev": true - }, - "ajv-merge-patch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ajv-merge-patch/-/ajv-merge-patch-3.0.0.tgz", - "integrity": "sha1-dvBx45H0Gf6f4/6n6SChrYJLK2E=", - "dev": true, - "requires": { - "fast-json-patch": "^1.0.0", - "json-merge-patch": "^0.2.3" - } - }, - "alce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/alce/-/alce-1.0.0.tgz", - "integrity": "sha1-QmGEyY7iiNDurHf9Y/7WgLZnyrY=", - "dev": true, - "requires": { - "esprima": "~1.0.4", - "estraverse": "~1.3.0" - }, - "dependencies": { - "esprima": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", - "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", - "dev": true }, - "estraverse": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.3.2.tgz", - "integrity": "sha1-N8K4k+8T1yPydth41g2FNRUqbEI=", - "dev": true - } - } - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, - "amqplib": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", - "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", - "dev": true, - "requires": { - "bitsyntax": "~0.0.4", - "bluebird": "^3.4.6", - "buffer-more-ints": "0.0.2", - "readable-stream": "1.x >=1.1.9", - "safe-buffer": "^5.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "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 }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + } } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "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 - } - } - }, - "anchor-markdown-header": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/anchor-markdown-header/-/anchor-markdown-header-0.5.7.tgz", - "integrity": "sha1-BFBj125qH5zTJ6V6ASaqD97Dcac=", - "dev": true, - "requires": { - "emoji-regex": "~6.1.0" - } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "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" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "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" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "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" + } + } + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "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": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "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" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.0.0.tgz", + "integrity": "sha512-ssa5JuRjMeZEUjg7bEL99AwpitxU/zWGAGpdj0di41pOEmJti8NR6kyUIJBkR78DTYNPZOU08luUo0GTHuB+ow==", + "dev": true, + "requires": { + "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": "^13.1.1" + }, + "dependencies": { + "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" + } + } + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "adm-zip": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz", + "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==", + "dev": true + }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.0.tgz", + "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0", + "uri-js": "^4.2.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "ajv-merge-patch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ajv-merge-patch/-/ajv-merge-patch-4.1.0.tgz", + "integrity": "sha512-0mAYXMSauA8RZ7r+B4+EAOYcZEcO9OK5EiQCR7W7Cv4E44pJj56ZnkKLJ9/PAcOc0dT+LlV9fdDcq2TxVJfOYw==", + "dev": true, + "requires": { + "fast-json-patch": "^2.0.6", + "json-merge-patch": "^0.2.3" + } + }, + "alce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/alce/-/alce-1.0.0.tgz", + "integrity": "sha1-QmGEyY7iiNDurHf9Y/7WgLZnyrY=", + "dev": true, + "requires": { + "esprima": "~1.0.4", + "estraverse": "~1.3.0" + }, + "dependencies": { + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + }, + "estraverse": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.3.2.tgz", + "integrity": "sha1-N8K4k+8T1yPydth41g2FNRUqbEI=", + "dev": true + } + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "anchor-markdown-header": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/anchor-markdown-header/-/anchor-markdown-header-0.5.7.tgz", + "integrity": "sha1-BFBj125qH5zTJ6V6ASaqD97Dcac=", + "dev": true, + "requires": { + "emoji-regex": "~6.1.0" + } }, "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", "dev": true, "requires": { - "string-width": "^2.0.0" + "string-width": "^3.0.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 + }, + "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 + }, + "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" + } + } } }, "ansi-escapes": { @@ -406,16 +1015,10 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, - "ansicolors": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", - "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=", - "dev": true - }, "any-observable": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.2.0.tgz", - "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", "dev": true }, "any-promise": { @@ -451,12 +1054,12 @@ }, "dependencies": { "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.14" } } } @@ -475,12 +1078,6 @@ "readable-stream": "^2.0.0" } }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -508,6 +1105,12 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, "array-filter": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", @@ -520,12 +1123,6 @@ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", - "dev": true - }, "array-map": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", @@ -565,12 +1162,6 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true - }, "asn1": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", @@ -609,10 +1200,10 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "ast-types": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", - "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==", + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, "async": { @@ -649,216 +1240,60 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "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" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "babel-core": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - } - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "dev": true }, - "babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "b64": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/b64/-/b64-4.1.2.tgz", + "integrity": "sha512-+GUspBxlH3CJaxMUGUE1EBoWM6RKgWiYwUDal0qdf8m3ArnXNN1KzKVo5HOnE/FSq4HHyWf3TlHLsZI8PKQgrQ==", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" + "hoek": "6.x.x" }, "dependencies": { - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "hoek": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", + "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", "dev": true } } }, - "babel-register": { + "babel-code-frame": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" }, "dependencies": { - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "source-map": "^0.5.6" + "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" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" } } } }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, "bail": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", @@ -933,9 +1368,9 @@ } }, "base64-js": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", - "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", "dev": true }, "bcrypt-pbkdf": { @@ -960,15 +1395,6 @@ "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, - "bitsyntax": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", - "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", - "dev": true, - "requires": { - "buffer-more-ints": "0.0.2" - } - }, "bl": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", @@ -980,9 +1406,9 @@ } }, "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "version": "3.4.6", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz", + "integrity": "sha1-AdqNgh2HgT0ViWfnQ9X+bGLPjA8=", "dev": true }, "bn.js": { @@ -1006,20 +1432,29 @@ "hoek": "4.x.x" } }, - "bops": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/bops/-/bops-0.1.1.tgz", - "integrity": "sha1-Bi4CqNqoAfoQ8uXb5nQM/4Af4X4=", + "bounce": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bounce/-/bounce-1.2.3.tgz", + "integrity": "sha512-3G7B8CyBnip5EahCZJjnvQ1HLyArC6P5e+xcolo13BVI9ogFaDOsNMAE7FIWliHtIkYI8/nTRCvCY9tZa3Mu4g==", "dev": true, "requires": { - "base64-js": "0.0.2", - "to-utf8": "0.0.1" + "boom": "7.x.x", + "hoek": "6.x.x" }, "dependencies": { - "base64-js": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz", - "integrity": "sha1-Ak8Pcq+iW3X5wO5zzU9V7Bvtl4Q=", + "boom": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz", + "integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==", + "dev": true, + "requires": { + "hoek": "6.x.x" + } + }, + "hoek": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", + "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", "dev": true } } @@ -1031,18 +1466,115 @@ "dev": true }, "boxen": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", "dev": true, "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.0.tgz", + "integrity": "sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "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 + }, + "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": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "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": "^5.0.0" + } + }, + "supports-color": { + "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": "^4.0.0" + } + } } }, "brace-expansion": { @@ -1167,30 +1699,29 @@ } }, "buffer": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", - "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", + "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", "dev": true, "requires": { - "base64-js": "0.0.8", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" } }, "buffer-alloc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.1.0.tgz", - "integrity": "sha1-BVFNM78WVtNUDGhPZbEgLpDsowM=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", "dev": true, "requires": { - "buffer-alloc-unsafe": "^0.1.0", - "buffer-fill": "^0.1.0" + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" } }, "buffer-alloc-unsafe": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz", - "integrity": "sha1-/+H2dVHdBVc33iUzN7/oU9+rGmo=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", "dev": true }, "buffer-crc32": { @@ -1206,9 +1737,9 @@ "dev": true }, "buffer-fill": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-0.1.1.tgz", - "integrity": "sha512-YgBMBzdRLEfgxJIGu2wrvI2E03tMCFU1p7d1KhB4BOoMN0VxmTFjSyN5JtKt9z8Z9JajMHruI6SE25W96wNv7Q==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", "dev": true }, "buffer-from": { @@ -1217,12 +1748,6 @@ "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", "dev": true }, - "buffer-more-ints": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", - "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", - "dev": true - }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", @@ -1253,12 +1778,6 @@ "safe-json-stringify": "~1" } }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -1276,6 +1795,38 @@ "unset-value": "^1.0.0" } }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", @@ -1309,9 +1860,9 @@ } }, "capture-stack-trace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", "dev": true }, "caseless": { @@ -1406,17 +1957,29 @@ "dev": true }, "cheerio": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", - "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", "dev": true, "requires": { "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", + "dom-serializer": "~0.1.1", "entities": "~1.1.1", "htmlparser2": "^3.9.1", "lodash": "^4.15.0", "parse5": "^3.0.1" + }, + "dependencies": { + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + } } }, "chokidar": { @@ -1440,9 +2003,28 @@ } }, "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", + "dev": true + }, + "chrome-launcher": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.12.0.tgz", + "integrity": "sha512-rBUP4tvWToiileDi3UR0SbWKoUoDCYTRmVND2sdoBL1xANBgVz8V9h1yQluj3MEQaBJg0fRw7hW82uOPrJus7A==", + "dev": true, + "requires": { + "@types/node": "*", + "is-wsl": "^2.1.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "0.5.1", + "rimraf": "^2.6.1" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, "cipher-base": { @@ -1484,20 +2066,10 @@ } } }, - "cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", - "dev": true, - "requires": { - "exit": "0.1.2", - "glob": "^7.1.1" - } - }, "cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", + "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", "dev": true }, "cli-cursor": { @@ -1509,12 +2081,6 @@ "restore-cursor": "^2.0.0" } }, - "cli-spinners": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", - "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", - "dev": true - }, "cli-truncate": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", @@ -1569,14 +2135,90 @@ "dev": true }, "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + }, + "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.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.0.tgz", + "integrity": "sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "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 + }, + "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 + }, + "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": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "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": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } } }, "clone": { @@ -1585,16 +2227,13 @@ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, - "clone-deep": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.3.0.tgz", - "integrity": "sha1-NIxhrpzb4O3+BT2R/0zFIdeQ7eg=", + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", "dev": true, "requires": { - "for-own": "^1.0.0", - "is-plain-object": "^2.0.1", - "kind-of": "^3.2.2", - "shallow-clone": "^0.1.2" + "mimic-response": "^1.0.0" } }, "co": { @@ -1682,13 +2321,10 @@ "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" }, "common-tags": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.7.2.tgz", - "integrity": "sha512-joj9ZlUOjCrwdbmiLqafeUSgkUM74NqhLsZtSqDmhKudaIY197zTrb8JMl31fMnCUuxwFT23eC/oWvrZzDLRJQ==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0" - } + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true }, "component-emitter": { "version": "1.2.1", @@ -1727,17 +2363,34 @@ } }, "configstore": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", - "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.0.tgz", + "integrity": "sha512-eE/hvMs7qw7DlcB5JPRnthmrITuHMmACUJAp89v6PT6iOqzoLS7HRWhBtuHMlhNHo2AhUSA/3Dh1bKNJHcublQ==", "dev": true, "requires": { - "dot-prop": "^4.1.0", + "dot-prop": "^5.1.0", "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" + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "console-browserify": { @@ -1755,16 +2408,10 @@ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", "dev": true }, - "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true - }, "cookiejar": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.1.tgz", - "integrity": "sha1-Qa1XsbVVlR7BcUEqgZQrHoIA00o=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", "dev": true }, "copy-descriptor": { @@ -1774,9 +2421,9 @@ "dev": true }, "core-js": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.6.tgz", - "integrity": "sha512-lQUVfQi0aLix2xpyjrrJEvfuYCqPc/HwmTKsC/VNf8q0zsjX7SQZtp4+oRONN5Tsur9GDETPjj+Ub2iDiGZfSQ==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", "dev": true }, "core-util-is": { @@ -1786,10 +2433,13 @@ "dev": true }, "crc": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.5.0.tgz", - "integrity": "sha1-mLi6fUiWZbo5efWbITgTdBAaGWQ=", - "dev": true + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "requires": { + "buffer": "^5.1.0" + } }, "crc32-stream": { "version": "2.0.0", @@ -1870,12 +2520,6 @@ } } }, - "crx-parser": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/crx-parser/-/crx-parser-0.1.2.tgz", - "integrity": "sha1-fu7tnt3JXiLBiTguNGJARKiaWm0=", - "dev": true - }, "cryptiles": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.4.tgz", @@ -1916,9 +2560,9 @@ } }, "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true }, "css-select": { @@ -1946,9 +2590,9 @@ } }, "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", "dev": true }, "currently-unhandled": { @@ -1960,20 +2604,14 @@ "array-find-index": "^1.0.1" } }, - "cycle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=", - "dev": true, - "optional": true - }, "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dev": true, "requires": { - "es5-ext": "^0.10.9" + "es5-ext": "^0.10.50", + "type": "^1.0.1" } }, "dashdash": { @@ -1985,16 +2623,10 @@ "assert-plus": "^1.0.0" } }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", - "dev": true - }, "date-fns": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", - "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", "dev": true }, "date-now": { @@ -2004,9 +2636,9 @@ "dev": true }, "debounce": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.1.0.tgz", - "integrity": "sha512-ZQVKfRVlwRfD150ndzEK8M90ABT+Y/JQKs4Y7U4MXdpuoUkkrr4DwKbVux3YjylA5bUMUj0Nc3pMxPJX6N2QQQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", + "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==", "dev": true }, "debug": { @@ -2064,6 +2696,15 @@ "strip-dirs": "^2.0.0" } }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, "decompress-tar": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", @@ -2128,10 +2769,26 @@ } }, "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } }, "deep-extend": { "version": "0.2.11", @@ -2146,15 +2803,18 @@ "dev": true }, "deepcopy": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/deepcopy/-/deepcopy-0.6.3.tgz", - "integrity": "sha1-Y0eA8vhlardxr4+oQx7RzO5Vx7A=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deepcopy/-/deepcopy-2.0.0.tgz", + "integrity": "sha512-d5ZK7pJw7F3k6M5vqDjGiiUS9xliIyWkdzBjnPhnSeRGjkYOGZMCFkdKVwV/WiHOe0NwzB8q+iDo7afvSf0arA==", + "dev": true, + "requires": { + "type-detect": "^4.0.8" + } }, "deepmerge": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.1.0.tgz", - "integrity": "sha512-Q89Z26KAfA3lpPGhbF6XMfYAm3jIV3avViy6KOJ2JLzFbeWHOvPQUu5aSJIWXap3gDZC2y1eF5HXEPI2wGqgvw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true }, "defaults": { @@ -2166,6 +2826,12 @@ "clone": "^1.0.2" } }, + "defer-to-connect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.1.tgz", + "integrity": "sha512-J7thop4u3mRTkYRQ+Vpfwy2G5Ehoy82I14+14W4YMDLKdWloI9gSzRbV30s/NckQGVJtPkWNcW4oMAUigTdqiQ==", + "dev": true + }, "define-properties": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", @@ -2223,25 +2889,6 @@ } } }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "dev": true, - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - } - } - }, "del": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", @@ -2263,12 +2910,6 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", @@ -2279,15 +2920,6 @@ "minimalistic-assert": "^1.0.0" } }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -2306,65 +2938,274 @@ } }, "dispensary": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/dispensary/-/dispensary-0.18.0.tgz", - "integrity": "sha512-ikVxjigcj4leoPgjqYcHV1YhmLEZ5eXMq30CIPTf1BniWrH1C0X35F5iVCa4U2/JXZYcQJyHWniSRSOpM+hiNw==", + "version": "0.48.1", + "resolved": "https://registry.npmjs.org/dispensary/-/dispensary-0.48.1.tgz", + "integrity": "sha512-oC9ItJ7YtO/DKsp24T90k7z0NxfkZQkvJ3USTxUoVjBKrfMRz1/kMd+NcFgDG+KrJg14GChiv1sbdFdxeKRUUw==", "dev": true, "requires": { - "array-from": "~2.1.1", - "async": "~2.6.0", + "async": "~3.1.0", "natural-compare-lite": "~1.4.0", - "pino": "~4.16.1", - "request": "~2.85.0", - "semver": "~5.5.0", + "pino": "~5.14.0", + "request": "~2.88.0", "sha.js": "~2.4.4", "source-map-support": "~0.5.4", - "yargs": "~11.0.0" + "yargs": "~15.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": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.1.0.tgz", + "integrity": "sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ==", + "dev": true + }, + "aws4": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", + "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "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 + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "lodash": "^4.17.10" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "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 + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "mime-db": { + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", + "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.25", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", + "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", + "dev": true, + "requires": { + "mime-db": "1.42.0" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "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 + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "source-map-support": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", - "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "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": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "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": "^5.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==", + "dev": true, + "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=", + "dev": true + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "punycode": "^2.1.0" } }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, "yargs": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", - "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.0.2.tgz", + "integrity": "sha512-GH/X/hYt+x5hOat4LMnCqMd8r5Cv78heOMIJn1hr7QPPBqfeC6p89Y78+WB9yGDvfpCvgasfmWLzNzEioOUD9Q==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^2.0.0", + "string-width": "^4.2.0", "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" + "y18n": "^4.0.0", + "yargs-parser": "^16.1.0" + } + }, + "yargs-parser": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", + "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -2442,22 +3283,31 @@ } }, "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": "5.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", + "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", "dev": true, "requires": { - "is-obj": "^1.0.0" + "is-obj": "^2.0.0" } }, "dtrace-provider": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.7.tgz", - "integrity": "sha1-3JObTT4GIM/gwc2APQ0tftBP/QQ=", + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", + "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==", "dev": true, "optional": true, "requires": { - "nan": "^2.10.0" + "nan": "^2.14.0" + }, + "dependencies": { + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + } } }, "duplexer": { @@ -2492,9 +3342,9 @@ } }, "ecdsa-sig-formatter": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", - "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "dev": true, "requires": { "safe-buffer": "^5.0.1" @@ -2521,12 +3371,6 @@ "minimalistic-crypto-utils": "^1.0.0" } }, - "email-validator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", - "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==", - "dev": true - }, "emoji-regex": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.3.tgz", @@ -2539,19 +3383,10 @@ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "dev": true, - "requires": { - "iconv-lite": "~0.4.13" - } - }, "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==", "dev": true, "requires": { "once": "^1.4.0" @@ -2606,14 +3441,14 @@ } }, "es5-ext": { - "version": "0.10.45", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", - "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", "dev": true, "requires": { "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "1" + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" } }, "es6-error": { @@ -2663,9 +3498,9 @@ }, "dependencies": { "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", "dev": true } } @@ -2681,27 +3516,39 @@ "es6-iterator": "~2.0.1", "es6-symbol": "3.1.1", "event-emitter": "~0.3.5" + }, + "dependencies": { + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } } }, "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14" + "d": "^1.0.1", + "ext": "^1.1.2" } }, "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "dev": true, "requires": { "d": "1", - "es5-ext": "^0.10.14", - "es6-iterator": "^2.0.1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.1" } }, @@ -2711,34 +3558,6 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "escodegen": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.10.0.tgz", - "integrity": "sha512-fjUOf8johsv23WuIKdNQU4P9t9jhQ4Qzx6pC2uW890OloK3Zs1ZAoCNpg/2larNF501jLl3UNy0kIRcF6VI22g==", - "dev": true, - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - }, - "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, - "optional": true - } - } - }, "escope": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", @@ -2827,12 +3646,12 @@ } }, "eslint-plugin-json": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-1.2.0.tgz", - "integrity": "sha1-m6c7sL6Z1QCT6In1uWhGPSow764=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-1.4.0.tgz", + "integrity": "sha512-CECvgRAWtUzuepdlPWd+VA7fhyF9HT183pZnl8wQw5x699Mk/MbME/q8xtULBfooi3LUbj6fToieNmsvUcDxWA==", "dev": true, "requires": { - "jshint": "^2.8.0" + "vscode-json-languageservice": "^3.2.1" } }, "eslint-plugin-mozilla": { @@ -3132,6 +3951,23 @@ "estraverse": "^4.1.1" } }, + "eslint-utils": { + "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.1.0" + }, + "dependencies": { + "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 + } + } + }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -3149,9 +3985,9 @@ } }, "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "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 }, "esquery": { @@ -3232,13 +4068,13 @@ } }, "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", + "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", @@ -3246,20 +4082,30 @@ "strip-eof": "^1.0.0" }, "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } } } }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, "exit-hook": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", @@ -3301,10 +4147,27 @@ } } }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, "extend-object": { @@ -3416,60 +4279,25 @@ } } }, - "extract-zip": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", - "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", - "dev": true, - "optional": true, - "requires": { - "concat-stream": "1.6.2", - "debug": "2.6.9", - "mkdirp": "0.5.1", - "yauzl": "2.4.1" - }, - "dependencies": { - "yauzl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", - "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", - "dev": true, - "optional": true, - "requires": { - "fd-slicer": "~1.0.1" - } - } - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, - "eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", - "dev": true, - "optional": true - }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, - "fast-json-parse": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", - "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", - "dev": true - }, "fast-json-patch": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-1.2.2.tgz", - "integrity": "sha1-03fZfGkR290qHIC/rNoEik+Du/k=", - "dev": true + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", + "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1" + } }, "fast-json-stable-stringify": { "version": "2.0.0", @@ -3482,20 +4310,17 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "fast-safe-stringify": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-1.2.3.tgz", - "integrity": "sha512-QJYT/i0QYoiZBQ71ivxdyTqkwKkQ0oxACXHYxH2zYHJEgzi2LsbjgvtzTbLi1SZcF190Db2YP7I7eTsU2egOlw==", + "fast-redact": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-2.0.0.tgz", + "integrity": "sha512-zxpkULI9W9MNTK2sJ3BpPQrTEXFNESd2X6O1tXMFpK/XM0G5c5Rll2EVYZH2TqI3xRGK/VaJ+eEOt7pnENJpeA==", "dev": true }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", + "dev": true }, "figures": { "version": "2.0.0", @@ -3522,12 +4347,6 @@ "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", "dev": true }, - "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==", - "dev": true - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -3561,9 +4380,9 @@ } }, "firefox-profile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/firefox-profile/-/firefox-profile-1.1.0.tgz", - "integrity": "sha512-wUIE4QeAjwoHvFbomWmXgKyYtV4/oZxDcJG4znxtGGa/0BhKkd3HzeOf3tAsMWPq1ExARZxCRRiNw1BL3FuPqA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/firefox-profile/-/firefox-profile-1.3.0.tgz", + "integrity": "sha512-3d7JPnFC3GrwGW8wonAqy2E4YCI7A8MO7yVDkqS09uQ3tLvMLCY3Ytt4ntvVXvyzjVMRmrLW9W/CubnnzrdLCA==", "dev": true, "requires": { "adm-zip": "~0.4.x", @@ -3598,23 +4417,14 @@ "jsonfile": "^4.0.0", "universalify": "^0.1.0" } - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true } } }, "first-chunk-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", - "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-3.0.0.tgz", + "integrity": "sha512-LNRvR4hr/S8cXXkIY5pTgVP7L3tq6LlYWcg9nWBuW7o1NMxKZo6oOVa/6GIekMGI0Iw7uC+HWimMe9u/VAeKqw==", + "dev": true }, "fixpack": { "version": "2.3.1", @@ -3641,15 +4451,21 @@ } }, "flatstr": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.8.tgz", - "integrity": "sha512-YXblbv/vc1zuVVUtnKl1hPqqk7TalZCppnKE7Pr8FI/Rp48vzckS/4SJ4Y9O9RNiI82Vcw/FydmtqdQOg1Dpqw==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", + "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==", + "dev": true + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, "fluent-syntax": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/fluent-syntax/-/fluent-syntax-0.7.0.tgz", - "integrity": "sha512-T0iqfhC40jrs3aDjYOKgzIQjjhsH2Fa6LnXB6naPv0ymW3DeYMUFa89y9aLKMpi1P9nl2vEimK7blx4tVnUWBg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/fluent-syntax/-/fluent-syntax-0.13.0.tgz", + "integrity": "sha512-0Bk1AsliuYB550zr4JV9AYhsETsD3ELXUQzdXGJfIc1Ni/ukAfBdQInDhVMYJUaT2QxoamNslwkYF7MlOrPUwg==", "dev": true }, "for-in": { @@ -3658,15 +4474,6 @@ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, "foreach": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", @@ -3711,6 +4518,16 @@ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -3727,6 +4544,15 @@ "universalify": "^0.1.0" } }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "requires": { + "minipass": "^2.6.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3794,13 +4620,6 @@ "concat-map": "0.0.1" } }, - "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", - "dev": true, - "optional": true - }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -3860,16 +4679,6 @@ "dev": true, "optional": true }, - "fs-minipass": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3995,27 +4804,6 @@ "dev": true, "optional": true }, - "minipass": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", - "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", - "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -4299,19 +5087,28 @@ "optional": true }, "tar": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", - "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "dev": true, "optional": true, "requires": { - "chownr": "^1.0.1", + "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true, + "optional": true + } } }, "util-deprecate": { @@ -4339,50 +5136,14 @@ "optional": true }, "yallist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "optional": true } } }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "dev": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -4396,13 +5157,12 @@ "dev": true }, "fx-runner": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/fx-runner/-/fx-runner-1.0.9.tgz", - "integrity": "sha1-eyPzdz3HaqzELxHZr/J2lnXLY/A=", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fx-runner/-/fx-runner-1.0.11.tgz", + "integrity": "sha512-igHogHf5wTqqaPPTOav18MMTVq/eoeTJiw/PvPUuwnzU8vbyZInFPgR66G9ZBwvwxC7e611nbtB4xSMcYVhlvg==", "dev": true, "requires": { "commander": "2.9.0", - "lodash": "4.17.10", "shell-quote": "1.6.1", "spawn-sync": "1.0.15", "when": "3.7.7", @@ -4438,37 +5198,26 @@ } }, "geckodriver": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-1.12.2.tgz", - "integrity": "sha512-nhTroSDoAjbws1GAALCBFGWcjUI7Uy5nLKJFKmOfOmVGCyn7TazdIYQJFpnre/vtKcieKwXOC8RqBD48g0a/4A==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-1.19.1.tgz", + "integrity": "sha512-xWL/+eEhQ6+t98rc1c+xVM3hshDJibXtZf9WJA3sshxq4k5L1PBwfmswyBmmlKUfBr4xuC256gLVC2RxFhiCsQ==", "dev": true, "requires": { "adm-zip": "0.4.11", "bluebird": "3.4.6", "got": "5.6.0", - "https-proxy-agent": "2.2.1", - "tar": "4.0.2" - }, - "dependencies": { - "adm-zip": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz", - "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==", - "dev": true - }, - "bluebird": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz", - "integrity": "sha1-AdqNgh2HgT0ViWfnQ9X+bGLPjA8=", - "dev": true - } + "https-proxy-agent": "3.0.0", + "tar": "4.4.2" } }, "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "requires": { + "is-property": "^1.0.2" + } }, "generate-object-property": { "version": "1.2.0", @@ -4486,20 +5235,53 @@ "dev": true }, "get-firefox": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/get-firefox/-/get-firefox-2.1.0.tgz", - "integrity": "sha512-Bw9dZcfjUf1HNjdBep5CzvQN/Jbzp2Rv4XzkghwOoDdQKfQsnIJHubuGuHmpNL1DSbx4MyY9D/OfzmiuLXriyQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-firefox/-/get-firefox-3.0.0.tgz", + "integrity": "sha512-WZvf2BuyZtpFoK7oIJxsEyeeM/SxhTYfvoqElv9vxqhPXkZpKLCHhknfkUpYYJKuKUomM6t5yeth2PQFB6dbdg==", "dev": true, "requires": { - "chalk": "^2.3.0", + "chalk": "^2.4.2", "decompress": "^4.2.0", - "listr": "^0.13.0", - "meow": "^4.0.0", + "into-stream": "^5.1.1", + "is-ci": "^2.0.0", + "listr": "^0.14.3", + "meow": "^5.0.0", "moz-download-url": "^2.0.0", - "node-fetch": "^1.7.3", - "sha": "^2.0.1", + "node-fetch": "^2.6.0", + "sha": "^3.0.0", "stream-to-promise": "^2.2.0", - "taskcluster-client": "^3.0.1" + "taskcluster-client": "^19.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" + } + } } }, "get-stream": { @@ -4512,20 +5294,6 @@ "pinkie-promise": "^2.0.0" } }, - "get-uri": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", - "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", - "dev": true, - "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "3", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" - } - }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -4541,26 +5309,23 @@ "assert-plus": "^1.0.0" } }, - "gettext-parser": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.1.0.tgz", - "integrity": "sha1-LFpmONiTk0ubVQN9CtgstwBLJnk=", - "dev": true, - "requires": { - "encoding": "^0.1.11" - } - }, "git-rev-sync": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/git-rev-sync/-/git-rev-sync-1.9.1.tgz", - "integrity": "sha1-oMLj3TkqvPa3aWLif8dfsyI0Sc4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-rev-sync/-/git-rev-sync-2.0.0.tgz", + "integrity": "sha512-vnHFv2eocTmt/wHqZm3ksxtVshK4vptT0cEoumk6hAYRFx3do6Qo7xHBTBCv29+r3ZZCQOQ1i328MUCsYF7AUw==", "dev": true, "requires": { "escape-string-regexp": "1.0.5", - "graceful-fs": "4.1.11", + "graceful-fs": "4.1.15", "shelljs": "0.7.7" }, "dependencies": { + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, "shelljs": { "version": "0.7.7", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.7.tgz", @@ -4610,12 +5375,12 @@ } }, "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", + "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", "dev": true, "requires": { - "ini": "^1.3.4" + "ini": "^1.3.5" } }, "globals": { @@ -4673,15 +5438,6 @@ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, - "graphlib": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.5.tgz", - "integrity": "sha512-XvtbqCcw+EM5SqQrIetIKKD+uZVNQtDPD1goIg7K73RuRZtVI5rYMdcCVSHm/AS1sCBZ7vt0p5WgXouucHQaOA==", - "dev": true, - "requires": { - "lodash": "^4.11.1" - } - }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -4748,18 +5504,18 @@ "ansi-regex": "^2.0.0" } }, - "has-color": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbols": { + "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==", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -4792,22 +5548,11 @@ } } }, - "hasbin": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/hasbin/-/hasbin-1.2.3.tgz", - "integrity": "sha1-eMWSaJPIAhXCtWiuH9P8q3omlrA=", - "dev": true, - "requires": { - "async": "~1.5" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - } - } + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true }, "hash-base": { "version": "3.0.4", @@ -4829,17 +5574,6 @@ "minimalistic-assert": "^1.0.0" } }, - "hasha": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", - "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", - "dev": true, - "optional": true, - "requires": { - "is-stream": "^1.0.1", - "pinkie-promise": "^2.0.0" - } - }, "hawk": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", @@ -4875,16 +5609,6 @@ "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", "dev": true }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } - }, "hosted-git-info": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", @@ -4893,51 +5617,24 @@ }, "htmlparser2": { "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", - "dev": true, - "requires": { - "domelementtype": "^1.3.0", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "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==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" } }, + "http-cache-semantics": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", + "integrity": "sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==", + "dev": true + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -4956,23 +5653,29 @@ "dev": true }, "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.0.tgz", + "integrity": "sha512-y4jAxNEihqvBI5F3SaO2rtsjIOnnNA8sEbuiP+UhJZJHeM2NRm6c09ax2tgqme+SgUUvjao2fJXF4h3D6Cb2HQ==", "dev": true, "requires": { - "agent-base": "^4.1.0", + "agent-base": "^4.3.0", "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==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "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 } } }, @@ -5003,6 +5706,24 @@ "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", "dev": true }, + "import-fresh": { + "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": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -5016,13 +5737,10 @@ "dev": true }, "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true }, "indexof": { "version": "0.0.1", @@ -5086,13 +5804,14 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "into-stream": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-5.1.1.tgz", + "integrity": "sha512-krrAJ7McQxGGmvaYbB7Q1mcA+cRwg9Ij2RfWIeVesNBgVDZmzY/Fa4IpZUT3bmdRzMzdf/mzltCG2Dq99IZGBA==", "dev": true, "requires": { - "loose-envify": "^1.0.0" + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" } }, "invert-kv": { @@ -5101,12 +5820,6 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, "is-absolute": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", @@ -5141,6 +5854,12 @@ "is-decimal": "^1.0.0" } }, + "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", @@ -5177,6 +5896,15 @@ "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", "dev": true }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -5229,15 +5957,6 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.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", @@ -5260,19 +5979,27 @@ "dev": true }, "is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.1.tgz", + "integrity": "sha512-oiEcGoQbGc+3/iijAijrK2qFpkNoNjsHOm/5V5iaeydyrS/hnwaRCEgH5cpW0P3T1lSjV5piB7S5b5lEugNLhg==", "dev": true, "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + }, + "dependencies": { + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "dev": true + } } }, "is-mergeable-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-mergeable-object/-/is-mergeable-object-1.1.0.tgz", - "integrity": "sha512-JfyDDwUdtS4yHCgUpxOyKB9dnfZ0gecufxB0eytX6BmSXSE+8dbxDGt+V7CNRIRJ9sYFV/WQt2KJG6hNob2sBw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-mergeable-object/-/is-mergeable-object-1.1.1.tgz", + "integrity": "sha512-CPduJfuGg8h8vW74WOxHtHmtQutyQBzR+3MjQ6iDHIYdbOnm1YC7jv43SqCoU8OPGTJD4nibmiryA4kmogbGrA==", "dev": true }, "is-my-ip-valid": { @@ -5282,9 +6009,9 @@ "dev": true }, "is-my-json-valid": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", - "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz", + "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==", "dev": true, "requires": { "generate-function": "^2.0.0", @@ -5301,9 +6028,9 @@ "dev": true }, "is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", "dev": true }, "is-number": { @@ -5316,18 +6043,18 @@ } }, "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true }, "is-observable": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-0.2.0.tgz", - "integrity": "sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", "dev": true, "requires": { - "symbol-observable": "^0.2.2" + "symbol-observable": "^1.1.0" } }, "is-odd": { @@ -5426,9 +6153,9 @@ "dev": true }, "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-stream": { @@ -5462,9 +6189,15 @@ "dev": true }, "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", + "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", + "dev": true + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, "isarray": { @@ -5533,9 +6266,9 @@ "dev": true }, "js-yaml": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", - "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -5549,100 +6282,11 @@ "dev": true, "optional": true }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "jshint": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.6.tgz", - "integrity": "sha512-KO9SIAKTlJQOM4lE64GQUtGBRpTOuvbrRrSZw3AhUxMNG266nX9hK2cKA4SBhXOj0irJGyNyGSLT62HGOVDEOA==", - "dev": true, - "requires": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "~4.17.10", - "minimatch": "~3.0.2", - "phantom": "~4.0.1", - "phantomjs-prebuilt": "~2.1.7", - "shelljs": "0.3.x", - "strip-json-comments": "1.0.x", - "unicode-5.2.0": "^0.7.5" - }, - "dependencies": { - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", - "dev": true - }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", - "dev": true, - "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", - "dev": true - } - } + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true }, "json-loader": { "version": "0.5.7", @@ -5703,6 +6347,12 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "jsonc-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.0.tgz", + "integrity": "sha512-4fLQxW1j/5fWj6p78vAlAafoCKtuBm6ghv+Ij5W2DrDx0qE+ZdEl2c6Ko1mgJNF5ftX1iEWQQ4Ap7+3GlhjkOA==", + "dev": true + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -5724,12 +6374,12 @@ "dev": true }, "jsonwebtoken": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.2.1.tgz", - "integrity": "sha512-l8rUBr0fqYYwPc8/ZGrue7GiW7vWdZtZqelxo4Sd5lMvuEeCK8/wS54sEo6tJhdZ6hqfutsj6COgC0d1XdbHGw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", "dev": true, "requires": { - "jws": "^3.1.4", + "jws": "^3.2.2", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", @@ -5738,13 +6388,19 @@ "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", - "xtend": "^4.0.1" + "semver": "^5.6.0" }, "dependencies": { "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 + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true } } @@ -5809,32 +6465,34 @@ } }, "jwa": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz", - "integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", "dev": true, "requires": { "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.10", + "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "jws": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz", - "integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", "dev": true, "requires": { - "jwa": "^1.1.5", + "jwa": "^1.4.1", "safe-buffer": "^5.0.1" } }, - "kew": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", - "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", "dev": true, - "optional": true + "requires": { + "json-buffer": "3.0.0" + } }, "kind-of": { "version": "3.2.2", @@ -5845,31 +6503,15 @@ "is-buffer": "^1.1.5" } }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.9" - } - }, "latest-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", "dev": true, "requires": { - "package-json": "^4.0.0" + "package-json": "^6.3.0" } }, - "lazy-cache": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", - "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=", - "dev": true - }, "lazystream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", @@ -5907,63 +6549,37 @@ "immediate": "~3.0.5" } }, + "lighthouse-logger": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.2.0.tgz", + "integrity": "sha512-wzUvdIeJZhRsG6gpZfmSCfysaxNEr43i+QT+Hie94wvHDKFLi4n7C2GqZ4sTC+PH5b5iktmXJvU87rWvhP3lHw==", + "dev": true, + "requires": { + "debug": "^2.6.8", + "marky": "^1.2.0" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, "listr": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/listr/-/listr-0.13.0.tgz", - "integrity": "sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0=", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", "dev": true, "requires": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "figures": "^1.7.0", - "indent-string": "^2.1.0", - "is-observable": "^0.2.0", + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", "is-promise": "^2.1.0", "is-stream": "^1.1.0", "listr-silent-renderer": "^1.1.1", - "listr-update-renderer": "^0.4.0", - "listr-verbose-renderer": "^0.4.0", - "log-symbols": "^1.0.2", - "log-update": "^1.0.2", - "ora": "^0.2.3", - "p-map": "^1.1.1", - "rxjs": "^5.4.2", - "stream-to-observable": "^0.2.0", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "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" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" } }, "listr-silent-renderer": { @@ -5972,72 +6588,20 @@ "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", "dev": true }, - "listr-update-renderer": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz", - "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "elegant-spinner": "^1.0.1", - "figures": "^1.7.0", - "indent-string": "^3.0.0", - "log-symbols": "^1.0.2", - "log-update": "^1.0.2", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "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" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "listr-verbose-renderer": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", - "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", "dev": true, "requires": { "chalk": "^1.1.3", - "cli-cursor": "^1.0.2", - "date-fns": "^1.27.2", - "figures": "^1.7.0" + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" }, "dependencies": { "chalk": { @@ -6053,15 +6617,6 @@ "supports-color": "^2.0.0" } }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, "figures": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", @@ -6072,22 +6627,6 @@ "object-assign": "^4.1.0" } }, - "onetime": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -6099,6 +6638,18 @@ } } }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + } + }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -6146,39 +6697,9 @@ } }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - }, - "lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, "lodash.includes": { @@ -6223,12 +6744,6 @@ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", "dev": true }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", - "dev": true - }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -6269,44 +6784,24 @@ } }, "log-update": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", - "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", "dev": true, "requires": { - "ansi-escapes": "^1.0.0", - "cli-cursor": "^1.0.2" + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" }, "dependencies": { - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", "dev": true, "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" } } } @@ -6323,15 +6818,6 @@ "integrity": "sha1-0GWXxNTDG1LMsfXY+P5xSOr9aWU=", "dev": true }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true, - "requires": { - "js-tokens": "^3.0.0" - } - }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -6348,22 +6834,6 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, - "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "macos-release": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-1.1.0.tgz", - "integrity": "sha512-mmLbumEYMi5nXReB9js3WGsB8UE6cDBWyIO62Z4DNx6GbRhDxHNjA1MlzSpJ2S2KM1wyiPRA0d19uHWYYvMHjA==", - "dev": true - }, "make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", @@ -6381,6 +6851,15 @@ } } }, + "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==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -6426,6 +6905,12 @@ "traverse": "^0.6.6" } }, + "marky": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.1.tgz", + "integrity": "sha512-md9k+Gxa3qLH6sUKpeC2CNkJK/Ld+bEz5X96nYwloqphQE0CKCVEKco/6jxEZixinqNdz5RFi/KaCyfbMDMAXQ==", + "dev": true + }, "md5.js": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", @@ -6436,13 +6921,38 @@ "inherits": "^2.0.1" } }, + "mdn-browser-compat-data": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdn-browser-compat-data/-/mdn-browser-compat-data-1.0.1.tgz", + "integrity": "sha512-FxRIu4UYu4rRdFs5JFf6del6J+OpbOq2tYfIEK7N/PtEtz6yGVcWcytmh5L5hZxe58kuxUzjgR8+/0TRyRzRqA==", + "dev": true, + "requires": { + "extend": "3.0.2" + } + }, "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", + "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^2.1.0", + "p-is-promise": "^2.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "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==", + "dev": true + } } }, "memory-fs": { @@ -6462,20 +6972,20 @@ "dev": true }, "meow": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", - "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", "dev": true, "requires": { "camelcase-keys": "^4.0.0", "decamelize-keys": "^1.0.0", "loud-rejection": "^1.0.0", - "minimist": "^1.1.3", "minimist-options": "^3.0.1", "normalize-package-data": "^2.3.4", "read-pkg-up": "^3.0.0", "redent": "^2.0.0", - "trim-newlines": "^2.0.0" + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" } }, "methods": { @@ -6524,9 +7034,9 @@ } }, "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", "dev": true }, "mime-db": { @@ -6550,6 +7060,12 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -6588,9 +7104,9 @@ } }, "minipass": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.4.tgz", - "integrity": "sha512-mlouk1OHlaUE8Odt1drMtG1bAJA4ZA6B/ehysgV0LUIrDHdKgo1KorZq3pK0b/7Z7LJIQ12MNM6aC+Tn6lUZ5w==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "requires": { "safe-buffer": "^5.1.2", @@ -6598,26 +7114,26 @@ }, "dependencies": { "yallist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true } } }, "minizlib": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", - "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, "requires": { - "minipass": "^2.2.1" + "minipass": "^2.9.0" } }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -6635,24 +7151,6 @@ } } }, - "mixin-object": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", - "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", - "dev": true, - "requires": { - "for-in": "^0.1.3", - "is-extendable": "^0.1.1" - }, - "dependencies": { - "for-in": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", - "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", - "dev": true - } - } - }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -6710,9 +7208,9 @@ } }, "moment": { - "version": "2.22.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", - "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=", + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==", "dev": true, "optional": true }, @@ -6728,6 +7226,33 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + } + } + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -6830,96 +7355,6 @@ "integrity": "sha1-F7CVgZiJef3a/gIB6TG6kzyWy7Q=", "dev": true }, - "nconf": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.10.0.tgz", - "integrity": "sha512-fKiXMQrpP7CYWJQzKkPPx9hPgmq+YLDyxcG9N8RpiE9FoCkCbzD0NyW0YhE3xn3Aupe7nnDeIx4PFzYehpHT9Q==", - "dev": true, - "requires": { - "async": "^1.4.0", - "ini": "^1.3.0", - "secure-keys": "^1.0.0", - "yargs": "^3.19.0" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "dev": true, - "requires": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" - } - } - } - }, "ncp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", @@ -6927,29 +7362,12 @@ "dev": true, "optional": true }, - "needle": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.1.tgz", - "integrity": "sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q==", - "dev": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, "neo-async": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==", "dev": true }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", - "dev": true - }, "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", @@ -6963,19 +7381,15 @@ "dev": true }, "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "dev": true, - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "dev": true }, "node-forge": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", - "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", + "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==", "dev": true }, "node-libs-browser": { @@ -7035,64 +7449,41 @@ } }, "node-notifier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz", - "integrity": "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-6.0.0.tgz", + "integrity": "sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw==", "dev": true, "requires": { "growly": "^1.3.0", - "semver": "^5.4.1", - "shellwords": "^0.1.1", - "which": "^1.3.0" - } - }, - "node-status-codes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", - "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", - "dev": true - }, - "nomnom": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", - "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", - "dev": true, - "requires": { - "chalk": "~0.4.0", - "underscore": "~1.6.0" + "is-wsl": "^2.1.1", + "semver": "^6.3.0", + "shellwords": "^0.1.1", + "which": "^1.3.1" }, "dependencies": { - "ansi-styles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, - "chalk": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", - "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "ansi-styles": "~1.0.0", - "has-color": "~0.1.0", - "strip-ansi": "~0.1.0" + "isexe": "^2.0.0" } - }, - "strip-ansi": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", - "dev": true - }, - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true } } }, + "node-status-codes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", + "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", + "dev": true + }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -7114,6 +7505,12 @@ "remove-trailing-separator": "^1.0.1" } }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true + }, "npm-run-all": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.3.tgz", @@ -7165,9 +7562,9 @@ } }, "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "dev": true, "requires": { "boolbase": "~1.0.0" @@ -7213,6 +7610,18 @@ } } }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", + "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==", + "dev": true + }, "object-keys": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", @@ -7228,6 +7637,18 @@ "isobject": "^3.0.0" } }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -7255,13 +7676,13 @@ "mimic-fn": "^1.0.0" } }, - "opn": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", - "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", + "open": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.0.0.tgz", + "integrity": "sha512-K6EKzYqnwQzk+/dzJAQSBORub3xlBTxMz+ntpZpH/LyCa1o6KjXhuN+2npAaI9jaSmU3R1Q8NWf4KUWcyytGsQ==", "dev": true, "requires": { - "is-wsl": "^1.1.0" + "is-wsl": "^2.1.0" } }, "optionator": { @@ -7278,67 +7699,6 @@ "wordwrap": "~1.0.0" } }, - "ora": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", - "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", - "dev": true, - "requires": { - "chalk": "^1.1.1", - "cli-cursor": "^1.0.2", - "cli-spinners": "^0.1.2", - "object-assign": "^4.0.1" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "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" - } - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -7352,24 +7712,31 @@ "dev": true }, "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, - "os-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-2.0.1.tgz", - "integrity": "sha1-uaOGNhwXrjohc27wWZQFyajF3F4=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-4.0.0.tgz", + "integrity": "sha512-HsSR1+2l6as4Wp2SGZxqLnuFHxVvh1Ir9pvZxyujsC13egZVe7P0YeBLN0ijQzM/twrO5To3ia3jzBXAvpMTEA==", "dev": true, "requires": { - "macos-release": "^1.0.0", - "win-release": "^1.0.0" + "execa": "^1.0.0", + "lcid": "^3.0.0", + "mem": "^5.0.0" + }, + "dependencies": { + "invert-kv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-3.0.0.tgz", + "integrity": "sha512-JzF8q2BeZA1ZkE3XROwRpoMQ9ObMgTtp0JH8EXewlbkikuOj2GPLIpUipdO+VL8QsTr2teAJD02EFGGL5cO7uw==", + "dev": true + }, + "lcid": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-3.1.1.tgz", + "integrity": "sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==", + "dev": true, + "requires": { + "invert-kv": "^3.0.0" + } + } } }, "os-shim": { @@ -7384,16 +7751,34 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, + "p-is-promise": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", + "dev": true + }, "p-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "requires": { "p-try": "^1.0.0" @@ -7409,9 +7794,9 @@ } }, "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true }, "p-try": { @@ -7420,94 +7805,66 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, - "pac-proxy-agent": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz", - "integrity": "sha512-cDNAN1Ehjbf5EHkNY5qnRhGPUCp6SnpyVof5fRzN800QV1Y2OkzbH9rmjZkbBRa8igof903yOnjIl6z0SlAhxA==", + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", "dev": true, "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^3.0.0" + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" }, "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { - "ms": "2.0.0" + "pump": "^3.0.0" } - } - } - }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "dev": true, - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - } - }, - "package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", - "dev": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true }, "got": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", "dev": true, "requires": { - "create-error-class": "^3.0.0", + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - } - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } } } }, @@ -7517,6 +7874,23 @@ "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", "dev": true }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, "parse-asn1": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", @@ -7568,16 +7942,6 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, - "path": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", - "dev": true, - "requires": { - "process": "^0.11.1", - "util": "^0.10.3" - } - }, "path-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", @@ -7615,9 +7979,9 @@ "dev": true }, "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "path-type": { @@ -7633,124 +7997,44 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "~2.3" - } - }, - "pbkdf2": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", - "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "phantom": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/phantom/-/phantom-4.0.12.tgz", - "integrity": "sha512-Tz82XhtPmwCk1FFPmecy7yRGZG2btpzY2KI9fcoPT7zT9det0CcMyfBFPp1S8DqzsnQnm8ZYEfdy528mwVtksA==", - "dev": true, - "optional": true, - "requires": { - "phantomjs-prebuilt": "^2.1.16", - "split": "^1.0.1", - "winston": "^2.4.0" - }, - "dependencies": { - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "optional": true, - "requires": { - "through": "2" - } - } - } - }, - "phantomjs-prebuilt": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", - "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", - "dev": true, - "optional": true, - "requires": { - "es6-promise": "^4.0.3", - "extract-zip": "^1.6.5", - "fs-extra": "^1.0.0", - "hasha": "^2.2.0", - "kew": "^0.7.0", - "progress": "^1.1.8", - "request": "^2.81.0", - "request-progress": "^2.0.1", - "which": "^1.2.10" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", - "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", - "dev": true, - "optional": true - }, - "fs-extra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", - "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" - } - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true, - "optional": true + "dev": true } } }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "~2.3" + } + }, + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -7773,25 +8057,23 @@ } }, "pino": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/pino/-/pino-4.16.1.tgz", - "integrity": "sha512-ST/IC5RMyqrOZL+Hq6LDwz5h4fGKABXzx2/5Ze7rz5TjuPvE8uI72dzj409xkq9JjyWsKoOOApgXn8kEjJ73yg==", + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-5.14.0.tgz", + "integrity": "sha512-Vj1f2wAojTGesogT0hsA/ua8ALltCOBCcA1nkEoDfnTsVWpgBu5UVSY7OdjiGmrMOKHBm24nd3nKXzyPUYJ3ig==", "dev": true, "requires": { - "chalk": "^2.3.2", - "fast-json-parse": "^1.0.3", - "fast-safe-stringify": "^1.2.3", - "flatstr": "^1.0.5", - "pino-std-serializers": "^2.0.0", - "pump": "^3.0.0", - "quick-format-unescaped": "^1.1.2", - "split2": "^2.2.0" + "fast-redact": "^2.0.0", + "fast-safe-stringify": "^2.0.7", + "flatstr": "^1.0.12", + "pino-std-serializers": "^2.4.2", + "quick-format-unescaped": "^3.0.3", + "sonic-boom": "^0.7.5" } }, "pino-std-serializers": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-2.1.0.tgz", - "integrity": "sha512-NqWvrQD/GpY78ybiNBzi/dg8ylERhDo6nB33j5sfCKpUmWLc3lYzeoBjyRoCMvEpDpL9lmH6ufRd0jw6rcd1pQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-2.4.2.tgz", + "integrity": "sha512-WaL504dO8eGs+vrK+j4BuQQq6GLKeCCcHaMB2ItygzVURcL1CycwNEUHTD/lHFHs/NL5qAz2UKrjYWXKSf4aMQ==", "dev": true }, "pluralize": { @@ -7800,16 +8082,6 @@ "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, - "po2json": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/po2json/-/po2json-0.4.5.tgz", - "integrity": "sha1-R7spUtoy1Yob4vJWpZjuvAt0URg=", - "dev": true, - "requires": { - "gettext-parser": "1.1.0", - "nomnom": "1.8.1" - } - }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -7817,16 +8089,47 @@ "dev": true }, "postcss": { - "version": "6.0.19", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.19.tgz", - "integrity": "sha512-f13HRz0HtVwVaEuW6J6cOUCBLFtymhgyLPV7t4QEk2UD3twRI9IluDcQNdzQdBpiixkXj2OmzejhhTbSbDxNTg==", + "version": "7.0.24", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.24.tgz", + "integrity": "sha512-Xl0XvdNWg+CblAXzNvbSOUvgJXwSjmbAKORqyw9V2AlHrm1js2gFw9y3jibBAhpKZi8b5JzJCVh/FyzPsTtgTA==", "dev": true, "requires": { - "chalk": "^2.3.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.2.0" + "supports-color": "^6.1.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" + }, + "dependencies": { + "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" + } + } + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7834,9 +8137,9 @@ "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": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -7884,20 +8187,13 @@ "integrity": "sha1-wa0g6APndJ+vkFpAnSNn4Gu+cyU=", "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==", - "dev": true - }, "probe-image-size": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-4.0.0.tgz", - "integrity": "sha512-nm7RvWUxps+2+jZKNLkd04mNapXNariS6G5WIEVzvAqjx7EUuKcY1Dp3e6oUK7GLwzJ+3gbSbPLFAASHFQrPcQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-5.0.0.tgz", + "integrity": "sha512-V6uBYw5eBc5UVIE7MUZD6Nxg0RYuGDWLDenEn0B1WC6PcTvn1xdQ6HLDDuznefsiExC6rNrCz7mFRBo0f3Xekg==", "dev": true, "requires": { - "any-promise": "^1.3.0", - "deepmerge": "^2.0.1", + "deepmerge": "^4.0.0", "inherits": "^2.0.3", "next-tick": "^1.0.0", "request": "^2.83.0", @@ -7922,48 +8218,6 @@ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", "dev": true }, - "promise": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.0.1.tgz", - "integrity": "sha1-5F1osAoXZHttpxG/he1u1HII9FA=", - "dev": true, - "requires": { - "asap": "~2.0.3" - } - }, - "proxy-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.0.tgz", - "integrity": "sha512-g6n6vnk8fRf705ShN+FEXFG/SDJaW++lSs0d9KaJh4uBWW/wi7en4Cpo5VYQW3SZzAE121lhB/KLQrbURoubZw==", - "dev": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "pac-proxy-agent": "^2.0.1", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^3.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true - }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -7985,6 +8239,12 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, + "psl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", + "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==", + "dev": true + }, "public-encrypt": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", @@ -8032,13 +8292,10 @@ "dev": true }, "quick-format-unescaped": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-1.1.2.tgz", - "integrity": "sha1-DKWB3jF0vs7yWsPC6JVjQjgdtpg=", - "dev": true, - "requires": { - "fast-safe-stringify": "^1.0.8" - } + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-3.0.3.tgz", + "integrity": "sha512-dy1yjycmn9blucmJLXOfZDx1ikZJUi6E8bBZLnhPG5gBrVhHXx2xVyqqgKBubVNEXmx51dBACMHpoMQK/N/AXQ==", + "dev": true }, "quick-lru": { "version": "1.1.0", @@ -8065,18 +8322,6 @@ "safe-buffer": "^5.1.0" } }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, "rc": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/rc/-/rc-0.6.0.tgz", @@ -8198,15 +8443,6 @@ "resolve": "^1.1.6" } }, - "recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", - "dev": true, - "requires": { - "minimatch": "3.0.4" - } - }, "redent": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", @@ -8215,20 +8451,12 @@ "requires": { "indent-string": "^3.0.0", "strip-indent": "^2.0.0" - }, - "dependencies": { - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - } } }, "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", "dev": true }, "regex-not": { @@ -8241,6 +8469,96 @@ "safe-regex": "^1.1.0" } }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "es-abstract": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0.tgz", + "integrity": "sha512-yYkE07YF+6SIBmg1MsJ9dlub5L48Ek7X0qz+c/CPCHS9EBXfESorzng4cJQjJW5/pB6vDF41u7F8vUhLVDqIug==", + "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.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "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" + } + }, + "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" + } + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "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" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, "regexpp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", @@ -8248,12 +8566,12 @@ "dev": true }, "registry-auth-token": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", - "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.0.0.tgz", + "integrity": "sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw==", "dev": true, "requires": { - "rc": "^1.1.6", + "rc": "^1.2.8", "safe-buffer": "^5.0.1" }, "dependencies": { @@ -8278,12 +8596,12 @@ } }, "registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", "dev": true, "requires": { - "rc": "^1.0.1" + "rc": "^1.2.8" }, "dependencies": { "deep-extend": { @@ -8307,35 +8625,42 @@ } }, "relaxed-json": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/relaxed-json/-/relaxed-json-1.0.1.tgz", - "integrity": "sha1-fI1KovCVcEzQIOMugJm8rhA/C9Q=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/relaxed-json/-/relaxed-json-1.0.3.tgz", + "integrity": "sha512-b7wGPo7o2KE/g7SqkJDDbav6zmrEeP4TK2VpITU72J/M949TLe/23y/ZHJo+pskcGM52xIfFoT9hydwmgr1AEg==", "dev": true, "requires": { - "chalk": "^1.0.0", + "chalk": "^2.4.2", "commander": "^2.6.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": "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==", "dev": true, "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" } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "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": { - "ansi-regex": "^2.0.0" + "has-flag": "^3.0.0" } } } @@ -8402,15 +8727,6 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, "request": { "version": "2.85.0", "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", @@ -8449,16 +8765,6 @@ } } }, - "request-progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", - "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", - "dev": true, - "optional": true, - "requires": { - "throttleit": "^1.0.0" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -8482,12 +8788,12 @@ } }, "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", + "integrity": "sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "^1.0.6" } }, "resolve-from": { @@ -8502,6 +8808,15 @@ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", @@ -8571,20 +8886,12 @@ } }, "rxjs": { - "version": "5.5.10", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.10.tgz", - "integrity": "sha512-SRjimIDUHJkon+2hFo7xnvNC4ZEHGzCRwh9P7nzX3zPkCGFEg/tuElrNR7L/rZMagnK2JeH2jQwPRpmyXyLB6A==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", "dev": true, "requires": { - "symbol-observable": "1.0.1" - }, - "dependencies": { - "symbol-observable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", - "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", - "dev": true - } + "tslib": "^1.9.0" } }, "safe-buffer": { @@ -8621,12 +8928,6 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, - "secure-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz", - "integrity": "sha1-8MgtmKOxOah3aogIBQuCRDEIf8o=", - "dev": true - }, "seek-bzip": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", @@ -8677,12 +8978,20 @@ "dev": true }, "semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", "dev": true, "requires": { - "semver": "^5.0.3" + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "set-blocking": { @@ -8698,9 +9007,9 @@ "dev": true }, "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -8726,20 +9035,13 @@ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, "sha": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/sha/-/sha-2.0.1.tgz", - "integrity": "sha1-YDCCL70smCOUn49y7WQR7lzyWq4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/sha/-/sha-3.0.0.tgz", + "integrity": "sha512-DOYnM37cNsLNSGIG/zZWch5CKIRNoLdYUQTQlcgkRkoYIUwDYjqDyye16YcDZg/OPdcbUgTKMjc4SY6TB7ZAPw==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "readable-stream": "^2.0.2" + "graceful-fs": "^4.1.2" } }, "sha.js": { @@ -8752,29 +9054,6 @@ "safe-buffer": "^5.0.1" } }, - "shallow-clone": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", - "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", - "dev": true, - "requires": { - "is-extendable": "^0.1.1", - "kind-of": "^2.0.1", - "lazy-cache": "^0.2.3", - "mixin-object": "^2.0.1" - }, - "dependencies": { - "kind-of": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", - "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", - "dev": true, - "requires": { - "is-buffer": "^1.0.2" - } - } - } - }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -8802,12 +9081,6 @@ "jsonify": "~0.0.0" } }, - "shelljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", - "dev": true - }, "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", @@ -8820,99 +9093,144 @@ "integrity": "sha1-2yBiSamGlJkVnThHxxiYV1lfgM0=" }, "sign-addon": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/sign-addon/-/sign-addon-0.3.1.tgz", - "integrity": "sha512-feaoG7+8IXr9SymOEd8VTZCSlVZArWcBDZ33IIdfXlU5NWWzXdCxCjPDqAkLQplFa7RRZr1S4lSmgMPn80Ze1A==", - "dev": true, - "requires": { - "babel-polyfill": "6.16.0", - "deepcopy": "0.6.3", - "es6-error": "4.0.0", - "es6-promisify": "5.0.0", - "jsonwebtoken": "8.2.1", - "mz": "2.5.0", - "request": "2.87.0", - "source-map-support": "0.4.6", - "stream-to-promise": "2.2.0", - "when": "3.7.7" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sign-addon/-/sign-addon-2.0.4.tgz", + "integrity": "sha512-QKfE558nIQ2o9VACAIMQBI4I+IhlL+k9bxhVsQUb4B6Bu+tC8IDSlnHrydcYPf3AB6K+g+BVzbDD1JlSw4bRDg==", + "dev": true, + "requires": { + "common-tags": "1.8.0", + "core-js": "3.6.0", + "deepcopy": "2.0.0", + "es6-error": "4.1.1", + "es6-promisify": "6.0.2", + "jsonwebtoken": "8.5.1", + "mz": "2.7.0", + "request": "2.88.0", + "source-map-support": "0.5.16", + "stream-to-promise": "2.2.0" }, "dependencies": { - "babel-polyfill": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.16.0.tgz", - "integrity": "sha1-LUUCHfh+JqN0ttTRqcZZZNF/JCI=", + "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": { - "babel-runtime": "^6.9.1", - "core-js": "^2.4.0", - "regenerator-runtime": "^0.9.5" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "es6-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.0.0.tgz", - "integrity": "sha1-8JTHBB9mJZm7EnINoFnWucf/D0A=", + "aws4": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", + "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==", "dev": true }, - "mz": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.5.0.tgz", - "integrity": "sha1-KFkCXfA9RrV7sxcXSxlkd85kzsE=", + "core-js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.0.tgz", + "integrity": "sha512-AHPTNKzyB+YwgDWoSOCaid9PUSEF6781vsfiK8qUz62zRR448/XgK2NtCbpiUGizbep8Lrpt0Du19PpGGZvw3Q==", + "dev": true + }, + "es6-promisify": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.0.2.tgz", + "integrity": "sha512-eO6vFm0JvqGzjWIQA6QVKjxpmELfhWbDUWHm1rPfIbn55mhKPiAa5xpLmQWJrNa629ZIeQ8ZvMAi13kvrjK6Mg==", + "dev": true + }, + "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==", "dev": true, "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "mime-db": { + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", + "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.25", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", + "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", + "dev": true, + "requires": { + "mime-db": "1.42.0" } }, - "regenerator-runtime": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz", - "integrity": "sha1-0z65XQ0gAaS+OWWXB8UbDLcc4Ck=", + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, "request": { - "version": "2.87.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", - "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "dev": true, "requires": { "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", + "aws4": "^1.8.0", "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "tough-cookie": "~2.3.3", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" + "uuid": "^3.3.2" } }, - "source-map-support": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.6.tgz", - "integrity": "sha1-MlUqpktFg5KoXqs7C17mFScWeus=", + "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==", "dev": true, "requires": { - "source-map": "^0.5.3" + "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=", + "dev": true + } } }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } } } }, @@ -8922,12 +9240,6 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, "slice-ansi": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", @@ -8938,20 +9250,15 @@ } }, "slugid": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/slugid/-/slugid-1.1.0.tgz", - "integrity": "sha1-4J8AiZwJ9acFjtw23UnwRv1QqCo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slugid/-/slugid-2.0.0.tgz", + "integrity": "sha512-zTCivUfTk2GC6MU4Fjcz0iXwAjhe0NweMJqpfWcGrBbrm2dWtVAUupAonfsc7ysw4M0kZ934Nle5ljwM2dR+/g==", "dev": true, "requires": { - "uuid": "^2.0.1" + "uuid": "^3.2.1", + "uuid-parse": "^1.0.0" } }, - "smart-buffer": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", - "dev": true - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -9026,371 +9333,50 @@ "kind-of": "^6.0.0" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - } - }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - }, - "snyk": { - "version": "1.83.0", - "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.83.0.tgz", - "integrity": "sha1-IH+y9HMGcZ9iZk0tLo6AeylLrqA=", - "dev": true, - "requires": { - "abbrev": "^1.1.1", - "ansi-escapes": "^3.1.0", - "chalk": "^2.4.1", - "configstore": "^3.1.2", - "debug": "^3.1.0", - "hasbin": "^1.2.3", - "inquirer": "^3.0.0", - "lodash": "^4.17.5", - "needle": "^2.0.1", - "opn": "^5.2.0", - "os-name": "^2.0.1", - "proxy-agent": "^3.0.0", - "proxy-from-env": "^1.0.0", - "recursive-readdir": "^2.2.2", - "semver": "^5.5.0", - "snyk-config": "2.1.0", - "snyk-go-plugin": "1.5.1", - "snyk-gradle-plugin": "1.3.0", - "snyk-module": "1.8.2", - "snyk-mvn-plugin": "1.2.0", - "snyk-nuget-plugin": "1.6.2", - "snyk-php-plugin": "1.5.1", - "snyk-policy": "1.12.0", - "snyk-python-plugin": "1.6.1", - "snyk-resolve": "1.0.1", - "snyk-resolve-deps": "3.1.0", - "snyk-sbt-plugin": "1.3.0", - "snyk-tree": "^1.0.0", - "snyk-try-require": "1.3.1", - "tempfile": "^2.0.0", - "then-fs": "^2.0.0", - "undefsafe": "^2.0.0", - "uuid": "^3.2.1" - }, - "dependencies": { - "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" - } - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true - } - } - }, - "snyk-config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/snyk-config/-/snyk-config-2.1.0.tgz", - "integrity": "sha512-D1Xz1pZa9lwA9AHogmAigyJGo/iuEGH+rcPB77mFsneVfnuiK9c6IjnsHbEBUf1cePtZvWdGBjs6e75Cvc2AMg==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "nconf": "^0.10.0" - }, - "dependencies": { - "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" - } - } - } - }, - "snyk-go-plugin": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/snyk-go-plugin/-/snyk-go-plugin-1.5.1.tgz", - "integrity": "sha512-8OPJOT05Z/UL5fFSXV6b/A6KjlS1Ahr2gpup1bhXtAGXlUUPyWidqkCIER9fexDXqYWgAoDAdn9YHIvmL/5bfw==", - "dev": true, - "requires": { - "graphlib": "^2.1.1", - "tmp": "0.0.33", - "toml": "^2.3.2" - } - }, - "snyk-gradle-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/snyk-gradle-plugin/-/snyk-gradle-plugin-1.3.0.tgz", - "integrity": "sha512-rKZcPwbDM9zk3pFcO0w77MIKOZTkk5ZBVBkBlTlUiFg+eNOKqPTmw2hBGF5NB4ASQmMnx3uB1C8+hrQ405CthA==", - "dev": true, - "requires": { - "clone-deep": "^0.3.0" - } - }, - "snyk-module": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/snyk-module/-/snyk-module-1.8.2.tgz", - "integrity": "sha512-XqhdbZ/CUuJ5gSaYdYfapLqx9qm2Mp6nyRMBCLXe9tJSiohOJsc9fQuUDbdOiRCqpA4BD6WLl+qlwOJmJoszBg==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "hosted-git-info": "^2.1.4" - }, - "dependencies": { - "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" - } - } - } - }, - "snyk-mvn-plugin": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/snyk-mvn-plugin/-/snyk-mvn-plugin-1.2.0.tgz", - "integrity": "sha512-ieTWhn1MB88gEQ6nUtGCeUKQ6Xoxm+u+QmD9u3zfP1QS5ep9fWt3YYDUQjgUiDTJJy7QyVQdZ/fsz3RECnOA7w==", - "dev": true - }, - "snyk-nuget-plugin": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/snyk-nuget-plugin/-/snyk-nuget-plugin-1.6.2.tgz", - "integrity": "sha512-8l8hS85esXyweTFgUFdwnGT94Ts42KcG5fdBX2wYosQkpUMePd+GTT9+64k/GvdH5hqcNt2OvtzW+Uf8JF+pbA==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "es6-promise": "^4.1.1", - "lodash": "^4.17.10", - "xml2js": "^0.4.17", - "zip": "^1.2.0" - }, - "dependencies": { - "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" - } - }, - "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", - "dev": true - } - } - }, - "snyk-php-plugin": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/snyk-php-plugin/-/snyk-php-plugin-1.5.1.tgz", - "integrity": "sha512-g5QSHBsRJ2O4cNxKC4zlWwnQYiSgQ77Y6QgGmo3ihPX3VLZrc1amaZIpPsNe1jwXirnGj2rvR5Xw+jDjbzvHFw==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash": "^4.17.5", - "path": "0.12.7" - }, - "dependencies": { - "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" - } - } - } - }, - "snyk-policy": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/snyk-policy/-/snyk-policy-1.12.0.tgz", - "integrity": "sha512-CEioNnDzccHyid7UIVl3bJ1dnG4co4ofI+KxuC1mo0IUXy64gxnBTeVoZF5gVLWbAyxGxSeW8f0+8GmWMHVb7w==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "email-validator": "^2.0.3", - "js-yaml": "^3.5.3", - "lodash.clonedeep": "^4.3.1", - "semver": "^5.5.0", - "snyk-module": "^1.8.2", - "snyk-resolve": "^1.0.1", - "snyk-try-require": "^1.1.1", - "then-fs": "^2.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "snyk-python-plugin": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/snyk-python-plugin/-/snyk-python-plugin-1.6.1.tgz", - "integrity": "sha512-6zr5jAB3p/bwMZQxZpdj+aPmioTgHB4DI6JMLInhZupss0x8Ome5YqzVzBbOvUKNrc3KaLtjGrJWcAuxDL6M/g==", - "dev": true, - "requires": { - "tmp": "0.0.33" - } - }, - "snyk-resolve": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/snyk-resolve/-/snyk-resolve-1.0.1.tgz", - "integrity": "sha512-7+i+LLhtBo1Pkth01xv+RYJU8a67zmJ8WFFPvSxyCjdlKIcsps4hPQFebhz+0gC5rMemlaeIV6cqwqUf9PEDpw==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "then-fs": "^2.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "snyk-resolve-deps": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/snyk-resolve-deps/-/snyk-resolve-deps-3.1.0.tgz", - "integrity": "sha512-YVAelR+dTpqLgfk6lf6WgOlw+MGmGI0r3/Dny8tUbJJ9uVTHTRAOdZCbUyTFqJG7oEmEZxUwmfjqgAuniYwx8Q==", - "dev": true, - "requires": { - "ansicolors": "^0.3.2", - "debug": "^3.1.0", - "lodash.assign": "^4.2.0", - "lodash.assignin": "^4.2.0", - "lodash.flatten": "^4.4.0", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", - "lru-cache": "^4.0.0", - "semver": "^5.1.0", - "snyk-module": "^1.6.0", - "snyk-resolve": "^1.0.0", - "snyk-tree": "^1.0.0", - "snyk-try-require": "^1.1.1", - "then-fs": "^2.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "snyk-sbt-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/snyk-sbt-plugin/-/snyk-sbt-plugin-1.3.0.tgz", - "integrity": "sha512-SRxPB16392dvN3Qv2RfUcHe0XETLWx2kNIOuoNXvc2Gl6DuPW+X+meDJY7xC/yQhU7bSPPKoM2B7awYaj9i2Bg==", - "dev": true, - "requires": { - "debug": "^2.2.0" - } - }, - "snyk-tree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/snyk-tree/-/snyk-tree-1.0.0.tgz", - "integrity": "sha1-D7cxdtvzLngvGRAClBYESPkRHMg=", - "dev": true, - "requires": { - "archy": "^1.0.0" - } - }, - "snyk-try-require": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/snyk-try-require/-/snyk-try-require-1.3.1.tgz", - "integrity": "sha1-bgJvkuZK9/zM6h7lPVJIQeQYohI=", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash.clonedeep": "^4.3.0", - "lru-cache": "^4.0.0", - "then-fs": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "ms": "2.0.0" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, - "socks": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", - "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + } + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "dev": true, "requires": { - "ip": "^1.1.4", - "smart-buffer": "^1.0.13" + "hoek": "4.x.x" } }, - "socks-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz", - "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", + "sonic-boom": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-0.7.6.tgz", + "integrity": "sha512-k9E2QQ4zxuVRLDW+ZW6ISzJs3wlEorVdmM7ApDgor7wsGKSDG5YGHsGmgLY4XYh4DMlr/2ap2BWAE7yTFJtWnQ==", "dev": true, "requires": { - "agent-base": "^4.1.0", - "socks": "^1.1.10" + "flatstr": "^1.0.12" } }, "source-list-map": { @@ -9419,11 +9405,12 @@ } }, "source-map-support": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.3.tgz", - "integrity": "sha512-eKkTgWYeBOQqFGXRfKabMFdnWepo51vWqEdoeikaEPFiJC7MCU5j2h4+6Q8npkZTeLGbSyecZvRxiSoWl3rh+w==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "dev": true, "requires": { + "buffer-from": "^1.0.0", "source-map": "^0.6.0" }, "dependencies": { @@ -9501,15 +9488,6 @@ "extend-shallow": "^3.0.0" } }, - "split2": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", - "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", - "dev": true, - "requires": { - "through2": "^2.0.2" - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -9533,13 +9511,6 @@ "tweetnacl": "~0.14.0" } }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "optional": true - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -9561,12 +9532,6 @@ } } }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, "stream-browserify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", @@ -9617,15 +9582,6 @@ "any-promise": "^1.1.0" } }, - "stream-to-observable": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.2.0.tgz", - "integrity": "sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA=", - "dev": true, - "requires": { - "any-observable": "^0.2.0" - } - }, "stream-to-promise": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/stream-to-promise/-/stream-to-promise-2.2.0.tgz", @@ -9678,6 +9634,60 @@ "function-bind": "^1.0.2" } }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -9729,22 +9739,22 @@ "dev": true }, "strip-bom-buf": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz", - "integrity": "sha1-HLRar1dTD0yvhsf3UXnSyaUd1XI=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-2.0.0.tgz", + "integrity": "sha512-gLFNHucd6gzb8jMsl5QmZ3QgnUJmp7qn4uUSHNwEXumAp7YizoGYw19ZUVfuq4aBOQUtyn2k8X/CwzWB73W2lQ==", "dev": true, "requires": { "is-utf8": "^0.2.1" } }, "strip-bom-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-3.0.0.tgz", - "integrity": "sha1-lWvMXYRDD2klapDtgjdlzYWOFZw=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-4.0.0.tgz", + "integrity": "sha512-0ApK3iAkHv6WbgLICw/J4nhwHeDZsBxIIsOD+gHgZICL6SeJ0S9f/WZqemka9cjkTyMN5geId6e8U5WGFAn3cQ==", "dev": true, "requires": { - "first-chunk-stream": "^2.0.0", - "strip-bom-buf": "^1.0.0" + "first-chunk-stream": "^3.0.0", + "strip-bom-buf": "^2.0.0" } }, "strip-dirs": { @@ -9784,31 +9794,87 @@ } }, "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.1.3.tgz", + "integrity": "sha512-2bno1Nb4uvZPECTJ7NDYlae6Q8LLQoZZZ9Vumd346jU1UGVkNC/lQI42jHwtrqVoepyt0QxNKFty01IRKgD4CA==", "dev": true, "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.2", + "debug": "^4.1.1", + "fast-safe-stringify": "^2.0.7", + "form-data": "^3.0.0", + "formidable": "^1.2.1", + "methods": "^1.1.2", + "mime": "^2.4.4", + "qs": "^6.9.1", + "readable-stream": "^3.4.0", + "semver": "^6.3.0" }, "dependencies": { + "combined-stream": { + "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" + } + }, + "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==", + "dev": true + }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "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.0.0" + "ms": "^2.1.1" + } + }, + "form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "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 + }, + "qs": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz", + "integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==", + "dev": true + }, + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -9819,9 +9885,9 @@ "dev": true }, "symbol-observable": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz", - "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", "dev": true }, "table": { @@ -9859,100 +9925,140 @@ } }, "tar": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.0.2.tgz", - "integrity": "sha512-4lWN4uAEWzw8aHyBUx9HWXvH3vIFEhOyvN22HfBzWpE07HaTBXM8ttSeCQpswRo5On4q3nmmYmk7Tomn0uhUaw==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.2.tgz", + "integrity": "sha512-BfkE9CciGGgDsATqkikUHrQrraBCO+ke/1f6SFAEMnxyyfN9lxC+nW1NFWMpqH865DhHIy9vQi682gk1X7friw==", "dev": true, "requires": { "chownr": "^1.0.1", - "minipass": "^2.2.1", - "minizlib": "^1.0.4", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", "yallist": "^3.0.2" }, "dependencies": { "yallist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true } } }, "tar-stream": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", - "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", "dev": true, "requires": { "bl": "^1.0.0", - "buffer-alloc": "^1.1.0", + "buffer-alloc": "^1.2.0", "end-of-stream": "^1.0.0", "fs-constants": "^1.0.0", "readable-stream": "^2.3.0", - "to-buffer": "^1.1.0", + "to-buffer": "^1.1.1", "xtend": "^4.0.0" } }, "taskcluster-client": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/taskcluster-client/-/taskcluster-client-3.4.0.tgz", - "integrity": "sha512-HfGZAkFzjtl82x7nnj6n02wD8auyRlMh1W12J6tQXuAAR4qK99UUCOwqm1UAfpu70WBAFC0O/gl3fEwxZ48n9g==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/taskcluster-client/-/taskcluster-client-19.0.0.tgz", + "integrity": "sha512-RVz4aZL16v8m0+ICt7MR/NrGo70z/AyAami2auYaingS7yEz82JpKk9qnKbF5oCs4NptacasHpndM/lhe01krw==", "dev": true, "requires": { - "amqplib": "^0.5.1", - "babel-runtime": "^6.26.0", - "debug": "^3.1.0", - "hawk": "^6.0.2", + "debug": "^4.0.0", + "hawk": "^7.0.10", "lodash": "^4.17.4", - "promise": "^8.0.1", - "slugid": "^1.1.0", - "superagent": "~3.8.1" + "slugid": "^2.0.0", + "superagent": "^5.0.0", + "taskcluster-lib-urls": "^12.0.0" }, "dependencies": { + "boom": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz", + "integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==", + "dev": true, + "requires": { + "hoek": "6.x.x" + } + }, + "cryptiles": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-4.1.3.tgz", + "integrity": "sha512-gT9nyTMSUC1JnziQpPbxKGBbUg8VL7Zn2NB4E1cJYvuXdElHrwxrV9bmltZGDzet45zSDGyYceueke1TjynGzw==", + "dev": true, + "requires": { + "boom": "7.x.x" + } + }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "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.0.0" + "ms": "^2.1.1" + } + }, + "hawk": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-7.0.10.tgz", + "integrity": "sha512-3RWF4SXN9CdZ1VDAe6Pn3Rd0tC3Lw+GV+esX5oKCrXoScZK3Ri6dl5Wt986M/hlzU+GuapTGiB0rBhGeRIBQsw==", + "dev": true, + "requires": { + "b64": "4.x.x", + "boom": "7.x.x", + "cryptiles": "4.x.x", + "hoek": "6.x.x", + "sntp": "3.x.x" + } + }, + "hoek": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", + "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", + "dev": true + }, + "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 + }, + "sntp": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-3.0.2.tgz", + "integrity": "sha512-MCAPpBPFjNp1fwDVCLSRuWuH9gONtb2R+lS1esC6Mp8lP6jy60FVUtP/Qr0jBvcWAVbhzx06y1b6ptXiy32dug==", + "dev": true, + "requires": { + "boom": "7.x.x", + "bounce": "1.x.x", + "hoek": "6.x.x", + "teamwork": "3.x.x" } } } }, - "temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "taskcluster-lib-urls": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/taskcluster-lib-urls/-/taskcluster-lib-urls-12.1.0.tgz", + "integrity": "sha512-zwHbZfhORlSylBrbYWevjNKcLgdTfcyANhvjGs5ckUuiJGeD0s19B7sDuYO0z5CZ6EmLOmY/LIRc7ZR772W/OA==", "dev": true }, - "tempfile": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", - "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", - "dev": true, - "requires": { - "temp-dir": "^1.0.0", - "uuid": "^3.0.1" - }, - "dependencies": { - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true - } - } + "teamwork": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/teamwork/-/teamwork-3.2.0.tgz", + "integrity": "sha512-xAmJ8PIVjRZMXAHgUuOP8ITsv0SedyWAit2UWiNImXgg/F+BxrsG46ZegElNBM0Dwp+iMfbigg/Ll/M2oDRYww==", + "dev": true }, "term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "dev": true, - "requires": { - "execa": "^0.7.0" - } + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.1.1.tgz", + "integrity": "sha512-UqvQSch04R+69g4RDhrslmGvGL3ucDRX/U+snYW0Mab4uCAyKSndUksaoqlJ81QKSpRnIsuOYQCbC2ZWx2896A==", + "dev": true }, "text-table": { "version": "0.2.0", @@ -9960,26 +10066,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "then-fs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/then-fs/-/then-fs-2.0.0.tgz", - "integrity": "sha1-cveS3Z0xcFqRrhnr/Piz+WjIHaI=", - "dev": true, - "requires": { - "promise": ">=3.2 <8" - }, - "dependencies": { - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "dev": true, - "requires": { - "asap": "~2.0.3" - } - } - } - }, "thenify": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", @@ -9998,35 +10084,12 @@ "thenify": ">= 3.1.0 < 4" } }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true, - "optional": true - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - } - }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", - "dev": true - }, "timed-out": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-2.0.0.tgz", @@ -10063,12 +10126,6 @@ "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", "dev": true }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -10078,6 +10135,12 @@ "kind-of": "^3.0.2" } }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", @@ -10100,18 +10163,6 @@ "repeat-string": "^1.6.1" } }, - "to-utf8": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", - "integrity": "sha1-0Xrqcv8vujm55DYBvns/9y4ImFI=", - "dev": true - }, - "toml": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.3.tgz", - "integrity": "sha512-O7L5hhSQHxuufWUdcTRPfuTh3phKfAZ/dqfxZFoxPCj2RYmpaSGLEIs016FCXItQwNr08yefUB5TSjzRYnajTA==", - "dev": true - }, "tosource": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tosource/-/tosource-1.0.0.tgz", @@ -10162,12 +10213,6 @@ "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", "dev": true }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, "trim-trailing-lines": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", @@ -10180,6 +10225,12 @@ "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==", "dev": true }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -10202,6 +10253,12 @@ "dev": true, "optional": true }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -10211,12 +10268,33 @@ "prelude-ls": "~1.1.2" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", @@ -10279,22 +10357,13 @@ "optional": true }, "unbzip2-stream": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz", - "integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==", - "dev": true, - "requires": { - "buffer": "^3.0.1", - "through": "^2.3.6" - } - }, - "undefsafe": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", - "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", + "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", "dev": true, "requires": { - "debug": "^2.2.0" + "buffer": "^5.2.1", + "through": "^2.3.8" } }, "underscore": { @@ -10313,12 +10382,6 @@ "xtend": "^4.0.1" } }, - "unicode-5.2.0": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/unicode-5.2.0/-/unicode-5.2.0-0.7.5.tgz", - "integrity": "sha512-KVGLW1Bri30x00yv4HNM8kBxoqFXr0Sbo55735nvrlsx4PYBZol3UtoWgO492fSwmsetzPEZzy73rbU8OGXJcA==", - "dev": true - }, "unified": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/unified/-/unified-4.2.1.tgz", @@ -10334,47 +10397,24 @@ } }, "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "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" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" } }, "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "dev": true, "requires": { - "crypto-random-string": "^1.0.0" + "crypto-random-string": "^2.0.0" } }, "unist-util-is": { @@ -10406,12 +10446,6 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -10465,20 +10499,75 @@ "dev": true }, "update-notifier": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.3.0.tgz", - "integrity": "sha1-TognpruRUUCrCTVZ1wFOPruDdFE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.0.0.tgz", + "integrity": "sha512-p9zf71hWt5GVXM4iEBujpUgx8mK9AWiCCapEJm/O1z5ntCim83Z1ATqzZFBHFYqx03laMqv8LiDgs/7ikXjf/g==", "dev": true, "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.0", + "has-yarn": "^2.1.0", "import-lazy": "^2.1.0", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.0.tgz", + "integrity": "sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "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.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": "^4.0.0" + } + } } }, "update-section": { @@ -10578,9 +10667,15 @@ "dev": true }, "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", + "dev": true + }, + "uuid-parse": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/uuid-parse/-/uuid-parse-1.1.0.tgz", + "integrity": "sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A==", "dev": true }, "validate-npm-package-license": { @@ -10625,6 +10720,43 @@ "indexof": "0.0.1" } }, + "vscode-json-languageservice": { + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.4.11.tgz", + "integrity": "sha512-26Qv1SFp6x3XmCqU1BRceRsSKRO3xkQa6/K8ziSRt52/LQPiw5ipSxlGVSlzIoi5LCmQVEqUajhiVEMNlFXhNw==", + "dev": true, + "requires": { + "jsonc-parser": "^2.2.0", + "vscode-languageserver-textdocument": "^1.0.0-next.5", + "vscode-languageserver-types": "^3.15.0-next.9", + "vscode-nls": "^4.1.1", + "vscode-uri": "^2.1.1" + } + }, + "vscode-languageserver-textdocument": { + "version": "1.0.0-next.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.0-next.5.tgz", + "integrity": "sha512-1jp/zAidN/bF/sqPimhBX1orH5G4rzRw63k75TesukJDuxm8yW79ECStWbDSy41BHGOwSGN4M69QFvhancSr5A==", + "dev": true + }, + "vscode-languageserver-types": { + "version": "3.15.0-next.9", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.9.tgz", + "integrity": "sha512-Rl/8qJ6932nrHCdPn+9y0x08uLVQaSLRG+U4JzhyKpWU4eJbVaDRoAcz1Llj7CErJGbPr6kdBvShPy5fRfR+Uw==", + "dev": true + }, + "vscode-nls": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.1.tgz", + "integrity": "sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A==", + "dev": true + }, + "vscode-uri": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.1.tgz", + "integrity": "sha512-eY9jmGoEnVf8VE8xr5znSah7Qt1P/xsCdErz+g8HYZtJ7bZqKH5E3d+6oVNm1AC/c6IHUDokbmVXKOi4qPAC9A==", + "dev": true + }, "watchpack": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.5.0.tgz", @@ -10646,76 +10778,284 @@ } }, "web-ext": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-2.7.0.tgz", - "integrity": "sha512-hXj/MV/x6G0oxplOirV4/j7BJ5MZJ2yZHml0gulBr7mH2BMNyTJHdRi+qzVBNPFdBMLV0/PS05YGZ7xr2YmwVA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-4.0.0.tgz", + "integrity": "sha512-778HKIoWpIrZzOq7rPA7Fu7YQ/fnZ6w9XCKUqGJRjo2NgOtgtkLmkd7lCw3gU7KJYe7hurI5XYossJMgjmyNaQ==", "dev": true, "requires": { + "@babel/polyfill": "7.7.0", + "@babel/runtime": "7.7.7", "@cliqz-oss/firefox-client": "0.3.1", "@cliqz-oss/node-firefox-connect": "1.2.1", - "adbkit": "2.11.0", - "addons-linter": "1.0.0", - "babel-polyfill": "6.26.0", - "babel-runtime": "6.26.0", + "adbkit": "2.11.1", + "addons-linter": "1.19.0", "bunyan": "1.8.12", - "camelcase": "4.1.0", - "debounce": "1.1.0", - "decamelize": "2.0.0", + "camelcase": "5.3.1", + "chrome-launcher": "0.12.0", + "debounce": "1.2.0", + "decamelize": "3.2.0", "es6-error": "4.1.1", - "es6-promisify": "5.0.0", "event-to-promise": "0.8.0", - "firefox-profile": "1.1.0", - "fx-runner": "1.0.9", - "git-rev-sync": "1.9.1", - "minimatch": "3.0.4", + "firefox-profile": "1.3.0", + "fx-runner": "1.0.11", + "git-rev-sync": "2.0.0", + "import-fresh": "3.2.1", "mkdirp": "0.5.1", + "multimatch": "4.0.0", "mz": "2.7.0", - "node-notifier": "5.2.1", - "opn": "5.3.0", - "parse-json": "4.0.0", - "regenerator-runtime": "0.11.1", - "require-uncached": "1.0.3", - "sign-addon": "0.3.1", - "source-map-support": "0.5.3", + "node-notifier": "6.0.0", + "open": "7.0.0", + "parse-json": "5.0.0", + "sign-addon": "2.0.4", + "source-map-support": "0.5.16", "stream-to-promise": "2.2.0", - "strip-json-comments": "2.0.1", - "tmp": "0.0.33", - "update-notifier": "2.3.0", - "watchpack": "1.5.0", - "yargs": "6.6.0", + "strip-bom": "4.0.0", + "strip-json-comments": "3.0.1", + "tmp": "0.1.0", + "update-notifier": "4.0.0", + "watchpack": "1.6.0", + "ws": "7.2.1", + "yargs": "15.0.2", "zip-dir": "1.0.2" }, "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 + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-3.2.0.tgz", + "integrity": "sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw==", + "dev": true, + "requires": { + "xregexp": "^4.2.4" + } + }, + "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 + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "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" + } + }, + "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 + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { - "xregexp": "4.0.0" + "p-limit": "^2.2.0" } }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", "dev": true, "requires": { + "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "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 + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "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": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "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": "^5.0.0" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "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 + }, + "tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "dev": true, + "requires": { + "rimraf": "^2.6.3" + } + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" } }, - "xregexp": { + "y18n": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true + }, + "yargs": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.0.2.tgz", + "integrity": "sha512-GH/X/hYt+x5hOat4LMnCqMd8r5Cv78heOMIJn1hr7QPPBqfeC6p89Y78+WB9yGDvfpCvgasfmWLzNzEioOUD9Q==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^16.1.0" + }, + "dependencies": { + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + } + } + }, + "yargs-parser": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", + "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + } + } } } }, "webext-experiment-utils": { - "version": "github:mozilla/webext-experiment-utils#23c4cd0c056695aefd10de1d74024f0211d2b758", - "from": "github:mozilla/webext-experiment-utils#23c4cd0c056695aefd10de1d74024f0211d2b758", + "version": "github:mozilla/webext-experiment-utils#31b6e71314934caf14fe541cd2c045957f1eb4ad", + "from": "github:mozilla/webext-experiment-utils#v0.2.0", "dev": true, "requires": { "ajv": "^6.5.0", @@ -10865,9 +11205,9 @@ } }, "whatwg-url": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.4.1.tgz", - "integrity": "sha512-FwygsxsXx27x6XXuExA/ox3Ktwcbf+OAvrKmLulotDAiO1Q6ixchPFaHYsis2zZBZSJTR0+dR+JVtf7MlbqZjw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", "dev": true, "requires": { "lodash.sortby": "^4.7.0", @@ -10897,66 +11237,60 @@ "dev": true }, "widest-line": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz", - "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", - "dev": true, - "requires": { - "string-width": "^2.1.1" - } - }, - "win-release": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", - "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", - "dev": true, - "requires": { - "semver": "^5.0.1" - } - }, - "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", - "dev": true - }, - "winreg": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/winreg/-/winreg-0.0.12.tgz", - "integrity": "sha1-BxBVVLoanQiXklHRKUdb/64wBrc=", - "dev": true - }, - "winston": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.4.tgz", - "integrity": "sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "dev": true, - "optional": true, "requires": { - "async": "~1.0.0", - "colors": "1.0.x", - "cycle": "1.0.x", - "eyes": "0.1.x", - "isstream": "0.1.x", - "stack-trace": "0.0.x" + "string-width": "^4.0.0" }, "dependencies": { - "async": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", - "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=", + "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 + }, + "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 + }, + "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 + }, + "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, - "optional": true + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, - "optional": true + "requires": { + "ansi-regex": "^5.0.0" + } } } }, + "winreg": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/winreg/-/winreg-0.0.12.tgz", + "integrity": "sha1-BxBVVLoanQiXklHRKUdb/64wBrc=", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -11020,20 +11354,27 @@ } }, "write-file-atomic": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", - "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.1.tgz", + "integrity": "sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } }, + "ws": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.1.tgz", + "integrity": "sha512-sucePNSafamSKoOqoNfBd8V0StlkzJKL2ZAhGQinCfNQ+oacw+Pk7lcdAElecBF2VkLNZRiIb5Oi1Q5lVUVt2A==", + "dev": true + }, "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, "xml2js": { @@ -11052,17 +11393,14 @@ "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", "dev": true }, - "xmldom": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", - "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", - "dev": true - }, "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", - "dev": true + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.2.4.tgz", + "integrity": "sha512-sO0bYdYeJAJBcJA8g7MJJX7UrOZIfJPd8U2SC7B2Dd/J24U0aQNoGp33shCaBSWeb0rD5rh6VBUIXOkGal1TZA==", + "dev": true, + "requires": { + "@babel/runtime-corejs2": "^7.2.0" + } }, "xtend": { "version": "4.0.1", @@ -11259,31 +11597,33 @@ } }, "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", "dev": true, "requires": { "camelcase": "^4.1.0" } }, "yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "dev": true, "requires": { "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.0.1" - } - }, - "zip": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/zip/-/zip-1.2.0.tgz", - "integrity": "sha1-rQrUImUwm+QutW/IYZThfCTmapw=", - "dev": true, - "requires": { - "bops": "~0.1.1" + "fd-slicer": "~1.1.0" + }, + "dependencies": { + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + } } }, "zip-dir": { diff --git a/package.json b/package.json index 783b6db..fa35426 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "shield-studies-addon-utils", - "description": "Utilities for building Shield-Study Mozilla Firefox add-ons.", - "version": "5.3.0", + "description": "Utilities for Mozilla Firefox study add-ons.", + "version": "6.0.0", "author": "Mozilla", "bin": { "copyStudyUtils": "bin/copyStudyUtils.js", @@ -21,20 +21,20 @@ "assert": "^1.4.1", "doctoc": "^1.3.1", "eslint": "4.19.1", - "eslint-plugin-json": "^1.2.0", + "eslint-plugin-json": "^1.4.0", "eslint-plugin-mozilla": "^0.13.0", "eslint-plugin-no-unsanitized": "^3.0.2", "fixpack": "^2.3.1", - "fx-runner": "^1.0.9", - "geckodriver": "^1.12.2", - "get-firefox": "^2.1.0", + "fx-runner": "^1.0.11", + "geckodriver": "^1.19.1", + "get-firefox": "^3.0.0", "mocha": "^5.2.0", "npm-run-all": "^4.1.2", "pre-commit": "^1.2.2", "prettier": "^1.11.0", "selenium-webdriver": "^3.6.0", - "web-ext": "^2.7.0", - "webext-experiment-utils": "github:mozilla/webext-experiment-utils#23c4cd0c056695aefd10de1d74024f0211d2b758", + "web-ext": "^4.0.0", + "webext-experiment-utils": "github:mozilla/webext-experiment-utils#v0.2.0", "webpack": "^2.6.1", "yamljs": "^0.3.0" }, @@ -72,7 +72,6 @@ }, "scripts": { "build": "npm run generate && cd webExtensionApis/study && webpack", - "clean": "rm -rf examples/*/{src/privileged/,dist/}", "docformat": "doctoc --title '**Contents**' docs/*.md && prettier '**/*.md' --write", "eslint": "eslint . --ext js --ext json", "eslint-fix": "npm run eslint -- --fix", @@ -93,7 +92,6 @@ "prepare": "export SKIPLINT=1 && fixpack && npm run build", "pretest": "npm run build && npm run test-addon:bundle-utils && npm run test-addon:build && npm run import-pioneer-opt-in", "pretest-addon": "npm run pretest", - "small-study": "cd examples/small-study && npm run rebuild && npm start", "test": "npm run test:func", "test-addon": "cd test-addon && web-ext run --no-reload", "test-addon:build": "cd test-addon && web-ext build", diff --git a/test-addon/src/background.js b/test-addon/src/background.js index f02c58c..dc56fe1 100644 --- a/test-addon/src/background.js +++ b/test-addon/src/background.js @@ -1,163 +1,11 @@ /* global getStudySetup */ -class StudyLifeCycleHandler { - /** - * Listen to onEndStudy, onReady - * `browser.study.setup` fires onReady OR onEndStudy - * - * call `this.enableFeature` to actually do the feature/experience/ui. - */ - constructor() { - /* - * IMPORTANT: Listen for `onEndStudy` before calling `browser.study.setup` - * because: - * - `setup` can end with 'ineligible' due to 'allowEnroll' key in first session. - * - */ - browser.study.onEndStudy.addListener(this.handleStudyEnding.bind(this)); - browser.study.onReady.addListener(this.enableFeature.bind(this)); - } - - /** - * Cleanup - * - * (If you have privileged code, you might need to clean - * that up as well. - * See: https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/lifecycle.html - * - * @returns {undefined} - */ - async cleanup() { - // do whatever work your addon needs to clean up - } - - /** - * - * side effects - * - set up expiration alarms - * - make feature/experience/ui with the particular variation for this user. - * - * @param {object} studyInfo browser.study.studyInfo object - * - * @returns {undefined} - */ - async enableFeature(studyInfo) { - await browser.study.logger.log(["Enabling experiment", studyInfo]); - const { delayInMinutes } = studyInfo; - if (delayInMinutes !== undefined) { - const alarmName = `${browser.runtime.id}:studyExpiration`; - const alarmListener = async alarm => { - if (alarm.name === alarmName) { - browser.alarms.onAlarm.removeListener(alarmListener); - await browser.study.endStudy("expired"); - } - }; - browser.alarms.onAlarm.addListener(alarmListener); - browser.alarms.create(alarmName, { - delayInMinutes, - }); - } - feature.configure(studyInfo); - } - - /** handles `study:end` signals - * - * - opens 'ending' urls (surveys, for example) - * - calls cleanup - * - * @param {object} ending An ending result - * - * @returns {undefined} - */ - async handleStudyEnding(ending) { - await browser.study.logger.log([`Study wants to end:`, ending]); - for (const url of ending.urls) { - await browser.tabs.create({ url }); - } - switch (ending.endingName) { - // could have different actions depending on positive / ending names - default: - await browser.study.logger.log(`The ending: ${ending.endingName}`); - await this.cleanup(); - break; - } - // actually remove the addon. - await browser.study.logger.log("About to actually uninstall"); - return browser.management.uninstallSelf(); - } -} - -/* An example feature singleton, demonstrating Telemetry and some endings */ -class ButtonFeature { - constructor() {} - - async configure(studyInfo) { - let clicksInSession = 0; - browser.browserAction.setBadgeText({ text: "" + clicksInSession }); - - browser.browserAction.onClicked.addListener(() => { - clicksInSession++; - browser.browserAction.setBadgeText({ text: "" + clicksInSession }); - - // see the telemetry appear in `about:Telemetry`, as string:string - browser.study.sendTelemetry({ clicksInSession: "" + clicksInSession }); - if (clicksInSession >= 3) { - browser.study.endStudy("user-used-the-feature"); - } - }); - await browser.study.logger.log([ - `Setting the browser action title to the variation name: '${ - studyInfo.variation.name - }'`, - ]); - await browser.browserAction.setTitle({ title: studyInfo.variation.name }); - await browser.study.logger.log( - "Feature is now enabled, sending 'test:onFeatureEnabled' event (for the tests)", - ); - const internals = await browser.studyDebug.getInternals(); - const updatedStudyInfo = await browser.study.getStudyInfo(); - const informationForTests = { - message: "test:onFeatureEnabled", - internals, - studyInfo, - updatedStudyInfo, - }; - browser.runtime.sendMessage(informationForTests).catch(console.error); - } -} - -// construct. will be configured after setup. -const feature = new ButtonFeature(); - -/** - * Run every startup to get config and instantiate the feature - * - * @returns {undefined} - */ async function onEveryExtensionLoad() { - new StudyLifeCycleHandler(); - - const studySetup = await getStudySetup(); - await browser.study.logger.log(["Study setup: ", studySetup]); - await browser.study.setup(studySetup); + console.log("The 'onEveryExtensionLoad' method has run."); + // Usually we fire study-specific code here, but this test-add-on is a noop } -// Since this is a test-addon, we don't initiate any code directly, but wait -// for events sent by tests. This allows us to control and test the execution -// properly. -// Note: Since this is the first onMessage listener, it will be able to send -// a response to the sending party -// onEveryExtensionLoad(); -const onEveryExtensionLoadTestListener = request => { - console.log("onEveryExtensionLoad listener - request", request); - if (request === "test:onEveryExtensionLoad") { - console.log("Removing onEveryExtensionLoadTestListener"); - browser.runtime.onMessage.removeListener(onEveryExtensionLoadTestListener); - console.log("Running onEveryExtensionLoad()"); - onEveryExtensionLoad(); - } -}; -browser.runtime.onMessage.addListener(onEveryExtensionLoadTestListener); +onEveryExtensionLoad(); // The tests that probe the web extensions APIs directly rely on an extension // page opening up in a new window/tab. @@ -170,8 +18,6 @@ const createData = { }; browser.windows.create(createData); -// Testing that the web extension events works properly with our bundled APIs requires the below code - /** * Fired when the extension is first installed, when the extension is updated * to a new version, and when the browser is updated to a new version. @@ -198,8 +44,5 @@ async function handleStartup() { console.log("The 'handleStartup' event was fired.", arguments); } -// todo: on shutdown -// Run shutdown-related non-privileged code - browser.runtime.onStartup.addListener(handleStartup); browser.runtime.onInstalled.addListener(handleInstalled); diff --git a/test-addon/src/extension-page-for-tests/index.html b/test-addon/src/extension-page-for-tests/index.html index 5eb66f8..eade6cf 100644 --- a/test-addon/src/extension-page-for-tests/index.html +++ b/test-addon/src/extension-page-for-tests/index.html @@ -16,15 +16,7 @@

Shield Study Utils Test Add-on

This is an extension page for shield-studies-addon-utils/test-addon

-

This add-on initiates no background logic on it's own, so that the tests - can test the state of the add-on before "onEveryExtensionLoad()".

+

Used by tests to be able to access the background page context using Selenium.

-

For manual testing, use the button below to run the code.

- -

- -

- - diff --git a/test-addon/src/extension-page-for-tests/page.js b/test-addon/src/extension-page-for-tests/page.js deleted file mode 100644 index a9469a7..0000000 --- a/test-addon/src/extension-page-for-tests/page.js +++ /dev/null @@ -1,7 +0,0 @@ -document.addEventListener("click", async e => { - if (e.target.id === "onEveryExtensionLoad-button") { - browser.runtime - .sendMessage("test:onEveryExtensionLoad") - .catch(console.error); - } -}); diff --git a/test-addon/src/icons/LICENSE b/test-addon/src/icons/LICENSE deleted file mode 100644 index fcd8e26..0000000 --- a/test-addon/src/icons/LICENSE +++ /dev/null @@ -1 +0,0 @@ -All icons are public domain and came from https://openclipart.org/. diff --git a/test-addon/src/icons/shield-icon.svg b/test-addon/src/icons/shield-icon.svg deleted file mode 100644 index 3ad3e5f..0000000 --- a/test-addon/src/icons/shield-icon.svg +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - Openclipart - - - Shield Icon - 2010-09-19T03:15:30 - Here is an icon depicting a shield bearing a star. Use it to depict security, strength etc. Easily modifiable to incorporate a different emblem such as a sword. Enjoy! - https://openclipart.org/detail/85567/shield-icon-by-marricklip14 - - - marricklip14 - - - - - Emblem - Icon Star - Security - Shield - Strength - - - - - - - - - - - diff --git a/test-addon/src/manifest.json b/test-addon/src/manifest.json index f7ac69d..801f625 100644 --- a/test-addon/src/manifest.json +++ b/test-addon/src/manifest.json @@ -21,14 +21,6 @@ }, "permissions": ["storage", "alarms"], "background": { - "scripts": ["studySetup.js", "background.js"] - }, - "icons": { - "48": "icons/shield-icon.svg" - }, - "browser_action": { - "browser_style": true, - "default_icon": "icons/shield-icon.svg", - "default_title": "Test" + "scripts": ["background.js"] } } diff --git a/test-addon/src/studySetup.js b/test-addon/src/studySetup.js deleted file mode 100644 index 3a6ba9b..0000000 --- a/test-addon/src/studySetup.js +++ /dev/null @@ -1,155 +0,0 @@ -/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "getStudySetup" }]*/ - -/** - * Overview: - * - * - constructs a well-formatted `studySetup` for use by `browser.study.setup` - * - mostly declarative, except that some fields are set at runtime - * asynchronously. - * - * Advanced features: - * - testing overrides from preferences - * - expiration time - * - some user defined endings. - * - study defined 'shouldAllowEnroll' logic. - */ - -/** Base for studySetup, as used by `browser.study.setup`. - * - * Will be augmented by 'getStudySetup' - */ -const baseStudySetup = { - // used for activeExperiments tagging (telemetryEnvironment.setActiveExperiment) - activeExperimentName: browser.runtime.id, - - // use either "shield" or "pioneer" telemetry semantics and data pipelines - studyType: null, // set by internal test override below in getStudySetup() - - // telemetry - telemetry: { - // Actually submit the pings to Telemetry. [default if omitted: false] - send: true, - // Marks pings with testing=true. Set flag to `true` for pings are meant to be seen by analysts [default if omitted: false] - removeTestingFlag: false, - // Keep an internal telemetry archive. Useful for verifying payloads of Pioneer studies without risking actually sending any unencrypted payloads [default if omitted: false] - internalTelemetryArchive: true, - }, - - // endings with urls - endings: { - /** standard endings */ - "user-disable": { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=user-disable", - ], - }, - ineligible: { - baseUrls: [], - }, - expired: { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=expired", - ], - }, - - /** Study specific endings */ - "user-used-the-feature": { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=user-used-the-feature", - ], - category: "ended-positive", - }, - "hated-the-feature": { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=hated-the-feature", - ], - category: "ended-negative", - }, - }, - - // Study branches and sample weights, overweighing feature branches - weightedVariations: [ - { - name: "feature-active", - weight: 1.5, - }, - { - name: "feature-passive", - weight: 1.5, - }, - { - name: "control", - weight: 1, - }, - ], - - // maximum time that the study should run, from the first run - expire: { - days: 14, - }, -}; - -/** - * Determine, based on common and study-specific criteria, if enroll (first run) - * should proceed. - * - * False values imply that *during first run only*, we should endStudy(`ineligible`) - * - * Add your own enrollment criteria as you see fit. - * - * (Guards against Normandy or other deployment mistakes or inadequacies). - * - * This implementation caches in local storage to speed up second run. - * - * @param {object} studySetup A complete study setup object - * @returns {Promise} answer An boolean answer about whether the user should be - * allowed to enroll in the study - */ -async function cachingFirstRunShouldAllowEnroll(studySetup) { - // Cached answer. Used on 2nd run - let allowed = await browser.storage.local.get("allowedEnrollOnFirstRun"); - if (allowed.allowedEnrollOnFirstRun === true) return true; - - /* - First run, we must calculate the answer. - If false, the study will endStudy with 'ineligible' during `setup` - */ - - // could have other reasons to be eligible, such add-ons, prefs - const dataPermissions = await browser.study.getDataPermissions(); - if (studySetup.studyType === "shield") { - allowed = dataPermissions.shield; - } - if (studySetup.studyType === "pioneer") { - allowed = dataPermissions.pioneer; - } - - // cache the answer - await browser.storage.local.set({ allowedEnrollOnFirstRun: allowed }); - return allowed; -} - -/** - * Augment declarative studySetup with any necessary async values - * - * @return {object} studySetup A complete study setup object - */ -async function getStudySetup() { - // shallow copy - const studySetup = Object.assign({}, baseStudySetup); - - // internal testing override necessary to be able to test all study types - const internalTestingOverrides = await browser.studyDebug.getInternalTestingOverrides(); - studySetup.studyType = internalTestingOverrides.studyType; - - studySetup.allowEnroll = await cachingFirstRunShouldAllowEnroll(studySetup); - - const testingOverrides = await browser.study.getTestingOverrides(); - studySetup.testing = { - variationName: testingOverrides.variationName, - firstRunTimestamp: testingOverrides.firstRunTimestamp, - expired: testingOverrides.expired, - }; - - return studySetup; -} diff --git a/test-addon/web-ext-config.js b/test-addon/web-ext-config.js index fbce17b..56f1396 100644 --- a/test-addon/web-ext-config.js +++ b/test-addon/web-ext-config.js @@ -12,7 +12,7 @@ const defaultConfig = { run: { firefox: process.env.FIREFOX_BINARY || "nightly", browserConsole: true, - startUrl: ["about:debugging"], + startUrl: ["about:debugging#/runtime/this-firefox"], pref: ["shieldStudy.logLevel=All"], }, }; diff --git a/test/functional/browser.study.api.js b/test/functional/browser.study.api.js index 4442068..e210e33 100644 --- a/test/functional/browser.study.api.js +++ b/test/functional/browser.study.api.js @@ -2,44 +2,11 @@ /* global browser */ const KEEPOPEN = process.env.KEEPOPEN; -/** Complete list of tests for testing - * - * - the public api for `browser.study` not specific to any add-on background logic - */ - -/** About webdriver extension based tests - * - * `addonExec`: Created in the one-time "before" function for each suite. - * - * Webdriver - * - `driver` created: uses the fx profile, sets up connenction - * and translation to Marionette - * - installs the `test-addon` extension - * - waits for UI as a signal that the extension page is ready. - * - now can `await addonExec`, as short-named bound version of - * "executeAsyncScriptInExtensionPageForTests", - * which runs in the exentension page contenxt and promises values we - * can use in tests in this file (node / mocha context). - * - * ## Creating a new test - * - * 1. Goal, call back from the webExtension with the data you need to test - * 2. Do the test in the script using node's `assert` - * - * ## Tips for `addonExec` - * - * 1. If something breaks / test fails, fx will stay open (`--bail`). - * Look in the BrowserConsole - * 2. Callback with a complex object if you need a lot of return values - * 3. Recall that `studyDebug` exists for doing resets, getting internals, etc - */ - -// TODO create new profile per test? const assert = require("assert"); const utils = require("./utils"); -const MINUTES_PER_DAY = 60 * 24; +// const MINUTES_PER_DAY = 60 * 24; // node's util, for printing a deeply nested object to node console const { inspect } = require("util"); @@ -52,61 +19,11 @@ function full(myObject) { // eslint-disable-next-line no-unused-vars const delay = ms => new Promise(res => setTimeout(res, ms)); -// simple merge all by top level keys, right-most wins -function merge(...sources) { - return Object.assign({}, ...sources); -} - -function publicApiTests(studyType) { - /** return a studySetup, shallow merged from overrides - * - * @return {object} mergedStudySetup - */ - function studySetupForTests(...overrides) { - // Minimal configuration to pass schema validation - const studySetup = { - activeExperimentName: `shield-utils-test-addon@${studyType}.mozilla.org`, - studyType, - endings: { - ineligible: { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=ineligible", - ], - }, - BrowserStudyApiEnding: { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=BrowserStudyApiEnding", - ], - }, - }, - telemetry: { - send: false, - removeTestingFlag: false, - internalTelemetryArchive: true, - }, - logLevel: 10, - weightedVariations: [ - { - name: "control", - weight: 1, - }, - ], - expire: { - days: 14, - }, - // Dynamic study configuration flags - allowEnroll: true, - testing: {}, - }; - - return merge(studySetup, ...overrides); - } - +function publicApiTests(telemetryPipeline) { // This gives Firefox time to start, and us a bit longer during some of the tests. this.timeout(30000 + KEEPOPEN * 1000 * 2); let driver; - let beginTime; let addonId; // run in the extension page @@ -116,6 +33,16 @@ function publicApiTests(studyType) { driver = await utils.setupWebdriver.promiseSetupDriver( utils.FIREFOX_PREFERENCES, ); + + // Ensure that shield optout studies are enabled during testing + await utils.preferences.set( + driver, + `app.shield.optoutstudies.enabled`, + true, + ); + + // TODO: Possibly configure Normandy here - replaces study utils setup phase + await installAddon(); await utils.ui.openBrowserConsole(driver); @@ -127,12 +54,12 @@ function publicApiTests(studyType) { } async function installAddon() { - beginTime = Date.now(); + // beginTime = Date.now(); if (addonId) { await utils.setupWebdriver.uninstallAddon(driver, addonId); addonId = null; } - if (studyType === "pioneer") { + if (telemetryPipeline === "pioneer") { await utils.setupWebdriver.installPioneerOptInAddon(driver); } addonId = await utils.setupWebdriver.installAddon(driver); @@ -149,19 +76,6 @@ function publicApiTests(studyType) { driver.quit(); }); - /* Reset a study */ - async function resetStudy() { - // console.debug("resetting"); - const reset = await addonExec(async function(cb) { - await browser.studyDebug.reset(); - const internals = await browser.studyDebug.getInternals(); - return cb(internals); - }); - assert(reset.isSetup === false); - // console.debug("reset done"); - return reset; - } - describe("testing infrastructure works", function() { it("should be able to access window.browser from the extension page for tests", async () => { const hasAccessToWebExtensionApi = await addonExec(async callback => { @@ -245,26 +159,26 @@ function publicApiTests(studyType) { } }, ); - assert( - caughtError === "Error: An async exception thrown for test purposes", + assert.equal( + caughtError, + "Error: An async exception thrown for test purposes", ); }); }); describe("getDataPermissions", function() { it("returns correct and current list of permissions", async () => { - const thisSetup = studySetupForTests(); - const dataPermissions = await addonExec(async (setup, cb) => { + const dataPermissions = await addonExec(async cb => { // this is what runs in the webExtension scope. const $dataPermissions = await browser.study.getDataPermissions(); // call back with all the data we care about to Mocha / node cb($dataPermissions); - }, thisSetup); - // console.debug(full(dataPermissions)); + }); + console.debug({ dataPermissions }); // tests - assert(dataPermissions.shield, "shield should be enabled"); - if (studyType === "pioneer") { + assert(dataPermissions.shield, "shield optoutstudies should be enabled"); + if (telemetryPipeline === "pioneer") { assert( dataPermissions.pioneer, "user should have opted in for pioneer", @@ -278,402 +192,38 @@ function publicApiTests(studyType) { }); }); - describe("test the setup requirement", function() { - it("should not be able to send telemetry before setup", async () => { - const caughtError = await utils.executeJs.executeAsyncScriptInExtensionPageForTests( - driver, - async callback => { - let _caughtError = null; - try { - await browser.study.sendTelemetry({ foo: "bar" }); - callback(false); - } catch (e) { - // console.debug("Caught error", e); - _caughtError = e.toString(); - callback(_caughtError); - } - callback(_caughtError); - }, - ); - assert( - caughtError === - "Error: telemetry: this method can't be used until `setup` is called", - ); - }); - - it("most functions throw if not studyUtils is not setup", async function() { - await resetStudy(); - const caughtErrors = await addonExec(async callback => { - const _caughtErrors = []; - try { - await browser.study.endStudy("ineligible"); - } catch (e) { - _caughtErrors.push(e.toString()); - } - - try { - await browser.study.sendTelemetry({ a: "b" }); - } catch (e) { - _caughtErrors.push(e.toString()); - } - - try { - await browser.study.getStudyInfo(); - } catch (e) { - _caughtErrors.push(e.toString()); - } - - try { - await browser.study.fullSurveyUrl( - "https://foo.com/survey-foo/", - "mid-study-survey", - ); - } catch (e) { - _caughtErrors.push(e.toString()); - } - - callback(_caughtErrors); - }); - const expected = [ - "Error: endStudy: this method can't be used until `setup` is called", - "Error: telemetry: this method can't be used until `setup` is called", - "Error: info: this method can't be used until `setup` is called", - "Error: endingQueryArgs: this method can't be used until `setup` is called", - ]; - assert.deepStrictEqual(caughtErrors, expected); - }); - }); - - describe("internals,studyInfo under several browser.setup() scenarios", function() { - beforeEach(resetStudy); - // afterEach(); - - it("1. firstRun, expire.days, allowEnroll, !testing.expired should: isFirstRun, should: pings enter,install", async function() { - // console.debug("doing test 1"); - const thisSetup = studySetupForTests(); - const data = await addonExec(async (setup, cb) => { - // this is what runs in the webExtension scope. - const info = await browser.study.setup(setup); - const internals = await browser.studyDebug.getInternals(); - // call back with all the data we care about to Mocha / node - cb({ info, internals }); - }, thisSetup); - // console.debug(full(data)); - const { info, internals } = data; - - // tests - const now = Number(Date.now()); - const seenTelemetryStates = internals.seenTelemetry - .filter(ping => ping.payload.type === "shield-study") - .map(ping => ping.payload.data.study_state); - assert(internals.isSetup, "should be isSetup"); - assert(!internals.isEnded, "should not be ended"); - assert(!internals.isEnding, "should not be ending"); - assert(info.isFirstRun, "should be isFirstRun"); - assert(info.variation, "should be a variation"); - assert.strictEqual(info.variation.name, "control", "should be 'control'"); - - assert.notStrictEqual( - info.firstRunTimestamp, - null, - "firstRunTimestamp should not be null since the study should be running", - ); - assert(now - info.firstRunTimestamp < 5000, "less than 5 seconds old"); - assert( - info.delayInMinutes > 13 * MINUTES_PER_DAY, - "should not expire within 13 days", - ); - assert( - info.delayInMinutes < 15 * MINUTES_PER_DAY, - "should expire within 15 days", - ); - assert.deepStrictEqual( - seenTelemetryStates, - ["enter", "installed"], - "should have seen correct study state telemetry", - ); - }); - - it("2. secondRun, expire.days, allowEnroll, !testing.expired should be !firstRun, should NOT have enter or install pings", async function() { - // console.debug("doing test 2"); - const now = Number(Date.now()); - const thisSetup = studySetupForTests({}); - const data = await addonExec( - async (setup, nowTs, cb) => { - // this is what runs in the webExtension scope. - await browser.studyDebug.setFirstRunTimestamp(nowTs); - const info = await browser.study.setup(setup); - const internals = await browser.studyDebug.getInternals(); - // call back with all the data we care about to Mocha / node - cb({ info, internals }); - }, - thisSetup, - now, - ); - // console.debug(full(data)); - const { info, internals } = data; - - // tests - const seenTelemetryStates = internals.seenTelemetry - .filter(ping => ping.payload.type === "shield-study") - .map(ping => ping.payload.data.study_state); - - assert(internals.isSetup, "should be isSetup"); - assert(!internals.isEnded, "should not be ended"); - assert(!internals.isEnding, "should not be ending"); - assert(!info.isFirstRun, "should NOT be isFirstRun"); - assert(info.variation, "should be a variation"); - assert.strictEqual(info.variation.name, "control", "should be 'control'"); - - assert.notStrictEqual( - info.firstRunTimestamp, - null, - "firstRunTimestamp should not be null since the study should be running", - ); - assert.strictEqual( - info.firstRunTimestamp, - now, - "firstRunTimestamp should be what we set", - ); - assert(now - info.firstRunTimestamp < 5000, "less than 5 seconds old"); - assert( - info.delayInMinutes > 13 * MINUTES_PER_DAY, - "should not expire within 13 days", - ); - assert( - info.delayInMinutes < 15 * MINUTES_PER_DAY, - "should expire within 15 days", - ); - assert.deepStrictEqual( - seenTelemetryStates, - [], - "should have seen any study state telemetry", - ); - }); - - it("3. firstRun, expire.days, !allowEnroll, !testing.expired should end ineligible, pings enter,ineligible,exit", async function() { - // console.debug("doing test 3"); - const thisSetup = studySetupForTests({ - allowEnroll: false, - }); - const data = await addonExec(async (setup, cb) => { - // this is what runs in the webExtension scope. - const info = await browser.study.setup(setup); - const internals = await browser.studyDebug.getInternals(); - // call back with all the data we care about to Mocha / node - cb({ info, internals }); - }, thisSetup); - // console.debug(full(data)); - const { info, internals } = data; - - // tests - const seenTelemetryStates = internals.seenTelemetry - .filter(ping => ping.payload.type === "shield-study") - .map(ping => ping.payload.data.study_state); - - assert(internals.isSetup, "should be isSetup"); - assert(internals.isEnded, "should be ended"); - assert(internals.isEnding, "should be ending"); - assert(info.isFirstRun, "should be isFirstRun"); - assert(info.variation, "should be a variation"); - assert.strictEqual(info.variation.name, "control", "should be 'control'"); - - assert.strictEqual( - info.firstRunTimestamp, - null, - "firstRunTimestamp should be null (the study was never run)", - ); - assert.strictEqual( - info.delayInMinutes, - null, - "delayInMinutes should be null (the study was never run)", - ); - assert.deepStrictEqual( - seenTelemetryStates, - ["enter", "ineligible", "exit"], - "should have seen correct study state telemetry", - ); - }); - - it("4. testing.variationName chooses that branch", async function() { - // console.debug("doing test 4"); - const thisSetup = studySetupForTests({ - testing: { - variationName: "the-rare-one", - }, - weightedVariations: [ - { - name: "the-rare-one", - weight: 1, - }, - { - name: "common", - weight: 1000000, - }, - ], - }); - const data = await addonExec(async (setup, cb) => { - // this is what runs in the webExtension scope. - const info = await browser.study.setup(setup); - const internals = await browser.studyDebug.getInternals(); - // call back with all the data we care about to Mocha / node - cb({ info, internals }); - }, thisSetup); - // console.debug(full(data)); - const { info } = data; - assert.strictEqual( - info.variation.name, - "the-rare-one", - "should be 'the-rare-one'", - ); - }); - - it("5. testing.variationName: if variation name isn't in weightedVariations, throw setup error", async function() { - // console.debug("doing test 5"); - const thisSetup = studySetupForTests({ - testing: { - variationName: "not-there", - }, - }); - const error = await addonExec(async (setup, cb) => { - // this is what runs in the webExtension scope. - try { - await browser.study.setup(setup); - } catch (e) { - cb(e.toString()); - } - cb("This should be an error"); - }, thisSetup); - // console.debug(full(error)); - assert.strictEqual( - error, - 'Error: setup error: testing.variationName "not-there" not in [{"name":"control","weight":1}]', - "should be an exception", - ); - }); - - it("6a. testing.firstRunTimestamp override can be set to an integer", async function() { - // console.debug("doing test 6"); - const thisSetup = studySetupForTests({ - testing: { - firstRunTimestamp: 123, - }, - }); - const data = await addonExec(async (setup, cb) => { - // this is what runs in the webExtension scope. - const info = await browser.study.setup(setup); - const internals = await browser.studyDebug.getInternals(); - // call back with all the data we care about to Mocha / node - cb({ info, internals }); - }, thisSetup); - // console.debug(full(data)); - const { info } = data; - assert.strictEqual( - info.firstRunTimestamp, - 123, - "should be the same as our override", - ); - }); - - it("6b. testing.firstRunTimestamp override can be set to 0", async function() { - // console.debug("doing test 6"); - const thisSetup = studySetupForTests({ - testing: { - firstRunTimestamp: 0, - }, - }); - const data = await addonExec(async (setup, cb) => { - // this is what runs in the webExtension scope. - const info = await browser.study.setup(setup); - const internals = await browser.studyDebug.getInternals(); - // call back with all the data we care about to Mocha / node - cb({ info, internals }); - }, thisSetup); - // console.debug(full(data)); - const { info } = data; - assert.strictEqual( - info.firstRunTimestamp, - 0, - "should be the same as our override", - ); - }); - - it("7. testing.expired override works as expected", async function() { - // console.debug("doing test 7"); - const thisSetup = studySetupForTests({ - testing: { - expired: true, - }, - }); - const data = await addonExec(async (setup, cb) => { - // this is what runs in the webExtension scope. - const info = await browser.study.setup(setup); - const internals = await browser.studyDebug.getInternals(); - // call back with all the data we care about to Mocha / node - cb({ info, internals }); - }, thisSetup); - // console.debug(full(data)); - const { info } = data; - assert.strictEqual(info.delayInMinutes, 0, "should be zero"); - }); - }); - - describe("life-cycle tests", function() { - describe("setup, sendTelemetry, manually invoked endStudy", function() { - let studyInfo, calculatedPingSize; - const overrides = { - activeExperimentName: "test:browser.study.api", - telemetry: { - send: true, - removeTestingFlag: false, - internalTelemetryArchive: true, - }, - endings: { - customEnding: { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=customEnding", - ], - category: "ended-positive", - }, - }, - }; + describe("telemetry tests", function() { + describe("sendTelemetry, calculateTelemetryPingSize", function() { + let calculatedPingSize; before(async function reinstallSetupDoTelemetryAndWait() { await installAddon(); - const _ = await addonExec(async (_studySetupForTests, callback) => { - // Ensure we have a configured study and are supposed to run our feature - browser.study.onReady.addListener(async _studyInfo => { - const samplePing = { foo: "bar" }; - await browser.study.sendTelemetry(samplePing); - const _calculatedPingSize = await browser.study.calculateTelemetryPingSize( - samplePing, - ); - callback({ - studyInfo: _studyInfo, - calculatedPingSize: _calculatedPingSize, - }); + const _ = await addonExec(async (_telemetryPipeline, callback) => { + await browser.studyDebug.resetSeenTelemetry(); + await browser.studyDebug.recordSeenTelemetry(); + const samplePing = { foo: "bar" }; + await browser.study.sendTelemetry(samplePing, _telemetryPipeline); + const _calculatedPingSize = await browser.study.calculateTelemetryPingSize( + samplePing, + _telemetryPipeline, + ); + callback({ + calculatedPingSize: _calculatedPingSize, }); - await browser.study.setup(_studySetupForTests); - }, studySetupForTests(overrides)); - studyInfo = _.studyInfo; + }, telemetryPipeline); calculatedPingSize = _.calculatedPingSize; await delay(1000); // wait a second to telemetry to settle on disk. }); - it("should fire the onReady event upon successful setup", async () => { - // console.debug(studyInfo); - assert.strictEqual( - studyInfo.activeExperimentName, - overrides.activeExperimentName, - ); - }); - it("calculated ping size is as expected", async () => { const expectedPingSizes = { shield: 20, - pioneer: 662, + pioneer: 682, }; - assert.strictEqual(calculatedPingSize, expectedPingSizes[studyType]); + assert.strictEqual( + calculatedPingSize, + expectedPingSizes[telemetryPipeline], + ); }); describe("telemetry archive / controller effects", function() { @@ -688,37 +238,34 @@ function publicApiTests(studyType) { "pioneer-study", ], }); - const internals = await browser.studyDebug.getInternals(); + const seenTelemetry = await browser.studyDebug.getSeenTelemetry(); callback({ sent: _studyPings, - seen: internals.seenTelemetry.reverse(), + seen: seenTelemetry.reverse(), }); // Using reverse() to mimic the default sorting of telemetry archive results }); // For debugging tests - // console.debug("Pings report: ", utils.telemetry.pingsReport(studyPings.seen)); - // console.debug("Pings with id and payload: ", utils.telemetry.pingsDebug(studyPings.seen)); - }); - - it("should have set the experiment to active in Telemetry", async () => { - const activeExperiments = await utils.telemetry.getActiveExperiments( - driver, + console.debug( + "Pings report: ", + utils.telemetry.pingsReport(studyPings.seen), ); - // console.debug(activeExperiments); - assert( - activeExperiments.hasOwnProperty(studyInfo.activeExperimentName), + console.debug( + "Pings with id and payload: ", + utils.telemetry.pingsDebug(studyPings.seen), ); }); - it("should have sent at least one shield telemetry ping", async () => { - assert( - studyPings.sent.length > 0, - "at least one shield telemetry ping", - ); + it("should have seen at least one telemetry ping", async () => { + assert(studyPings.seen.length > 0, "at least one telemetry ping"); + }); + + it("should have sent at least one telemetry ping", async () => { + assert(studyPings.sent.length > 0, "at least one telemetry ping"); }); it("should have sent expected telemetry", async () => { const observed = utils.telemetry.summarizePings( - studyType === "shield" ? studyPings.sent : studyPings.seen, + telemetryPipeline === "shield" ? studyPings.sent : studyPings.seen, ); const expected = [ [ @@ -729,604 +276,14 @@ function publicApiTests(studyType) { }, }, ], - [ - "shield-study", - { - study_state: "installed", - }, - ], - [ - "shield-study", - { - study_state: "enter", - }, - ], ]; assert.deepStrictEqual( observed, expected, - "telemetry pings as as expected", + "telemetry pings as expected", ); }); }); - - describe("browser.study.endStudy() side effects for first time called", function() { - let endingResult, endingInternals; - before(async () => { - const _ = await addonExec(async callback => { - browser.study.onEndStudy.addListener(async _endingResult => { - const internals = await browser.studyDebug.getInternals(); - callback({ - endingResult: _endingResult, - endingInternals: internals, - }); - }); - await browser.study.endStudy("customEnding"); - }); - endingResult = _.endingResult; - endingInternals = _.endingInternals; - // let telemetry and disk/files sync up - await delay(1000); - }); - it("should have fired onEndStudy event with the endingResult", function() { - // console.debug(full(endingResult)); - assert(endingResult); - assert.strictEqual(endingResult.endingName, "customEnding"); - assert.strictEqual(endingResult.queryArgs.fullreason, "customEnding"); - assert(endingResult.shouldUninstall); - assert.strictEqual(endingResult.urls.length, 1); - }); - - it("should have set the experiment as inactive", async () => { - const activeExperiments = await utils.telemetry.getActiveExperiments( - driver, - ); - assert( - !activeExperiments.hasOwnProperty(studyInfo.activeExperimentName), - ); - }); - - it("should throw when calling endStudy multiple times", async function() { - const caughtErrors = await addonExec(async callback => { - const _caughtErrors = []; - const reasons = ["ineligible", "expired", "user-disable"]; - for (const r of reasons) { - try { - await browser.study.endStudy(r); - } catch (e) { - // console.debug("Caught error", e); - _caughtErrors.push(e.toString()); - } - } - callback(_caughtErrors); - }); - const expected = [ - "Error: endStudy, requested: ineligible, but already ending customEnding", - "Error: endStudy, requested: expired, but already ending customEnding", - "Error: endStudy, requested: user-disable, but already ending customEnding", - ]; - assert.deepStrictEqual(caughtErrors, expected); - }); - - describe("should have sent the expected exit telemetry", function() { - let studyPings; - - before(async () => { - studyPings = {}; - studyPings.seen = endingInternals.seenTelemetry.reverse(); - studyPings.sent = await utils.telemetry.searchSentTelemetry( - driver, - { - type: [ - "shield-study", - "shield-study-addon", - "shield-study-error", - "pioneer-study", - ], - timestamp: beginTime, - }, - ); - // For debugging tests - // console.debug("Final pings report: ", utils.telemetry.pingsReport(studyPings.seen)); - // console.debug("Final pings with id and payload: ", utils.telemetry.pingsDebug(studyPings.seen)); - }); - - it("should have sent at least one shield telemetry ping", async () => { - assert( - studyPings.sent.length > 0, - "at least one shield telemetry ping", - ); - }); - - it("should have sent expected telemetry", async () => { - const observed = utils.telemetry.summarizePings( - studyType === "shield" ? studyPings.sent : studyPings.seen, - ); - const expected = [ - [ - "shield-study", - { - study_state: "exit", - }, - ], - [ - "shield-study", - { - study_state: "ended-positive", - study_state_fullname: "customEnding", - }, - ], - [ - "shield-study-addon", - { - attributes: { - foo: "bar", - }, - }, - ], - [ - "shield-study", - { - study_state: "installed", - }, - ], - [ - "shield-study", - { - study_state: "enter", - }, - ], - ]; - assert.deepStrictEqual( - observed, - expected, - "telemetry pings as as expected", - ); - }); - }); - }); - }); - - describe("setup of an ineligible study should result in endStudy('ineligible') without even emitting onReady", function() { - let endingResult, endingInternals; - const overrides = { - activeExperimentName: "test:browser.study.api", - telemetry: { - send: true, - removeTestingFlag: false, - internalTelemetryArchive: true, - }, - endings: { - ineligible: { - baseUrls: [], - }, - }, - allowEnroll: false, - testing: {}, - }; - - before(async function reinstallSetupAndAwaitEndStudy() { - await installAddon(); - const _ = await addonExec(async (_studySetupForTests, callback) => { - // Ensure we have a configured study and are supposed to run our feature - browser.study.onEndStudy.addListener(async _endingResult => { - console.log( - "In resetSetupAndAwaitEndStudy - onEndStudy listener", - _endingResult, - ); - const internals = await browser.studyDebug.getInternals(); - callback({ - endingResult: _endingResult, - endingInternals: internals, - }); - }); - browser.study.onReady.addListener(async _studyInfo => { - console.log( - "In resetSetupAndAwaitEndStudy - onReady listener", - _studyInfo, - ); - throw new Error("onReady should not have been emitted", _studyInfo); - }); - await browser.study.setup(_studySetupForTests); - }, studySetupForTests(overrides)); - endingResult = _.endingResult; - endingInternals = _.endingInternals; - }); - - describe("browser.study.endStudy() side effects", function() { - it("should have fired onEndStudy event with the endingResult", function() { - // console.debug(full(endingResult)); - assert(endingResult); - assert.strictEqual(endingResult.endingName, "ineligible"); - assert.strictEqual(endingResult.queryArgs.fullreason, "ineligible"); - assert(endingResult.shouldUninstall); - assert.strictEqual( - endingResult.urls.length, - 0, - "the ending should have the expected number of urls configured", - ); - }); - - it("should have set the experiment as inactive", async () => { - const activeExperiments = await utils.telemetry.getActiveExperiments( - driver, - ); - assert( - !activeExperiments.hasOwnProperty(overrides.activeExperimentName), - ); - }); - - describe("should have sent the expected exit telemetry", function() { - let studyPings; - - before(async () => { - studyPings = {}; - studyPings.seen = endingInternals.seenTelemetry.reverse(); - studyPings.sent = await utils.telemetry.searchSentTelemetry( - driver, - { - type: [ - "shield-study", - "shield-study-addon", - "shield-study-error", - "pioneer-study", - ], - timestamp: beginTime, - }, - ); - // For debugging tests - // console.debug("Final pings report: ", utils.telemetry.pingsReport(studyPings.seen)); - // console.debug("Final pings with id and payload: ", utils.telemetry.pingsDebug(studyPings.seen)); - }); - - it("should have sent at least one shield telemetry ping", async () => { - assert( - studyPings.sent.length > 0, - "at least one shield telemetry ping", - ); - }); - - it("should have sent expected telemetry", async () => { - const observed = utils.telemetry.summarizePings( - studyType === "shield" ? studyPings.sent : studyPings.seen, - ); - const expected = [ - [ - "shield-study", - { - study_state: "exit", - }, - ], - [ - "shield-study", - { - study_state: "ineligible", - study_state_fullname: "ineligible", - }, - ], - [ - "shield-study", - { - study_state: "enter", - }, - ], - ]; - assert.deepStrictEqual( - observed, - expected, - "telemetry pings as as expected", - ); - }); - }); - }); - }); - - describe("setup of an already expired study should result in endStudy('expired') without even emitting onReady", function() { - let endingResult, endingInternals; - const overrides = { - activeExperimentName: "test:browser.study.api", - telemetry: { - send: true, - removeTestingFlag: false, - internalTelemetryArchive: true, - }, - endings: { - expired: { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=expired", - ], - }, - }, - testing: { - expired: true, - }, - }; - - before(async function reinstallSetupAndAwaitEndStudy() { - await installAddon(); - const _ = await addonExec(async (_studySetupForTests, callback) => { - // Ensure we have a configured study and are supposed to run our feature - browser.study.onEndStudy.addListener(async _endingResult => { - console.log( - "In resetSetupAndAwaitEndStudy - onEndStudy listener", - _endingResult, - ); - const internals = await browser.studyDebug.getInternals(); - callback({ - endingResult: _endingResult, - endingInternals: internals, - }); - }); - browser.study.onReady.addListener(async _studyInfo => { - console.log( - "In resetSetupAndAwaitEndStudy - onReady listener", - _studyInfo, - ); - throw new Error("onReady should not have been emitted", _studyInfo); - }); - await browser.study.setup(_studySetupForTests); - }, studySetupForTests(overrides)); - endingResult = _.endingResult; - endingInternals = _.endingInternals; - }); - - describe("browser.study.endStudy() side effects", function() { - it("should have fired onEndStudy event with the endingResult", function() { - // console.debug(full(endingResult)); - assert(endingResult); - assert.strictEqual(endingResult.endingName, "expired"); - assert.strictEqual(endingResult.queryArgs.fullreason, "expired"); - assert(endingResult.shouldUninstall); - assert.strictEqual( - endingResult.urls.length, - 1, - "the ending should have the expected number of urls configured", - ); - }); - - it("should have set the experiment as inactive", async () => { - const activeExperiments = await utils.telemetry.getActiveExperiments( - driver, - ); - assert( - !activeExperiments.hasOwnProperty(overrides.activeExperimentName), - ); - }); - - describe("should have sent the expected exit telemetry", function() { - let studyPings; - - before(async () => { - studyPings = {}; - studyPings.seen = endingInternals.seenTelemetry.reverse(); - studyPings.sent = await utils.telemetry.searchSentTelemetry( - driver, - { - type: [ - "shield-study", - "shield-study-addon", - "shield-study-error", - "pioneer-study", - ], - timestamp: beginTime, - }, - ); - // For debugging tests - // console.debug("Final pings report: ", utils.telemetry.pingsReport(studyPings.seen)); - // console.debug("Final pings with id and payload: ", utils.telemetry.pingsDebug(studyPings.seen)); - }); - - it("should have sent at least one shield telemetry ping", async () => { - assert( - studyPings.sent.length > 0, - "at least one shield telemetry ping", - ); - }); - - it("should have sent expected telemetry", async () => { - const observed = utils.telemetry.summarizePings( - studyType === "shield" ? studyPings.sent : studyPings.seen, - ); - const expected = [ - [ - "shield-study", - { - study_state: "exit", - }, - ], - [ - "shield-study", - { - study_state: "expired", - study_state_fullname: "expired", - }, - ], - [ - "shield-study", - { - study_state: "enter", - }, - ], - ]; - assert.deepStrictEqual( - observed, - expected, - "telemetry pings as as expected", - ); - }); - }); - }); - }); - - describe("setup of a study that expires within a few seconds should result in endStudy('expired') after a few seconds", function() { - let endingResult, endingInternals; - const overrides = { - activeExperimentName: "test:browser.study.api", - telemetry: { - send: true, - removeTestingFlag: false, - internalTelemetryArchive: true, - }, - expire: { - days: 1, - }, - endings: { - expired: { - baseUrls: [ - "https://qsurvey.mozilla.com/s3/Shield-Study-Example-Survey/?reason=expired", - ], - }, - }, - testing: { - firstRunTimestamp: null, // needs to be set in the before-hook below in order to be executed just before the setup of the study - }, - }; - - before(async function reinstallSetupAndConfigureAlarm() { - await installAddon(); - // Set the study to expire after a few seconds - const now = Number(Date.now()); - const msInOneDay = 60 * 60 * 24 * 1000; - overrides.testing.firstRunTimestamp = now - msInOneDay + 5000; - // console.log("Expiration debug: now, firstRunTimestamp, new Date(), new Date(now), new Date(firstRunTimestamp)", now, overrides.testing.firstRunTimestamp, new Date(), new Date(now), new Date(overrides.testing.firstRunTimestamp)); - const _ = await addonExec(async (_studySetupForTests, callback) => { - console.log( - "In resetSetupAndConfigureAlarm - addonExec", - _studySetupForTests, - ); - // Ensure we have a configured study and are supposed to run our feature - browser.study.onEndStudy.addListener(async _endingResult => { - console.log( - "In resetSetupAndConfigureAlarm - onEndStudy listener", - _endingResult, - ); - const internals = await browser.studyDebug.getInternals(); - callback({ - endingResult: _endingResult, - endingInternals: internals, - }); - }); - browser.study.onReady.addListener(async _studyInfo => { - console.log( - "In resetSetupAndConfigureAlarm - onReady listener", - _studyInfo, - ); - await browser.study.sendTelemetry({ foo: "bar" }); - const { delayInMinutes } = _studyInfo; - if (delayInMinutes !== undefined) { - const alarmName = `${browser.runtime.id}:studyExpiration`; - const alarmListener = async alarm => { - console.log( - "In resetSetupAndConfigureAlarm - alarmListener", - alarm, - ); - if (alarm.name === alarmName) { - browser.alarms.onAlarm.removeListener(alarmListener); - await browser.study.endStudy("expired"); - } - }; - console.log("Setting up alarm listener", alarmListener); - browser.alarms.onAlarm.addListener(alarmListener); - console.log("Creating alarm", alarmName, delayInMinutes); - browser.alarms.create(alarmName, { - delayInMinutes, - }); - } - }); - await browser.study.setup(_studySetupForTests); - }, studySetupForTests(overrides)); - endingResult = _.endingResult; - endingInternals = _.endingInternals; - }); - - describe("browser.study.endStudy() side effects", function() { - it("should have fired onEndStudy event with the endingResult", function() { - // console.debug(full(endingResult)); - assert(endingResult); - assert.strictEqual(endingResult.endingName, "expired"); - assert.strictEqual(endingResult.queryArgs.fullreason, "expired"); - assert(endingResult.shouldUninstall); - assert.strictEqual( - endingResult.urls.length, - 1, - "the ending should have the expected number of urls configured", - ); - }); - - it("should have set the experiment as inactive", async () => { - const activeExperiments = await utils.telemetry.getActiveExperiments( - driver, - ); - assert( - !activeExperiments.hasOwnProperty(overrides.activeExperimentName), - ); - }); - - describe("should have sent the expected exit telemetry", function() { - let studyPings; - - before(async () => { - studyPings = {}; - studyPings.seen = endingInternals.seenTelemetry.reverse(); - studyPings.sent = await utils.telemetry.searchSentTelemetry( - driver, - { - type: [ - "shield-study", - "shield-study-addon", - "shield-study-error", - "pioneer-study", - ], - timestamp: beginTime, - }, - ); - // For debugging tests - // console.debug("Final pings report: ", utils.telemetry.pingsReport(studyPings.seen)); - // console.debug("Final pings with id and payload: ", utils.telemetry.pingsDebug(studyPings.seen)); - }); - - it("should have sent at least one shield telemetry ping", async () => { - assert( - studyPings.sent.length > 0, - "at least one shield telemetry ping", - ); - }); - - it("should have sent expected telemetry", async () => { - const observed = utils.telemetry.summarizePings( - studyType === "shield" ? studyPings.sent : studyPings.seen, - ); - const expected = [ - [ - "shield-study", - { - study_state: "exit", - }, - ], - [ - "shield-study", - { - study_state: "expired", - study_state_fullname: "expired", - }, - ], - [ - "shield-study-addon", - { - attributes: { - foo: "bar", - }, - }, - ], - ]; - assert.deepStrictEqual( - observed, - expected, - "telemetry pings as as expected", - ); - }); - }); - }); }); }); @@ -1370,39 +327,32 @@ function publicApiTests(studyType) { describe("api: fullSurveyUrl", function() { describe("correctly constructs urls queryArgs", function() { it("an example url is correct", async function() { - const actual = await addonExec(async callback => { + const actual = await addonExec(async (_telemetryPipeline, callback) => { const result = await browser.study.fullSurveyUrl( "https://foo.com/survey-foo/", "mid-study-survey", + _telemetryPipeline, ); callback(result); - }); + }, telemetryPipeline); + console.debug({ actual }); const matchesExpectedExceptForVariableArguments = actual.indexOf( - "https://foo.com/survey-foo/?shield=3&study=test%3Abrowser.study.api", + "https://foo.com/survey-foo/?shield=3&study=shield-utils-test-addon%40shield.mozilla.org", ) > -1 && actual.indexOf( - "&testing=1&reason=mid-study-survey&fullreason=mid-study-survey", + "&testing=-1&reason=mid-study-survey&fullreason=mid-study-survey", ) > -1; assert(matchesExpectedExceptForVariableArguments); }); }); }); - - // TODO 5.3+ - describe.skip("possible 5.3+ future tests.", function() { - describe("uninstall by users - individual opt-out", function() {}); - - describe.skip("browser.study.logger", function() { - it("log level works?"); - }); - }); } -describe("PUBLIC API `browser.study` (studyType: shield)", function() { +describe("PUBLIC API `browser.study` (telemetryPipeline: shield)", function() { publicApiTests.call(this, "shield"); }); -describe("PUBLIC API `browser.study` (studyType: pioneer)", function() { +describe("PUBLIC API `browser.study` (telemetryPipeline: pioneer)", function() { publicApiTests.call(this, "pioneer"); }); diff --git a/test/functional/test-addon.js b/test/functional/test-addon.js index 020cd1c..62bb96c 100644 --- a/test/functional/test-addon.js +++ b/test/functional/test-addon.js @@ -12,7 +12,7 @@ const KEEPOPEN = process.env.KEEPOPEN; const assert = require("assert"); const utils = require("./utils"); -const testAddonTests = function(studyType) { +const testAddonTests = function(telemetryPipeline) { // This gives Firefox time to start, and us a bit longer during some of the tests. this.timeout(15000 + KEEPOPEN * 1000 * 3); @@ -22,15 +22,7 @@ const testAddonTests = function(studyType) { driver = await utils.setupWebdriver.promiseSetupDriver( utils.FIREFOX_PREFERENCES, ); - const widgetId = utils.ui.makeWidgetId( - "shield-utils-test-addon@shield.mozilla.org", - ); - await utils.preferences.set( - driver, - `extensions.${widgetId}.test.studyType`, - studyType, - ); - if (studyType === "pioneer") { + if (telemetryPipeline === "pioneer") { await utils.setupWebdriver.installPioneerOptInAddon(driver); } await utils.setupWebdriver.installAddon(driver); @@ -65,105 +57,12 @@ const testAddonTests = function(studyType) { ); assert(hasAccessToShieldUtilsWebExtensionApi); }); - - describe('test the test add-on\'s "onEveryExtensionLoad" process', function() { - // For unknown reasons, whenever we query browser.studyDebug.getInternals() or browser.study.getStudyInfo() - // from this test, a clean state is encountered. Instead, we let the relevant information be sent via messaging - // to test, stored in the following variable: - let informationFromAddon; - - /** - * Before running the tests in this group, trigger onEveryExtensionLoad and wait for the study to be running - */ - before(async () => { - informationFromAddon = await utils.executeJs.executeAsyncScriptInExtensionPageForTests( - driver, - async callback => { - // Let the test add-on know it is time to load the background logic - await browser.runtime - .sendMessage("test:onEveryExtensionLoad") - .catch(console.error); - - // Wait for the feature to be enabled before continuing with the test assertions - browser.runtime.onMessage.addListener(async request => { - console.log("test:onFeatureEnabled listener - request:", request); - if (request.message === "test:onFeatureEnabled") { - callback(request); - } - }); - }, - ); - // console.log("informationFromAddon", informationFromAddon); - }); - - it("should have chosen one of the study's variations", async () => { - const chosenVariation = informationFromAddon.studyInfo.variation; - assert(chosenVariation); - assert( - chosenVariation.name === "feature-active" || - chosenVariation.name === "feature-passive" || - chosenVariation.name === "control", - ); - }); - - describe.skip("test the library's endStudy() function", function() { - // before(async() => { - // await utils.executeJs.executeAsyncScriptInExtensionPageForTests( - // driver, - // async callback => { - // // TODO add tests for other reasons (?) - // await browser.study.endStudy("expired", { - // baseUrls: ["some.url"], - // endingName: "anEnding", - // endingClass: "ended-positive", - // }); - // callback(); - // }, - // ); - // }); - // TODO: glind - restore these tests - /* - describe("test the opening of an URL at the end of the study", function() { - it("should open a new tab", async() => { - const newTabOpened = await driver.wait(async() => { - const handles = await driver.getAllWindowHandles(); - return handles.length === 2; // opened a new tab - }, 3000); - assert(newTabOpened); - }); - - it("should open a new tab to the correct URL", async() => { - const currentHandle = await driver.getWindowHandle(); - const firefox = require("selenium-webdriver/firefox"); - const Context = firefox.Context; - driver.setContext(Context.CONTENT); - // Find the new window handle. - let newWindowHandle = null; - const handles = await driver.getAllWindowHandles(); - for (const handle of handles) { - if (handle !== currentHandle) { - newWindowHandle = handle; - } - } - const correctURLOpened = await driver.wait(async() => { - await driver.switchTo().window(newWindowHandle); - const currentURL = await driver.getCurrentUrl(); - return currentURL.startsWith( - "http://www.example.com/?reason=expired", - ); - }); - assert(correctURLOpened); - }); - }); - */ - }); - }); }; -describe("Tests verifying that the test add-on works as expected (studyType: shield)", function() { +describe("Tests verifying that the test add-on loads (telemetryPipeline: shield)", function() { testAddonTests.bind(this)("shield"); }); -describe("Tests verifying that the test add-on works as expected (studyType: pioneer)", function() { +describe("Tests verifying that the test add-on loads (telemetryPipeline: pioneer)", function() { testAddonTests.bind(this)("pioneer"); }); diff --git a/testUtils/wip.js b/testUtils/wip.js deleted file mode 100644 index 173feaa..0000000 --- a/testUtils/wip.js +++ /dev/null @@ -1,101 +0,0 @@ -/* eslint-env node */ -/* eslint no-console:off */ - -/* -const webdriver = require("selenium-webdriver"); -const firefox = require("selenium-webdriver/firefox"); -const Context = firefox.Context; -const until = webdriver.until; -*/ - -// TODO glind general wrapper for 'async with callback'? - -/* this is NOT WORKING FOR UNKNOWN HARD TO EXLAIN REASONS -=> Uncaught WebDriverError: InternalError: too much recursion -module.exports.allAddons = async(driver) => { - // callback is how you get the return back from the script - return driver.executeAsyncScript(async(callback,) => { - Components.utils.import("resource://gre/modules/AddonManager.jsm"); - const L = await AddonManager.getAllAddons(); - callback(await L); - }); -}; -*/ - -// TODO glind, specific to share-button-study but useful to demo patterns. -// TODO glind, generalize, document, or destroy - -// module.exports.copyUrlBar = async(driver) => { -// const urlBar = await getChromeElementBy.id(driver,'urlbar'); -// const urlBar = await module.exports.promiseUrlBar(driver); -// await urlBar.sendKeys(webdriver.Key.chord(MODIFIER_KEY, "A")); -// await urlBar.sendKeys(webdriver.Key.chord(MODIFIER_KEY, "C")); -// }; - -// module.exports.testAnimation = async(driver) => { -// const button = await module.exports.promiseAddonButton(driver); -// if (button === null) { return { hasClass: false, hasColor: false }; } -// -// const buttonClassString = await button.getAttribute("class"); -// const buttonColor = await button.getCssValue("background-color"); -// -// const hasClass = buttonClassString.split(" ").includes("social-share-button-on"); -// const hasColor = buttonColor.includes("43, 153, 255"); -// return { hasClass, hasColor }; -// }; - -// module.exports.waitForClassAdded = async(driver) => { -// try { -// const animationTest = await driver.wait(async() => { -// const { hasClass } = await module.exports.testAnimation(driver); -// return hasClass; -// }, 1000); -// return animationTest; -// } catch (e) { -// if (e.name === "TimeoutError") { return null; } -// throw (e); -// } -// }; -// -// module.exports.waitForAnimationEnd = async(driver) => { -// try { -// return await driver.wait(async() => { -// const { hasClass, hasColor } = await module.exports.testAnimation(driver); -// return !hasClass && !hasColor; -// }, 1000); -// } catch (e) { -// if (e.name === "TimeoutError") { return null; } -// throw (e); -// } -// }; - -// module.exports.testPanel = async(driver, panelId) => { -// driver.setContext(Context.CHROME); -// try { // if we can't find the panel, return false -// return await driver.wait(async() => { -// // need to execute JS, since state is not an HTML attribute, it's a property -// const panelState = await driver.executeAsyncScript((panelIdArg, callback) => { -// const shareButtonPanel = window.document.getElementById(panelIdArg); -// if (shareButtonPanel === null) { -// callback(null); -// } else { -// const state = shareButtonPanel.state; -// callback(state); -// } -// }, panelId); -// return panelState === "open"; -// }, 1000); -// } catch (e) { -// if (e.name === "TimeoutError") { return null; } -// throw e; -// } -// }; - -// module.exports.closePanel = async(driver, target = null) => { -// if (target !== null) { -// target.sendKeys(webdriver.Key.ESCAPE); -// } else { -// const urlbar = await module.exports.promiseUrlBar(driver); -// await urlbar.sendKeys(webdriver.Key.ESCAPE); -// } -// }; diff --git a/webExtensionApis/prefs/api.js b/webExtensionApis/prefs/api.js deleted file mode 100644 index 503a7e2..0000000 --- a/webExtensionApis/prefs/api.js +++ /dev/null @@ -1,15 +0,0 @@ -"use strict"; - -/* global ExtensionAPI */ - -ChromeUtils.import("resource://gre/modules/Services.jsm"); - -/* https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/functions.html */ -this.prefs = class extends ExtensionAPI { - getAPI(context) { - return { - // eslint-disable-next-line no-undef - prefs: Services.prefs, - }; - } -}; diff --git a/webExtensionApis/prefs/schema.json b/webExtensionApis/prefs/schema.json deleted file mode 100644 index 605c449..0000000 --- a/webExtensionApis/prefs/schema.json +++ /dev/null @@ -1,36 +0,0 @@ -[ - { - "namespace": "prefs", - "description": "Pref get, set, watch, unwatch(?)", - "functions": [ - { - "name": "get", - "type": "function", - "description": "Returns the value of a pref", - "async": true, - "parameters": [ - { - "name": "prefName", - "type": "string" - } - ] - }, - { - "name": "set", - "type": "function", - "description": "Sets the value of a pref", - "async": true, - "parameters": [ - { - "name": "prefName", - "type": "string" - }, - { - "name": "value", - "type": "any" - } - ] - } - ] - } -] diff --git a/webExtensionApis/study/.gitignore b/webExtensionApis/study/.gitignore index fa0b6dc..f3cd4f1 100644 --- a/webExtensionApis/study/.gitignore +++ b/webExtensionApis/study/.gitignore @@ -1,3 +1 @@ -/api.js -/schema.json /stubApi.js diff --git a/webExtensionApis/study/api.js b/webExtensionApis/study/api.js new file mode 100644 index 0000000..415a9bc --- /dev/null +++ b/webExtensionApis/study/api.js @@ -0,0 +1,12405 @@ +/* eslint-disable */ +(function(e, a) { for(var i in a) e[i] = a[i]; }(this, /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // identity function for calling harmony imports with the correct context +/******/ __webpack_require__.i = function(value) { return value; }; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 72); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + + +module.exports = { + copy: copy, + checkDataType: checkDataType, + checkDataTypes: checkDataTypes, + coerceToTypes: coerceToTypes, + toHash: toHash, + getProperty: getProperty, + escapeQuotes: escapeQuotes, + equal: __webpack_require__(5), + ucs2length: __webpack_require__(28), + varOccurences: varOccurences, + varReplace: varReplace, + cleanUpCode: cleanUpCode, + finalCleanUpCode: finalCleanUpCode, + schemaHasRules: schemaHasRules, + schemaHasRulesExcept: schemaHasRulesExcept, + toQuotedString: toQuotedString, + getPathExpr: getPathExpr, + getPath: getPath, + getData: getData, + unescapeFragment: unescapeFragment, + unescapeJsonPointer: unescapeJsonPointer, + escapeFragment: escapeFragment, + escapeJsonPointer: escapeJsonPointer +}; + + +function copy(o, to) { + to = to || {}; + for (var key in o) to[key] = o[key]; + return to; +} + + +function checkDataType(dataType, data, negate) { + var EQUAL = negate ? ' !== ' : ' === ' + , AND = negate ? ' || ' : ' && ' + , OK = negate ? '!' : '' + , NOT = negate ? '' : '!'; + switch (dataType) { + case 'null': return data + EQUAL + 'null'; + case 'array': return OK + 'Array.isArray(' + data + ')'; + case 'object': return '(' + OK + data + AND + + 'typeof ' + data + EQUAL + '"object"' + AND + + NOT + 'Array.isArray(' + data + '))'; + case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND + + NOT + '(' + data + ' % 1)' + + AND + data + EQUAL + data + ')'; + default: return 'typeof ' + data + EQUAL + '"' + dataType + '"'; + } +} + + +function checkDataTypes(dataTypes, data) { + switch (dataTypes.length) { + case 1: return checkDataType(dataTypes[0], data, true); + default: + var code = ''; + var types = toHash(dataTypes); + if (types.array && types.object) { + code = types.null ? '(': '(!' + data + ' || '; + code += 'typeof ' + data + ' !== "object")'; + delete types.null; + delete types.array; + delete types.object; + } + if (types.number) delete types.integer; + for (var t in types) + code += (code ? ' && ' : '' ) + checkDataType(t, data, true); + + return code; + } +} + + +var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]); +function coerceToTypes(optionCoerceTypes, dataTypes) { + if (Array.isArray(dataTypes)) { + var types = []; + for (var i=0; i= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl); + return paths[lvl - up]; + } + + if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl); + data = 'data' + ((lvl - up) || ''); + if (!jsonPointer) return data; + } + + var expr = data; + var segments = jsonPointer.split('/'); + for (var i=0; iGary Court + * @see http://github.com/garycourt/uri-js + */ +/** + * Copyright 2011 Gary Court. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of Gary Court. + */ + + + + +const SCHEMES = {}; +/* harmony export (immutable) */ __webpack_exports__["a"] = SCHEMES; + +function pctEncChar(chr) { + const c = chr.charCodeAt(0); + let e; + if (c < 16) + e = "%0" + c.toString(16).toUpperCase(); + else if (c < 128) + e = "%" + c.toString(16).toUpperCase(); + else if (c < 2048) + e = "%" + ((c >> 6) | 192).toString(16).toUpperCase() + "%" + ((c & 63) | 128).toString(16).toUpperCase(); + else + e = "%" + ((c >> 12) | 224).toString(16).toUpperCase() + "%" + (((c >> 6) & 63) | 128).toString(16).toUpperCase() + "%" + ((c & 63) | 128).toString(16).toUpperCase(); + return e; +} +function pctDecChars(str) { + let newStr = ""; + let i = 0; + const il = str.length; + while (i < il) { + const c = parseInt(str.substr(i + 1, 2), 16); + if (c < 128) { + newStr += String.fromCharCode(c); + i += 3; + } + else if (c >= 194 && c < 224) { + if ((il - i) >= 6) { + const c2 = parseInt(str.substr(i + 4, 2), 16); + newStr += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + } + else { + newStr += str.substr(i, 6); + } + i += 6; + } + else if (c >= 224) { + if ((il - i) >= 9) { + const c2 = parseInt(str.substr(i + 4, 2), 16); + const c3 = parseInt(str.substr(i + 7, 2), 16); + newStr += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + } + else { + newStr += str.substr(i, 9); + } + i += 9; + } + else { + newStr += str.substr(i, 3); + i += 3; + } + } + return newStr; +} +function _normalizeComponentEncoding(components, protocol) { + function decodeUnreserved(str) { + const decStr = pctDecChars(str); + return (!decStr.match(protocol.UNRESERVED) ? str : decStr); + } + if (components.scheme) + components.scheme = String(components.scheme).replace(protocol.PCT_ENCODED, decodeUnreserved).toLowerCase().replace(protocol.NOT_SCHEME, ""); + if (components.userinfo !== undefined) + components.userinfo = String(components.userinfo).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_USERINFO, pctEncChar).replace(protocol.PCT_ENCODED, __WEBPACK_IMPORTED_MODULE_3__util__["a" /* toUpperCase */]); + if (components.host !== undefined) + components.host = String(components.host).replace(protocol.PCT_ENCODED, decodeUnreserved).toLowerCase().replace(protocol.NOT_HOST, pctEncChar).replace(protocol.PCT_ENCODED, __WEBPACK_IMPORTED_MODULE_3__util__["a" /* toUpperCase */]); + if (components.path !== undefined) + components.path = String(components.path).replace(protocol.PCT_ENCODED, decodeUnreserved).replace((components.scheme ? protocol.NOT_PATH : protocol.NOT_PATH_NOSCHEME), pctEncChar).replace(protocol.PCT_ENCODED, __WEBPACK_IMPORTED_MODULE_3__util__["a" /* toUpperCase */]); + if (components.query !== undefined) + components.query = String(components.query).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_QUERY, pctEncChar).replace(protocol.PCT_ENCODED, __WEBPACK_IMPORTED_MODULE_3__util__["a" /* toUpperCase */]); + if (components.fragment !== undefined) + components.fragment = String(components.fragment).replace(protocol.PCT_ENCODED, decodeUnreserved).replace(protocol.NOT_FRAGMENT, pctEncChar).replace(protocol.PCT_ENCODED, __WEBPACK_IMPORTED_MODULE_3__util__["a" /* toUpperCase */]); + return components; +} +; +function _stripLeadingZeros(str) { + return str.replace(/^0*(.*)/, "$1") || "0"; +} +function _normalizeIPv4(host, protocol) { + const matches = host.match(protocol.IPV4ADDRESS) || []; + const [, address] = matches; + if (address) { + return address.split(".").map(_stripLeadingZeros).join("."); + } + else { + return host; + } +} +function _normalizeIPv6(host, protocol) { + const matches = host.match(protocol.IPV6ADDRESS) || []; + const [, address, zone] = matches; + if (address) { + const [last, first] = address.toLowerCase().split('::').reverse(); + const firstFields = first ? first.split(":").map(_stripLeadingZeros) : []; + const lastFields = last.split(":").map(_stripLeadingZeros); + const isLastFieldIPv4Address = protocol.IPV4ADDRESS.test(lastFields[lastFields.length - 1]); + const fieldCount = isLastFieldIPv4Address ? 7 : 8; + const lastFieldsStart = lastFields.length - fieldCount; + const fields = Array(fieldCount); + for (let x = 0; x < fieldCount; ++x) { + fields[x] = firstFields[x] || lastFields[lastFieldsStart + x] || ''; + } + if (isLastFieldIPv4Address) { + fields[fieldCount - 1] = _normalizeIPv4(fields[fieldCount - 1], protocol); + } + const allZeroFields = fields.reduce((acc, field, index) => { + if (!field || field === "0") { + const lastLongest = acc[acc.length - 1]; + if (lastLongest && lastLongest.index + lastLongest.length === index) { + lastLongest.length++; + } + else { + acc.push({ index, length: 1 }); + } + } + return acc; + }, []); + const longestZeroFields = allZeroFields.sort((a, b) => b.length - a.length)[0]; + let newHost; + if (longestZeroFields && longestZeroFields.length > 1) { + const newFirst = fields.slice(0, longestZeroFields.index); + const newLast = fields.slice(longestZeroFields.index + longestZeroFields.length); + newHost = newFirst.join(":") + "::" + newLast.join(":"); + } + else { + newHost = fields.join(":"); + } + if (zone) { + newHost += "%" + zone; + } + return newHost; + } + else { + return host; + } +} +const URI_PARSE = /^(?:([^:\/?#]+):)?(?:\/\/((?:([^\/?#@]*)@)?(\[[^\/?#\]]+\]|[^\/?#:]*)(?:\:(\d*))?))?([^?#]*)(?:\?([^#]*))?(?:#((?:.|\n|\r)*))?/i; +const NO_MATCH_IS_UNDEFINED = ("").match(/(){0}/)[1] === undefined; +function parse(uriString, options = {}) { + const components = {}; + const protocol = (options.iri !== false ? __WEBPACK_IMPORTED_MODULE_1__regexps_iri__["a" /* default */] : __WEBPACK_IMPORTED_MODULE_0__regexps_uri__["a" /* default */]); + if (options.reference === "suffix") + uriString = (options.scheme ? options.scheme + ":" : "") + "//" + uriString; + const matches = uriString.match(URI_PARSE); + if (matches) { + if (NO_MATCH_IS_UNDEFINED) { + //store each component + components.scheme = matches[1]; + components.userinfo = matches[3]; + components.host = matches[4]; + components.port = parseInt(matches[5], 10); + components.path = matches[6] || ""; + components.query = matches[7]; + components.fragment = matches[8]; + //fix port number + if (isNaN(components.port)) { + components.port = matches[5]; + } + } + else { //IE FIX for improper RegExp matching + //store each component + components.scheme = matches[1] || undefined; + components.userinfo = (uriString.indexOf("@") !== -1 ? matches[3] : undefined); + components.host = (uriString.indexOf("//") !== -1 ? matches[4] : undefined); + components.port = parseInt(matches[5], 10); + components.path = matches[6] || ""; + components.query = (uriString.indexOf("?") !== -1 ? matches[7] : undefined); + components.fragment = (uriString.indexOf("#") !== -1 ? matches[8] : undefined); + //fix port number + if (isNaN(components.port)) { + components.port = (uriString.match(/\/\/(?:.|\n)*\:(?:\/|\?|\#|$)/) ? matches[4] : undefined); + } + } + if (components.host) { + //normalize IP hosts + components.host = _normalizeIPv6(_normalizeIPv4(components.host, protocol), protocol); + } + //determine reference type + if (components.scheme === undefined && components.userinfo === undefined && components.host === undefined && components.port === undefined && !components.path && components.query === undefined) { + components.reference = "same-document"; + } + else if (components.scheme === undefined) { + components.reference = "relative"; + } + else if (components.fragment === undefined) { + components.reference = "absolute"; + } + else { + components.reference = "uri"; + } + //check for reference errors + if (options.reference && options.reference !== "suffix" && options.reference !== components.reference) { + components.error = components.error || "URI is not a " + options.reference + " reference."; + } + //find scheme handler + const schemeHandler = SCHEMES[(options.scheme || components.scheme || "").toLowerCase()]; + //check if scheme can't handle IRIs + if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) { + //if host component is a domain name + if (components.host && (options.domainHost || (schemeHandler && schemeHandler.domainHost))) { + //convert Unicode IDN -> ASCII IDN + try { + components.host = __WEBPACK_IMPORTED_MODULE_2_punycode___default.a.toASCII(components.host.replace(protocol.PCT_ENCODED, pctDecChars).toLowerCase()); + } + catch (e) { + components.error = components.error || "Host's domain name can not be converted to ASCII via punycode: " + e; + } + } + //convert IRI -> URI + _normalizeComponentEncoding(components, __WEBPACK_IMPORTED_MODULE_0__regexps_uri__["a" /* default */]); + } + else { + //normalize encodings + _normalizeComponentEncoding(components, protocol); + } + //perform scheme specific parsing + if (schemeHandler && schemeHandler.parse) { + schemeHandler.parse(components, options); + } + } + else { + components.error = components.error || "URI can not be parsed."; + } + return components; +} +; +function _recomposeAuthority(components, options) { + const protocol = (options.iri !== false ? __WEBPACK_IMPORTED_MODULE_1__regexps_iri__["a" /* default */] : __WEBPACK_IMPORTED_MODULE_0__regexps_uri__["a" /* default */]); + const uriTokens = []; + if (components.userinfo !== undefined) { + uriTokens.push(components.userinfo); + uriTokens.push("@"); + } + if (components.host !== undefined) { + //normalize IP hosts, add brackets and escape zone separator for IPv6 + uriTokens.push(_normalizeIPv6(_normalizeIPv4(String(components.host), protocol), protocol).replace(protocol.IPV6ADDRESS, (_, $1, $2) => "[" + $1 + ($2 ? "%25" + $2 : "") + "]")); + } + if (typeof components.port === "number") { + uriTokens.push(":"); + uriTokens.push(components.port.toString(10)); + } + return uriTokens.length ? uriTokens.join("") : undefined; +} +; +const RDS1 = /^\.\.?\//; +const RDS2 = /^\/\.(\/|$)/; +const RDS3 = /^\/\.\.(\/|$)/; +const RDS4 = /^\.\.?$/; +const RDS5 = /^\/?(?:.|\n)*?(?=\/|$)/; +function removeDotSegments(input) { + const output = []; + while (input.length) { + if (input.match(RDS1)) { + input = input.replace(RDS1, ""); + } + else if (input.match(RDS2)) { + input = input.replace(RDS2, "/"); + } + else if (input.match(RDS3)) { + input = input.replace(RDS3, "/"); + output.pop(); + } + else if (input === "." || input === "..") { + input = ""; + } + else { + const im = input.match(RDS5); + if (im) { + const s = im[0]; + input = input.slice(s.length); + output.push(s); + } + else { + throw new Error("Unexpected dot segment condition"); + } + } + } + return output.join(""); +} +; +function serialize(components, options = {}) { + const protocol = (options.iri ? __WEBPACK_IMPORTED_MODULE_1__regexps_iri__["a" /* default */] : __WEBPACK_IMPORTED_MODULE_0__regexps_uri__["a" /* default */]); + const uriTokens = []; + //find scheme handler + const schemeHandler = SCHEMES[(options.scheme || components.scheme || "").toLowerCase()]; + //perform scheme specific serialization + if (schemeHandler && schemeHandler.serialize) + schemeHandler.serialize(components, options); + if (components.host) { + //if host component is an IPv6 address + if (protocol.IPV6ADDRESS.test(components.host)) { + //TODO: normalize IPv6 address as per RFC 5952 + } + //if host component is a domain name + else if (options.domainHost || (schemeHandler && schemeHandler.domainHost)) { + //convert IDN via punycode + try { + components.host = (!options.iri ? __WEBPACK_IMPORTED_MODULE_2_punycode___default.a.toASCII(components.host.replace(protocol.PCT_ENCODED, pctDecChars).toLowerCase()) : __WEBPACK_IMPORTED_MODULE_2_punycode___default.a.toUnicode(components.host)); + } + catch (e) { + components.error = components.error || "Host's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e; + } + } + } + //normalize encoding + _normalizeComponentEncoding(components, protocol); + if (options.reference !== "suffix" && components.scheme) { + uriTokens.push(components.scheme); + uriTokens.push(":"); + } + const authority = _recomposeAuthority(components, options); + if (authority !== undefined) { + if (options.reference !== "suffix") { + uriTokens.push("//"); + } + uriTokens.push(authority); + if (components.path && components.path.charAt(0) !== "/") { + uriTokens.push("/"); + } + } + if (components.path !== undefined) { + let s = components.path; + if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) { + s = removeDotSegments(s); + } + if (authority === undefined) { + s = s.replace(/^\/\//, "/%2F"); //don't allow the path to start with "//" + } + uriTokens.push(s); + } + if (components.query !== undefined) { + uriTokens.push("?"); + uriTokens.push(components.query); + } + if (components.fragment !== undefined) { + uriTokens.push("#"); + uriTokens.push(components.fragment); + } + return uriTokens.join(""); //merge tokens into a string +} +; +function resolveComponents(base, relative, options = {}, skipNormalization) { + const target = {}; + if (!skipNormalization) { + base = parse(serialize(base, options), options); //normalize base components + relative = parse(serialize(relative, options), options); //normalize relative components + } + options = options || {}; + if (!options.tolerant && relative.scheme) { + target.scheme = relative.scheme; + //target.authority = relative.authority; + target.userinfo = relative.userinfo; + target.host = relative.host; + target.port = relative.port; + target.path = removeDotSegments(relative.path || ""); + target.query = relative.query; + } + else { + if (relative.userinfo !== undefined || relative.host !== undefined || relative.port !== undefined) { + //target.authority = relative.authority; + target.userinfo = relative.userinfo; + target.host = relative.host; + target.port = relative.port; + target.path = removeDotSegments(relative.path || ""); + target.query = relative.query; + } + else { + if (!relative.path) { + target.path = base.path; + if (relative.query !== undefined) { + target.query = relative.query; + } + else { + target.query = base.query; + } + } + else { + if (relative.path.charAt(0) === "/") { + target.path = removeDotSegments(relative.path); + } + else { + if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) { + target.path = "/" + relative.path; + } + else if (!base.path) { + target.path = relative.path; + } + else { + target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path; + } + target.path = removeDotSegments(target.path); + } + target.query = relative.query; + } + //target.authority = base.authority; + target.userinfo = base.userinfo; + target.host = base.host; + target.port = base.port; + } + target.scheme = base.scheme; + } + target.fragment = relative.fragment; + return target; +} +; +function resolve(baseURI, relativeURI, options) { + const schemelessOptions = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_3__util__["b" /* assign */])({ scheme: 'null' }, options); + return serialize(resolveComponents(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true), schemelessOptions); +} +; +function normalize(uri, options) { + if (typeof uri === "string") { + uri = serialize(parse(uri, options), options); + } + else if (__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_3__util__["c" /* typeOf */])(uri) === "object") { + uri = parse(serialize(uri, options), options); + } + return uri; +} +; +function equal(uriA, uriB, options) { + if (typeof uriA === "string") { + uriA = serialize(parse(uriA, options), options); + } + else if (__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_3__util__["c" /* typeOf */])(uriA) === "object") { + uriA = serialize(uriA, options); + } + if (typeof uriB === "string") { + uriB = serialize(parse(uriB, options), options); + } + else if (__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_3__util__["c" /* typeOf */])(uriB) === "object") { + uriB = serialize(uriB, options); + } + return uriA === uriB; +} +; +function escapeComponent(str, options) { + return str && str.toString().replace((!options || !options.iri ? __WEBPACK_IMPORTED_MODULE_0__regexps_uri__["a" /* default */].ESCAPE : __WEBPACK_IMPORTED_MODULE_1__regexps_iri__["a" /* default */].ESCAPE), pctEncChar); +} +; +function unescapeComponent(str, options) { + return str && str.toString().replace((!options || !options.iri ? __WEBPACK_IMPORTED_MODULE_0__regexps_uri__["a" /* default */].PCT_ENCODED : __WEBPACK_IMPORTED_MODULE_1__regexps_iri__["a" /* default */].PCT_ENCODED), pctDecChars); +} +; +//# sourceMappingURL=uri.js.map + +/***/ }), +/* 2 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export createLogger */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return utilsLogger; }); +/* eslint-env commonjs */ + + + +/** + * Creates a logger for debugging. + * + * The pref to control this is "shieldStudy.logLevel" + * + * @param {string} prefix - a prefix string to be printed before + * the actual logged message + * @param {string} maxLogLevelPref - String pref name which contains the + * level to use for maxLogLevel + * @param {string} maxLogLevel - level to use by default, see LOG_LEVELS in gre/modules/Console.jsm + * @returns {Object} - the Console instance, see gre/modules/Console.jsm + */ +function createLogger(prefix, maxLogLevelPref, maxLogLevel = "warn") { + const ConsoleAPI = ChromeUtils.import( + "resource://gre/modules/Console.jsm", + {}, + ).ConsoleAPI; + return new ConsoleAPI({ + prefix, + maxLogLevelPref, + maxLogLevel, + }); +} + +const utilsLogger = createLogger("shield-study-utils", "shieldStudy.logLevel"); + + + + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var resolve = __webpack_require__(4); + +module.exports = { + Validation: errorSubclass(ValidationError), + MissingRef: errorSubclass(MissingRefError) +}; + + +function ValidationError(errors) { + this.message = 'validation failed'; + this.errors = errors; + this.ajv = this.validation = true; +} + + +MissingRefError.message = function (baseId, ref) { + return 'can\'t resolve reference ' + ref + ' from id ' + baseId; +}; + + +function MissingRefError(baseId, ref, message) { + this.message = message || MissingRefError.message(baseId, ref); + this.missingRef = resolve.url(baseId, ref); + this.missingSchema = resolve.normalizeId(resolve.fullPath(this.missingRef)); +} + + +function errorSubclass(Subclass) { + Subclass.prototype = Object.create(Error.prototype); + Subclass.prototype.constructor = Subclass; + return Subclass; +} + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var URI = __webpack_require__(64) + , equal = __webpack_require__(5) + , util = __webpack_require__(0) + , SchemaObject = __webpack_require__(8) + , traverse = __webpack_require__(58); + +module.exports = resolve; + +resolve.normalizeId = normalizeId; +resolve.fullPath = getFullPath; +resolve.url = resolveUrl; +resolve.ids = resolveIds; +resolve.inlineRef = inlineRef; +resolve.schema = resolveSchema; + +/** + * [resolve and compile the references ($ref)] + * @this Ajv + * @param {Function} compile reference to schema compilation funciton (localCompile) + * @param {Object} root object with information about the root schema for the current schema + * @param {String} ref reference to resolve + * @return {Object|Function} schema object (if the schema can be inlined) or validation function + */ +function resolve(compile, root, ref) { + /* jshint validthis: true */ + var refVal = this._refs[ref]; + if (typeof refVal == 'string') { + if (this._refs[refVal]) refVal = this._refs[refVal]; + else return resolve.call(this, compile, root, refVal); + } + + refVal = refVal || this._schemas[ref]; + if (refVal instanceof SchemaObject) { + return inlineRef(refVal.schema, this._opts.inlineRefs) + ? refVal.schema + : refVal.validate || this._compile(refVal); + } + + var res = resolveSchema.call(this, root, ref); + var schema, v, baseId; + if (res) { + schema = res.schema; + root = res.root; + baseId = res.baseId; + } + + if (schema instanceof SchemaObject) { + v = schema.validate || compile.call(this, schema.schema, root, undefined, baseId); + } else if (schema !== undefined) { + v = inlineRef(schema, this._opts.inlineRefs) + ? schema + : compile.call(this, schema, root, undefined, baseId); + } + + return v; +} + + +/** + * Resolve schema, its root and baseId + * @this Ajv + * @param {Object} root root object with properties schema, refVal, refs + * @param {String} ref reference to resolve + * @return {Object} object with properties schema, root, baseId + */ +function resolveSchema(root, ref) { + /* jshint validthis: true */ + var p = URI.parse(ref) + , refPath = _getFullPath(p) + , baseId = getFullPath(this._getId(root.schema)); + if (refPath !== baseId) { + var id = normalizeId(refPath); + var refVal = this._refs[id]; + if (typeof refVal == 'string') { + return resolveRecursive.call(this, root, refVal, p); + } else if (refVal instanceof SchemaObject) { + if (!refVal.validate) this._compile(refVal); + root = refVal; + } else { + refVal = this._schemas[id]; + if (refVal instanceof SchemaObject) { + if (!refVal.validate) this._compile(refVal); + if (id == normalizeId(ref)) + return { schema: refVal, root: root, baseId: baseId }; + root = refVal; + } else { + return; + } + } + if (!root.schema) return; + baseId = getFullPath(this._getId(root.schema)); + } + return getJsonPointer.call(this, p, baseId, root.schema, root); +} + + +/* @this Ajv */ +function resolveRecursive(root, ref, parsedRef) { + /* jshint validthis: true */ + var res = resolveSchema.call(this, root, ref); + if (res) { + var schema = res.schema; + var baseId = res.baseId; + root = res.root; + var id = this._getId(schema); + if (id) baseId = resolveUrl(baseId, id); + return getJsonPointer.call(this, parsedRef, baseId, schema, root); + } +} + + +var PREVENT_SCOPE_CHANGE = util.toHash(['properties', 'patternProperties', 'enum', 'dependencies', 'definitions']); +/* @this Ajv */ +function getJsonPointer(parsedRef, baseId, schema, root) { + /* jshint validthis: true */ + parsedRef.fragment = parsedRef.fragment || ''; + if (parsedRef.fragment.slice(0,1) != '/') return; + var parts = parsedRef.fragment.split('/'); + + for (var i = 1; i < parts.length; i++) { + var part = parts[i]; + if (part) { + part = util.unescapeFragment(part); + schema = schema[part]; + if (schema === undefined) break; + var id; + if (!PREVENT_SCOPE_CHANGE[part]) { + id = this._getId(schema); + if (id) baseId = resolveUrl(baseId, id); + if (schema.$ref) { + var $ref = resolveUrl(baseId, schema.$ref); + var res = resolveSchema.call(this, root, $ref); + if (res) { + schema = res.schema; + root = res.root; + baseId = res.baseId; + } + } + } + } + } + if (schema !== undefined && schema !== root.schema) + return { schema: schema, root: root, baseId: baseId }; +} + + +var SIMPLE_INLINED = util.toHash([ + 'type', 'format', 'pattern', + 'maxLength', 'minLength', + 'maxProperties', 'minProperties', + 'maxItems', 'minItems', + 'maximum', 'minimum', + 'uniqueItems', 'multipleOf', + 'required', 'enum' +]); +function inlineRef(schema, limit) { + if (limit === false) return false; + if (limit === undefined || limit === true) return checkNoRef(schema); + else if (limit) return countKeys(schema) <= limit; +} + + +function checkNoRef(schema) { + var item; + if (Array.isArray(schema)) { + for (var i=0; i 1) { + sets[0] = sets[0].slice(0, -1); + const xl = sets.length - 1; + for (let x = 1; x < xl; ++x) { + sets[x] = sets[x].slice(1, -1); + } + sets[xl] = sets[xl].slice(1); + return sets.join(''); + } + else { + return sets[0]; + } +} +function subexp(str) { + return "(?:" + str + ")"; +} +function typeOf(o) { + return o === undefined ? "undefined" : (o === null ? "null" : Object.prototype.toString.call(o).split(" ").pop().split("]").shift().toLowerCase()); +} +function toUpperCase(str) { + return str.toUpperCase(); +} +function toArray(obj) { + return obj !== undefined && obj !== null ? (obj instanceof Array ? obj : (typeof obj.length !== "number" || obj.split || obj.setInterval || obj.call ? [obj] : Array.prototype.slice.call(obj))) : []; +} +function assign(target, source) { + const obj = target; + if (source) { + for (const key in source) { + obj[key] = source[key]; + } + } + return obj; +} +//# sourceMappingURL=util.js.map + +/***/ }), +/* 7 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export isShieldEnabled */ +/* harmony export (immutable) */ __webpack_exports__["b"] = isUserOptedInToPioneer; +/* harmony export (immutable) */ __webpack_exports__["a"] = getDataPermissions; +const { Services } = ChromeUtils.import( + "resource://gre/modules/Services.jsm", + {}, +); +const { AddonManager } = ChromeUtils.import( + "resource://gre/modules/AddonManager.jsm", + {}, +); + +/** + * Checks to see if SHIELD is enabled for a user. + * + * @returns {Boolean} + * A boolean to indicate SHIELD opt-in status. + */ +function isShieldEnabled() { + return Services.prefs.getBoolPref("app.shield.optoutstudies.enabled", true); +} + +/** + * Checks to see if the user has opted in to Pioneer. This is + * done by checking that the opt-in addon is installed and active. + * + * @returns {Boolean} + * A boolean to indicate opt-in status. + */ +async function isUserOptedInToPioneer() { + const addon = await AddonManager.getAddonByID("pioneer-opt-in@mozilla.org"); + return isShieldEnabled() && addon !== null && addon.isActive; +} + +async function getDataPermissions() { + const shield = isShieldEnabled(); + const pioneer = await isUserOptedInToPioneer(); + return { + shield, + pioneer, + }; +} + + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var util = __webpack_require__(0); + +module.exports = SchemaObject; + +function SchemaObject(obj) { + util.copy(obj, this); +} + + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate__limit(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $isMax = $keyword == 'maximum', + $exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum', + $schemaExcl = it.schema[$exclusiveKeyword], + $isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data, + $op = $isMax ? '<' : '>', + $notOp = $isMax ? '>' : '<', + $errorKeyword = undefined; + if ($isDataExcl) { + var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr), + $exclusive = 'exclusive' + $lvl, + $exclType = 'exclType' + $lvl, + $exclIsNumber = 'exclIsNumber' + $lvl, + $opExpr = 'op' + $lvl, + $opStr = '\' + ' + $opExpr + ' + \''; + out += ' var schemaExcl' + ($lvl) + ' = ' + ($schemaValueExcl) + '; '; + $schemaValueExcl = 'schemaExcl' + $lvl; + out += ' var ' + ($exclusive) + '; var ' + ($exclType) + ' = typeof ' + ($schemaValueExcl) + '; if (' + ($exclType) + ' != \'boolean\' && ' + ($exclType) + ' != \'undefined\' && ' + ($exclType) + ' != \'number\') { '; + var $errorKeyword = $exclusiveKeyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_exclusiveLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'' + ($exclusiveKeyword) + ' should be boolean\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' ' + ($exclType) + ' == \'number\' ? ( (' + ($exclusive) + ' = ' + ($schemaValue) + ' === undefined || ' + ($schemaValueExcl) + ' ' + ($op) + '= ' + ($schemaValue) + ') ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaValueExcl) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) : ( (' + ($exclusive) + ' = ' + ($schemaValueExcl) + ' === true) ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaValue) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) || ' + ($data) + ' !== ' + ($data) + ') { var op' + ($lvl) + ' = ' + ($exclusive) + ' ? \'' + ($op) + '\' : \'' + ($op) + '=\'; '; + if ($schema === undefined) { + $errorKeyword = $exclusiveKeyword; + $errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword; + $schemaValue = $schemaValueExcl; + $isData = $isDataExcl; + } + } else { + var $exclIsNumber = typeof $schemaExcl == 'number', + $opStr = $op; + if ($exclIsNumber && $isData) { + var $opExpr = '\'' + $opStr + '\''; + out += ' if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' ( ' + ($schemaValue) + ' === undefined || ' + ($schemaExcl) + ' ' + ($op) + '= ' + ($schemaValue) + ' ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaExcl) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) || ' + ($data) + ' !== ' + ($data) + ') { '; + } else { + if ($exclIsNumber && $schema === undefined) { + $exclusive = true; + $errorKeyword = $exclusiveKeyword; + $errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword; + $schemaValue = $schemaExcl; + $notOp += '='; + } else { + if ($exclIsNumber) $schemaValue = Math[$isMax ? 'min' : 'max']($schemaExcl, $schema); + if ($schemaExcl === ($exclIsNumber ? $schemaValue : true)) { + $exclusive = true; + $errorKeyword = $exclusiveKeyword; + $errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword; + $notOp += '='; + } else { + $exclusive = false; + $opStr += '='; + } + } + var $opExpr = '\'' + $opStr + '\''; + out += ' if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' || ' + ($data) + ' !== ' + ($data) + ') { '; + } + } + $errorKeyword = $errorKeyword || $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { comparison: ' + ($opExpr) + ', limit: ' + ($schemaValue) + ', exclusive: ' + ($exclusive) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should be ' + ($opStr) + ' '; + if ($isData) { + out += '\' + ' + ($schemaValue); + } else { + out += '' + ($schemaValue) + '\''; + } + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else { '; + } + return out; +} + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate__limitItems(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $op = $keyword == 'maxItems' ? '>' : '<'; + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' ' + ($data) + '.length ' + ($op) + ' ' + ($schemaValue) + ') { '; + var $errorKeyword = $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limitItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have '; + if ($keyword == 'maxItems') { + out += 'more'; + } else { + out += 'less'; + } + out += ' than '; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + ($schema); + } + out += ' items\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; +} + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate__limitLength(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $op = $keyword == 'maxLength' ? '>' : '<'; + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + if (it.opts.unicode === false) { + out += ' ' + ($data) + '.length '; + } else { + out += ' ucs2length(' + ($data) + ') '; + } + out += ' ' + ($op) + ' ' + ($schemaValue) + ') { '; + var $errorKeyword = $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limitLength') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT be '; + if ($keyword == 'maxLength') { + out += 'longer'; + } else { + out += 'shorter'; + } + out += ' than '; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + ($schema); + } + out += ' characters\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; +} + + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate__limitProperties(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $op = $keyword == 'maxProperties' ? '>' : '<'; + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || '; + } + out += ' Object.keys(' + ($data) + ').length ' + ($op) + ' ' + ($schemaValue) + ') { '; + var $errorKeyword = $keyword; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || '_limitProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have '; + if ($keyword == 'maxProperties') { + out += 'more'; + } else { + out += 'less'; + } + out += ' than '; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + ($schema); + } + out += ' properties\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; +} + + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate_validate(it, $keyword, $ruleType) { + var out = ''; + var $async = it.schema.$async === true, + $refKeywords = it.util.schemaHasRulesExcept(it.schema, it.RULES.all, '$ref'), + $id = it.self._getId(it.schema); + if (it.isTop) { + out += ' var validate = '; + if ($async) { + it.async = true; + out += 'async '; + } + out += 'function(data, dataPath, parentData, parentDataProperty, rootData) { \'use strict\'; '; + if ($id && (it.opts.sourceCode || it.opts.processCode)) { + out += ' ' + ('/\*# sourceURL=' + $id + ' */') + ' '; + } + } + if (typeof it.schema == 'boolean' || !($refKeywords || it.schema.$ref)) { + var $keyword = 'false schema'; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $errorKeyword; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + if (it.schema === false) { + if (it.isTop) { + $breakOnError = true; + } else { + out += ' var ' + ($valid) + ' = false; '; + } + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'false schema') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'boolean schema is false\' '; + } + if (it.opts.verbose) { + out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + } else { + if (it.isTop) { + if ($async) { + out += ' return data; '; + } else { + out += ' validate.errors = null; return true; '; + } + } else { + out += ' var ' + ($valid) + ' = true; '; + } + } + if (it.isTop) { + out += ' }; return validate; '; + } + return out; + } + if (it.isTop) { + var $top = it.isTop, + $lvl = it.level = 0, + $dataLvl = it.dataLevel = 0, + $data = 'data'; + it.rootId = it.resolve.fullPath(it.self._getId(it.root.schema)); + it.baseId = it.baseId || it.rootId; + delete it.isTop; + it.dataPathArr = [undefined]; + out += ' var vErrors = null; '; + out += ' var errors = 0; '; + out += ' if (rootData === undefined) rootData = data; '; + } else { + var $lvl = it.level, + $dataLvl = it.dataLevel, + $data = 'data' + ($dataLvl || ''); + if ($id) it.baseId = it.resolve.url(it.baseId, $id); + if ($async && !it.async) throw new Error('async schema in sync schema'); + out += ' var errs_' + ($lvl) + ' = errors;'; + } + var $valid = 'valid' + $lvl, + $breakOnError = !it.opts.allErrors, + $closingBraces1 = '', + $closingBraces2 = ''; + var $errorKeyword; + var $typeSchema = it.schema.type, + $typeIsArray = Array.isArray($typeSchema); + if ($typeIsArray && $typeSchema.length == 1) { + $typeSchema = $typeSchema[0]; + $typeIsArray = false; + } + if (it.schema.$ref && $refKeywords) { + if (it.opts.extendRefs == 'fail') { + throw new Error('$ref: validation keywords used in schema at path "' + it.errSchemaPath + '" (see option extendRefs)'); + } else if (it.opts.extendRefs !== true) { + $refKeywords = false; + it.logger.warn('$ref: keywords ignored in schema at path "' + it.errSchemaPath + '"'); + } + } + if (it.schema.$comment && it.opts.$comment) { + out += ' ' + (it.RULES.all.$comment.code(it, '$comment')); + } + if ($typeSchema) { + if (it.opts.coerceTypes) { + var $coerceToTypes = it.util.coerceToTypes(it.opts.coerceTypes, $typeSchema); + } + var $rulesGroup = it.RULES.types[$typeSchema]; + if ($coerceToTypes || $typeIsArray || $rulesGroup === true || ($rulesGroup && !$shouldUseGroup($rulesGroup))) { + var $schemaPath = it.schemaPath + '.type', + $errSchemaPath = it.errSchemaPath + '/type'; + var $schemaPath = it.schemaPath + '.type', + $errSchemaPath = it.errSchemaPath + '/type', + $method = $typeIsArray ? 'checkDataTypes' : 'checkDataType'; + out += ' if (' + (it.util[$method]($typeSchema, $data, true)) + ') { '; + if ($coerceToTypes) { + var $dataType = 'dataType' + $lvl, + $coerced = 'coerced' + $lvl; + out += ' var ' + ($dataType) + ' = typeof ' + ($data) + '; '; + if (it.opts.coerceTypes == 'array') { + out += ' if (' + ($dataType) + ' == \'object\' && Array.isArray(' + ($data) + ')) ' + ($dataType) + ' = \'array\'; '; + } + out += ' var ' + ($coerced) + ' = undefined; '; + var $bracesCoercion = ''; + var arr1 = $coerceToTypes; + if (arr1) { + var $type, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $type = arr1[$i += 1]; + if ($i) { + out += ' if (' + ($coerced) + ' === undefined) { '; + $bracesCoercion += '}'; + } + if (it.opts.coerceTypes == 'array' && $type != 'array') { + out += ' if (' + ($dataType) + ' == \'array\' && ' + ($data) + '.length == 1) { ' + ($coerced) + ' = ' + ($data) + ' = ' + ($data) + '[0]; ' + ($dataType) + ' = typeof ' + ($data) + '; } '; + } + if ($type == 'string') { + out += ' if (' + ($dataType) + ' == \'number\' || ' + ($dataType) + ' == \'boolean\') ' + ($coerced) + ' = \'\' + ' + ($data) + '; else if (' + ($data) + ' === null) ' + ($coerced) + ' = \'\'; '; + } else if ($type == 'number' || $type == 'integer') { + out += ' if (' + ($dataType) + ' == \'boolean\' || ' + ($data) + ' === null || (' + ($dataType) + ' == \'string\' && ' + ($data) + ' && ' + ($data) + ' == +' + ($data) + ' '; + if ($type == 'integer') { + out += ' && !(' + ($data) + ' % 1)'; + } + out += ')) ' + ($coerced) + ' = +' + ($data) + '; '; + } else if ($type == 'boolean') { + out += ' if (' + ($data) + ' === \'false\' || ' + ($data) + ' === 0 || ' + ($data) + ' === null) ' + ($coerced) + ' = false; else if (' + ($data) + ' === \'true\' || ' + ($data) + ' === 1) ' + ($coerced) + ' = true; '; + } else if ($type == 'null') { + out += ' if (' + ($data) + ' === \'\' || ' + ($data) + ' === 0 || ' + ($data) + ' === false) ' + ($coerced) + ' = null; '; + } else if (it.opts.coerceTypes == 'array' && $type == 'array') { + out += ' if (' + ($dataType) + ' == \'string\' || ' + ($dataType) + ' == \'number\' || ' + ($dataType) + ' == \'boolean\' || ' + ($data) + ' == null) ' + ($coerced) + ' = [' + ($data) + ']; '; + } + } + } + out += ' ' + ($bracesCoercion) + ' if (' + ($coerced) + ' === undefined) { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \''; + if ($typeIsArray) { + out += '' + ($typeSchema.join(",")); + } else { + out += '' + ($typeSchema); + } + out += '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should be '; + if ($typeIsArray) { + out += '' + ($typeSchema.join(",")); + } else { + out += '' + ($typeSchema); + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else { '; + var $parentData = $dataLvl ? 'data' + (($dataLvl - 1) || '') : 'parentData', + $parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty'; + out += ' ' + ($data) + ' = ' + ($coerced) + '; '; + if (!$dataLvl) { + out += 'if (' + ($parentData) + ' !== undefined)'; + } + out += ' ' + ($parentData) + '[' + ($parentDataProperty) + '] = ' + ($coerced) + '; } '; + } else { + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \''; + if ($typeIsArray) { + out += '' + ($typeSchema.join(",")); + } else { + out += '' + ($typeSchema); + } + out += '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should be '; + if ($typeIsArray) { + out += '' + ($typeSchema.join(",")); + } else { + out += '' + ($typeSchema); + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + } + out += ' } '; + } + } + if (it.schema.$ref && !$refKeywords) { + out += ' ' + (it.RULES.all.$ref.code(it, '$ref')) + ' '; + if ($breakOnError) { + out += ' } if (errors === '; + if ($top) { + out += '0'; + } else { + out += 'errs_' + ($lvl); + } + out += ') { '; + $closingBraces2 += '}'; + } + } else { + var arr2 = it.RULES; + if (arr2) { + var $rulesGroup, i2 = -1, + l2 = arr2.length - 1; + while (i2 < l2) { + $rulesGroup = arr2[i2 += 1]; + if ($shouldUseGroup($rulesGroup)) { + if ($rulesGroup.type) { + out += ' if (' + (it.util.checkDataType($rulesGroup.type, $data)) + ') { '; + } + if (it.opts.useDefaults && !it.compositeRule) { + if ($rulesGroup.type == 'object' && it.schema.properties) { + var $schema = it.schema.properties, + $schemaKeys = Object.keys($schema); + var arr3 = $schemaKeys; + if (arr3) { + var $propertyKey, i3 = -1, + l3 = arr3.length - 1; + while (i3 < l3) { + $propertyKey = arr3[i3 += 1]; + var $sch = $schema[$propertyKey]; + if ($sch.default !== undefined) { + var $passData = $data + it.util.getProperty($propertyKey); + out += ' if (' + ($passData) + ' === undefined) ' + ($passData) + ' = '; + if (it.opts.useDefaults == 'shared') { + out += ' ' + (it.useDefault($sch.default)) + ' '; + } else { + out += ' ' + (JSON.stringify($sch.default)) + ' '; + } + out += '; '; + } + } + } + } else if ($rulesGroup.type == 'array' && Array.isArray(it.schema.items)) { + var arr4 = it.schema.items; + if (arr4) { + var $sch, $i = -1, + l4 = arr4.length - 1; + while ($i < l4) { + $sch = arr4[$i += 1]; + if ($sch.default !== undefined) { + var $passData = $data + '[' + $i + ']'; + out += ' if (' + ($passData) + ' === undefined) ' + ($passData) + ' = '; + if (it.opts.useDefaults == 'shared') { + out += ' ' + (it.useDefault($sch.default)) + ' '; + } else { + out += ' ' + (JSON.stringify($sch.default)) + ' '; + } + out += '; '; + } + } + } + } + } + var arr5 = $rulesGroup.rules; + if (arr5) { + var $rule, i5 = -1, + l5 = arr5.length - 1; + while (i5 < l5) { + $rule = arr5[i5 += 1]; + if ($shouldUseRule($rule)) { + var $code = $rule.code(it, $rule.keyword, $rulesGroup.type); + if ($code) { + out += ' ' + ($code) + ' '; + if ($breakOnError) { + $closingBraces1 += '}'; + } + } + } + } + } + if ($breakOnError) { + out += ' ' + ($closingBraces1) + ' '; + $closingBraces1 = ''; + } + if ($rulesGroup.type) { + out += ' } '; + if ($typeSchema && $typeSchema === $rulesGroup.type && !$coerceToTypes) { + out += ' else { '; + var $schemaPath = it.schemaPath + '.type', + $errSchemaPath = it.errSchemaPath + '/type'; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \''; + if ($typeIsArray) { + out += '' + ($typeSchema.join(",")); + } else { + out += '' + ($typeSchema); + } + out += '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should be '; + if ($typeIsArray) { + out += '' + ($typeSchema.join(",")); + } else { + out += '' + ($typeSchema); + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + } + } + if ($breakOnError) { + out += ' if (errors === '; + if ($top) { + out += '0'; + } else { + out += 'errs_' + ($lvl); + } + out += ') { '; + $closingBraces2 += '}'; + } + } + } + } + } + if ($breakOnError) { + out += ' ' + ($closingBraces2) + ' '; + } + if ($top) { + if ($async) { + out += ' if (errors === 0) return data; '; + out += ' else throw new ValidationError(vErrors); '; + } else { + out += ' validate.errors = vErrors; '; + out += ' return errors === 0; '; + } + out += ' }; return validate;'; + } else { + out += ' var ' + ($valid) + ' = errors === errs_' + ($lvl) + ';'; + } + out = it.util.cleanUpCode(out); + if ($top) { + out = it.util.finalCleanUpCode(out, $async); + } + + function $shouldUseGroup($rulesGroup) { + var rules = $rulesGroup.rules; + for (var i = 0; i < rules.length; i++) + if ($shouldUseRule(rules[i])) return true; + } + + function $shouldUseRule($rule) { + return it.schema[$rule.keyword] !== undefined || ($rule.implements && $ruleImplementsSomeKeyword($rule)); + } + + function $ruleImplementsSomeKeyword($rule) { + var impl = $rule.implements; + for (var i = 0; i < impl.length; i++) + if (it.schema[impl[i]] !== undefined) return true; + } + return out; +} + + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = function (data, opts) { + if (!opts) opts = {}; + if (typeof opts === 'function') opts = { cmp: opts }; + var cycles = (typeof opts.cycles === 'boolean') ? opts.cycles : false; + + var cmp = opts.cmp && (function (f) { + return function (node) { + return function (a, b) { + var aobj = { key: a, value: node[a] }; + var bobj = { key: b, value: node[b] }; + return f(aobj, bobj); + }; + }; + })(opts.cmp); + + var seen = []; + return (function stringify (node) { + if (node && node.toJSON && typeof node.toJSON === 'function') { + node = node.toJSON(); + } + + if (node === undefined) return; + if (typeof node == 'number') return isFinite(node) ? '' + node : 'null'; + if (typeof node !== 'object') return JSON.stringify(node); + + var i, out; + if (Array.isArray(node)) { + out = '['; + for (i = 0; i < node.length; i++) { + if (i) out += ','; + out += stringify(node[i]) || 'null'; + } + return out + ']'; + } + + if (node === null) return 'null'; + + if (seen.indexOf(node) !== -1) { + if (cycles) return JSON.stringify('__cycle__'); + throw new TypeError('Converting circular structure to JSON'); + } + + var seenIndex = seen.push(node) - 1; + var keys = Object.keys(node).sort(cmp && cmp(node)); + out = ''; + for (i = 0; i < keys.length; i++) { + var key = keys[i]; + var value = stringify(node[key]); + + if (!value) continue; + if (out) out += ','; + out += JSON.stringify(key) + ':' + value; + } + seen.splice(seenIndex, 1); + return '{' + out + '}'; + })(data); +}; + + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/punycode v1.4.1 by @mathias */ +;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw new RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.4.1', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + true + ) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { + return punycode; + }.call(exports, __webpack_require__, exports, module), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { + // in Node.js, io.js, or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { + // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { + // in Rhino or a web browser + root.punycode = punycode; + } + +}(this)); + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(70)(module), __webpack_require__(18))) + +/***/ }), +/* 16 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = buildExps; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__util__ = __webpack_require__(6); + +function buildExps(isIRI) { + const ALPHA$$ = "[A-Za-z]", CR$ = "[\\x0D]", DIGIT$$ = "[0-9]", DQUOTE$$ = "[\\x22]", HEXDIG$$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])(DIGIT$$, "[A-Fa-f]"), //case-insensitive + LF$$ = "[\\x0A]", SP$$ = "[\\x20]", PCT_ENCODED$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("%[EFef]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("%[89A-Fa-f]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("%" + HEXDIG$$ + HEXDIG$$)), //expanded + GEN_DELIMS$$ = "[\\:\\/\\?\\#\\[\\]\\@]", SUB_DELIMS$$ = "[\\!\\$\\&\\'\\(\\)\\*\\+\\,\\;\\=]", RESERVED$$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])(GEN_DELIMS$$, SUB_DELIMS$$), UCSCHAR$$ = isIRI ? "[\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]" : "[]", //subset, excludes bidi control characters + IPRIVATE$$ = isIRI ? "[\\uE000-\\uF8FF]" : "[]", //subset + UNRESERVED$$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])(ALPHA$$, DIGIT$$, "[\\-\\.\\_\\~]", UCSCHAR$$), SCHEME$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(ALPHA$$ + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])(ALPHA$$, DIGIT$$, "[\\+\\-\\.]") + "*"), USERINFO$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(PCT_ENCODED$ + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])(UNRESERVED$$, SUB_DELIMS$$, "[\\:]")) + "*"), DEC_OCTET$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("25[0-5]") + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("2[0-4]" + DIGIT$$) + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("1" + DIGIT$$ + DIGIT$$) + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("[1-9]" + DIGIT$$) + "|" + DIGIT$$), DEC_OCTET_RELAXED$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("25[0-5]") + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("2[0-4]" + DIGIT$$) + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("1" + DIGIT$$ + DIGIT$$) + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("0?[1-9]" + DIGIT$$) + "|0?0?" + DIGIT$$), //relaxed parsing rules + IPV4ADDRESS$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$ + "\\." + DEC_OCTET_RELAXED$), H16$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(HEXDIG$$ + "{1,4}"), LS32$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:" + H16$) + "|" + IPV4ADDRESS$), IPV6ADDRESS1$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:") + "{6}" + LS32$), // 6( h16 ":" ) ls32 + IPV6ADDRESS2$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\:\\:" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:") + "{5}" + LS32$), // "::" 5( h16 ":" ) ls32 + IPV6ADDRESS3$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$) + "?\\:\\:" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:") + "{4}" + LS32$), //[ h16 ] "::" 4( h16 ":" ) ls32 + IPV6ADDRESS4$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:") + "{0,1}" + H16$) + "?\\:\\:" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:") + "{3}" + LS32$), //[ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 + IPV6ADDRESS5$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:") + "{0,2}" + H16$) + "?\\:\\:" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:") + "{2}" + LS32$), //[ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 + IPV6ADDRESS6$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:") + "{0,3}" + H16$) + "?\\:\\:" + H16$ + "\\:" + LS32$), //[ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 + IPV6ADDRESS7$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:") + "{0,4}" + H16$) + "?\\:\\:" + LS32$), //[ *4( h16 ":" ) h16 ] "::" ls32 + IPV6ADDRESS8$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:") + "{0,5}" + H16$) + "?\\:\\:" + H16$), //[ *5( h16 ":" ) h16 ] "::" h16 + IPV6ADDRESS9$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(H16$ + "\\:") + "{0,6}" + H16$) + "?\\:\\:"), //[ *6( h16 ":" ) h16 ] "::" + IPV6ADDRESS$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])([IPV6ADDRESS1$, IPV6ADDRESS2$, IPV6ADDRESS3$, IPV6ADDRESS4$, IPV6ADDRESS5$, IPV6ADDRESS6$, IPV6ADDRESS7$, IPV6ADDRESS8$, IPV6ADDRESS9$].join("|")), ZONEID$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(UNRESERVED$$ + "|" + PCT_ENCODED$) + "+"), //RFC 6874 + IPV6ADDRZ$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(IPV6ADDRESS$ + "\\%25" + ZONEID$), //RFC 6874 + IPV6ADDRZ_RELAXED$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(IPV6ADDRESS$ + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\%25|\\%(?!" + HEXDIG$$ + "{2})") + ZONEID$), //RFC 6874, with relaxed parsing rules + IPVFUTURE$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("[vV]" + HEXDIG$$ + "+\\." + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])(UNRESERVED$$, SUB_DELIMS$$, "[\\:]") + "+"), IP_LITERAL$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\[" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(IPV6ADDRZ_RELAXED$ + "|" + IPV6ADDRESS$ + "|" + IPVFUTURE$) + "\\]"), //RFC 6874 + REG_NAME$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(PCT_ENCODED$ + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])(UNRESERVED$$, SUB_DELIMS$$)) + "*"), HOST$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(IP_LITERAL$ + "|" + IPV4ADDRESS$ + "(?!" + REG_NAME$ + ")" + "|" + REG_NAME$), PORT$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(DIGIT$$ + "*"), AUTHORITY$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(USERINFO$ + "@") + "?" + HOST$ + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\:" + PORT$) + "?"), PCHAR$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(PCT_ENCODED$ + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])(UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@]")), SEGMENT$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(PCHAR$ + "*"), SEGMENT_NZ$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(PCHAR$ + "+"), SEGMENT_NZ_NC$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(PCT_ENCODED$ + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])(UNRESERVED$$, SUB_DELIMS$$, "[\\@]")) + "+"), PATH_ABEMPTY$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\/" + SEGMENT$) + "*"), PATH_ABSOLUTE$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\/" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(SEGMENT_NZ$ + PATH_ABEMPTY$) + "?"), //simplified + PATH_NOSCHEME$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(SEGMENT_NZ_NC$ + PATH_ABEMPTY$), //simplified + PATH_ROOTLESS$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(SEGMENT_NZ$ + PATH_ABEMPTY$), //simplified + PATH_EMPTY$ = "(?!" + PCHAR$ + ")", PATH$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$), QUERY$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(PCHAR$ + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])("[\\/\\?]", IPRIVATE$$)) + "*"), FRAGMENT$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(PCHAR$ + "|[\\/\\?]") + "*"), HIER_PART$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\/\\/" + AUTHORITY$ + PATH_ABEMPTY$) + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$), URI$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(SCHEME$ + "\\:" + HIER_PART$ + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\?" + QUERY$) + "?" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\#" + FRAGMENT$) + "?"), RELATIVE_PART$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\/\\/" + AUTHORITY$ + PATH_ABEMPTY$) + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_EMPTY$), RELATIVE$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(RELATIVE_PART$ + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\?" + QUERY$) + "?" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\#" + FRAGMENT$) + "?"), URI_REFERENCE$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(URI$ + "|" + RELATIVE$), ABSOLUTE_URI$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(SCHEME$ + "\\:" + HIER_PART$ + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\?" + QUERY$) + "?"), GENERIC_REF$ = "^(" + SCHEME$ + ")\\:" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\/\\/(" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")") + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\?(" + QUERY$ + ")") + "?" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\#(" + FRAGMENT$ + ")") + "?$", RELATIVE_REF$ = "^(){0}" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\/\\/(" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_EMPTY$ + ")") + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\?(" + QUERY$ + ")") + "?" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\#(" + FRAGMENT$ + ")") + "?$", ABSOLUTE_REF$ = "^(" + SCHEME$ + ")\\:" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\/\\/(" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")") + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\?(" + QUERY$ + ")") + "?$", SAMEDOC_REF$ = "^" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\#(" + FRAGMENT$ + ")") + "?$", AUTHORITY_REF$ = "^" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\:(" + PORT$ + ")") + "?$"; + return { + NOT_SCHEME: new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])("[^]", ALPHA$$, DIGIT$$, "[\\+\\-\\.]"), "g"), + NOT_USERINFO: new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])("[^\\%\\:]", UNRESERVED$$, SUB_DELIMS$$), "g"), + NOT_HOST: new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])("[^\\%\\[\\]\\:]", UNRESERVED$$, SUB_DELIMS$$), "g"), + NOT_PATH: new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])("[^\\%\\/\\:\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"), + NOT_PATH_NOSCHEME: new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])("[^\\%\\/\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"), + NOT_QUERY: new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])("[^\\%]", UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@\\/\\?]", IPRIVATE$$), "g"), + NOT_FRAGMENT: new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])("[^\\%]", UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@\\/\\?]"), "g"), + ESCAPE: new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])("[^]", UNRESERVED$$, SUB_DELIMS$$), "g"), + UNRESERVED: new RegExp(UNRESERVED$$, "g"), + OTHER_CHARS: new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["d" /* merge */])("[^\\%]", UNRESERVED$$, RESERVED$$), "g"), + PCT_ENCODED: new RegExp(PCT_ENCODED$, "g"), + IPV4ADDRESS: new RegExp("^(" + IPV4ADDRESS$ + ")$"), + IPV6ADDRESS: new RegExp("^\\[?(" + IPV6ADDRESS$ + ")" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__util__["e" /* subexp */])("\\%25|\\%(?!" + HEXDIG$$ + "{2})") + "(" + ZONEID$ + ")") + "?\\]?$") //RFC 6874, with relaxed parsing rules + }; +} +/* harmony default export */ __webpack_exports__["a"] = (buildExps(false)); +//# sourceMappingURL=regexps-uri.js.map + +/***/ }), +/* 17 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +const handler = { + scheme: "http", + domainHost: true, + parse: function (components, options) { + //report missing host + if (!components.host) { + components.error = components.error || "HTTP URIs must have a host."; + } + return components; + }, + serialize: function (components, options) { + //normalize the default port + if (components.port === (String(components.scheme).toLowerCase() !== "https" ? 80 : 443) || components.port === "") { + components.port = undefined; + } + //normalize the empty path + if (!components.path) { + components.path = "/"; + } + //NOTE: We do not parse query strings for HTTP URIs + //as WWW Form Url Encoded query strings are part of the HTML4+ spec, + //and not the HTTP spec. + return components; + } +}; +/* harmony default export */ __webpack_exports__["a"] = (handler); +//# sourceMappingURL=http.js.map + +/***/ }), +/* 18 */ +/***/ (function(module, exports) { + +var g; + +// This works in non-strict mode +g = (function() { + return this; +})(); + +try { + // This works if eval is allowed (see CSP) + g = g || Function("return this")() || (1,eval)("this"); +} catch(e) { + // This works if the window reference is available + if(typeof window === "object") + g = window; +} + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + +module.exports = g; + + +/***/ }), +/* 19 */ +/***/ (function(module, exports) { + +/* eslint-env commonjs */ + +/** + * Calculate the size of a ping. + * + * @param {Object} payload + * The data payload of the ping. + * + * @returns {Number} + * The total size of the ping. + */ +function getPingSize(payload) { + const converter = Cc[ + "@mozilla.org/intl/scriptableunicodeconverter" + ].createInstance(Ci.nsIScriptableUnicodeConverter); + converter.charset = "UTF-8"; + let utf8Payload = converter.ConvertFromUnicode(JSON.stringify(payload)); + utf8Payload += converter.Finish(); + return utf8Payload.length; +} + +module.exports = { + getPingSize, +}; + + +/***/ }), +/* 20 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__logger__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__telemetryPipelines_shield__ = __webpack_require__(76); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__telemetryPipelines_pioneer__ = __webpack_require__(74); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__jsonschema__ = __webpack_require__(73); +/* eslint no-console: ["warn", { allow: ["info", "warn", "error"] }] */ +/* eslint-env commonjs */ + + + + + + + +const UTILS_VERSION = __webpack_require__(71).version; +const PACKET_VERSION = 3; + +const { Services } = ChromeUtils.import( + "resource://gre/modules/Services.jsm", + {}, +); +const { ExtensionUtils } = ChromeUtils.import( + "resource://gre/modules/ExtensionUtils.jsm", + {}, +); +/* eslint-disable no-undef */ +const { ExtensionError } = ExtensionUtils; + +Cu.importGlobalProperties(["URL", "crypto", "URLSearchParams"]); + +/** + * Telemetry Probe JSON schema validation (via AJV at runtime) + * + * Schemas here are used for: + * - Telemetry (Ensure correct Parquet format for different types of + * outbound packets): + * - "shield-study": shield study state and outcome data common to all + * shield studies. + * - "shield-study-addon": addon-specific probe data, with `attributes` + * (used to capture feature-specific state) sent as Map(string,string). + * - "shield-study-error": data used to notify, group and count some kinds + * of errors from shield studies + */ +const schemas = { + // Telemetry PingType schemas + "shield-study": __webpack_require__(63), // eslint-disable-line max-len + "shield-study-addon": __webpack_require__(61), // eslint-disable-line max-len + "shield-study-error": __webpack_require__(62), // eslint-disable-line max-len +}; + + +/** Simple spread/rest based merge, using Object.assign. + * + * Right-most overrides, top level only, by full value replacement. + * + * Note: Unlike deep merges might not handle symbols and other things. + * + * @param {...Object} sources - 1 or more sources + * @returns {Object} - the resulting merged object + */ +function merge(...sources) { + return Object.assign({}, ...sources); +} + +/** + * Appends a query string to a url. + * @param {string} url - a base url to append; must be static (data) or external + * @param {Object} args - query arguments, one or more object literal used to + * build a query string + * + * @returns {string} - an absolute url appended with a query string + */ +function mergeQueryArgs(url, ...args) { + const U = new URL(url); + // get the query string already attached to url, if it exists + let q = U.search || "?"; + // create an interface to interact with the query string + q = new URLSearchParams(q); + const merged = merge({}, ...args); + // Set each search parameter in "merged" to its value in the query string, + // building up the query string one search parameter at a time. + Object.keys(merged).forEach(k => { + q.set(k, merged[k]); + }); + // append our new query string to the URL object made with "url" + U.search = q.toString(); + // return the full url, with the appended query string + return U.toString(); +} + +/** + * Class representing utilities singleton for shield studies. + */ +class StudyUtils { + /** + * Create a StudyUtils instance to power the `browser.study` API + * + * - `this._extensionManifest`: mirrors the extensionManifest at the time of api creation + * - `this.seenTelemetry`: array of seen telemetry. Fully populated only if this.recordSeenTelemetry is true + */ + constructor() { + // expose schemas + this.schemas = schemas; + + // expose jsonschema validation methods + this.jsonschema = __WEBPACK_IMPORTED_MODULE_3__jsonschema__["a" /* default */]; + + this._extensionManifest = {}; + this.telemetryPipelineHandler = null; + this.recordSeenTelemetry = false; + this.seenTelemetry = []; + } + + setExtensionManifest(extensionManifest) { + this._extensionManifest = extensionManifest; + } + + /** + * @param {string} telemetryPipeline - the telemetry pipeline + * @returns {Object} The instance of the appropriate handler class + */ + getTelemetryPipelineHandler(telemetryPipeline) { + if (!this.telemetryPipelineHandler) { + // Different telemetry pipelines treat data and configuration differently + switch (telemetryPipeline) { + case "shield": + this.telemetryPipelineHandler = new __WEBPACK_IMPORTED_MODULE_1__telemetryPipelines_shield__["a" /* default */](this); + break; + case "pioneer": + this.telemetryPipelineHandler = new __WEBPACK_IMPORTED_MODULE_2__telemetryPipelines_pioneer__["a" /* default */](this); + break; + default: + throw new ExtensionError( + `Unknown telemetryPipeline: "${telemetryPipeline}"`, + ); + } + } + return this.telemetryPipelineHandler; + } + + /** + * Gets the telemetry client ID for the user. + * @param {string} telemetryPipeline - the telemetry pipeline + * @returns {string} - the telemetry client ID + */ + async getTelemetryId(telemetryPipeline) { + return this.getTelemetryPipelineHandler(telemetryPipeline).getTelemetryId(); + } + + /** + * Gets the Shield recipe client ID. + * @returns {string} - the Shield recipe client ID. + */ + getShieldId() { + const key = "extensions.shield-recipe-client.user_id"; + return Services.prefs.getStringPref(key, ""); + } + + async fullSurveyUrl({ surveyBaseUrl, reason, telemetryPipeline }) { + const study = this._extensionManifest.applications.gecko.id; + const variation = this._extensionManifest.applications.gecko.id; + const queryArgs = await this.endingQueryArgs({ + telemetryPipeline, + study, + variation, + }); + queryArgs.reason = reason; + queryArgs.fullreason = reason; + return mergeQueryArgs(surveyBaseUrl, queryArgs); + } + + /** + * Builds an object whose properties are query arguments that can be + * appended to a study ending url + * @returns {Object} - the query arguments for the study + */ + async endingQueryArgs({ telemetryPipeline, study, variation }) { + try { + const who = await this.getTelemetryId(telemetryPipeline); + const queryArgs = { + shield: PACKET_VERSION, + study, + variation, + updateChannel: Services.appinfo.defaultUpdateChannel, + fxVersion: Services.appinfo.version, + addon: this._extensionManifest.version, // addon version + who, // telemetry clientId + }; + queryArgs.testing = "-1"; // Currently unconfigurable but surveygizmo-expected parameter - filling with "-1" as placeholder + return queryArgs; + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } + } + + /** + * Validates and submits telemetry pings from StudyUtils. + * @param {Object} data - the data to send as part of the telemetry packet + * @param {string} bucket - the type of telemetry packet to be sent + * @param {string} telemetryPipeline - the telemetry pipeline + * @returns {Promise|boolean} - A promise that resolves with the ping id + * once the ping is stored or sent, or false if + * - there is a validation error, + * - the packet is of type "shield-study-error" + * - the study's telemetryConfig.send is set to false + */ + async _telemetry(data, { bucket, telemetryPipeline }) { + try { + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug(`telemetry in: ${bucket} ${JSON.stringify(data)}`); + + const study_name = this._extensionManifest.applications.gecko.id; + const branch = this._extensionManifest.applications.gecko.id; + const testing = false; // Currently unconfigurable schema-expected parameter - defaulting to false + const payload = { + version: PACKET_VERSION, + study_name, + branch, + addon_version: this._extensionManifest.version, + shield_version: UTILS_VERSION, + type: bucket, + data, + testing, + }; + + let validation; + try { + validation = __WEBPACK_IMPORTED_MODULE_3__jsonschema__["a" /* default */].validate(payload, schemas[bucket]); + } catch (err) { + // Catch failures of unknown origin (could be library, add-on, system...) + // if validation broke, GIVE UP. + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].error(err); + return false; + } + /* + * Handle validation errors by sending a "shield-study-error" + * telemetry ping with the error report. + * If the invalid payload is itself of type "shield-study-error", + * throw an error (to avoid a possible infinite loop). + */ + if (validation.errors.length) { + const errorReport = { + error_id: "jsonschema-validation", + error_source: "addon", + severity: "fatal", + message: JSON.stringify(validation.errors), + }; + if (bucket === "shield-study-error") { + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].warn("cannot validate shield-study-error", data, bucket); + return false; // just die, maybe should have a super escape hatch? + } + return this.telemetryError(errorReport, telemetryPipeline); + } + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug(`telemetry: ${JSON.stringify(payload)}`); + + const pingId = await this.getTelemetryPipelineHandler( + telemetryPipeline, + ).sendTelemetry(bucket, payload); + + // Store a copy of the ping if it's a shield-study or error ping, which are few in number, or if we have activated the internal telemetry archive configuration + if ( + bucket === "shield-study" || + bucket === "shield-study-error" || + this.recordSeenTelemetry + ) { + this.seenTelemetry.push({ id: pingId, payload }); + } + + return pingId; + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } + } + + /** + * Validates and submits telemetry pings from the add-on; mostly from + * webExtension messages. + * @param {Object} payload - the data to send as part of the telemetry packet + * @param {string} telemetryPipeline - the telemetry pipeline + * @returns {Promise|boolean} - see StudyUtils._telemetry + */ + async telemetry(payload, telemetryPipeline) { + try { + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug(`telemetry ${JSON.stringify(payload)}`); + const toSubmit = { + attributes: payload, + }; + return this._telemetry(toSubmit, { + telemetryPipeline, + bucket: "shield-study-addon", + }); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } + } + + /** + * Submits error report telemetry pings. + * @param {Object} errorReport - the error report, see StudyUtils._telemetry + * @param {string} telemetryPipeline - the telemetry pipeline + * @returns {Promise|boolean} - see StudyUtils._telemetry + */ + telemetryError(errorReport, telemetryPipeline) { + try { + return this._telemetry(errorReport, { + bucket: "shield-study-error", + telemetryPipeline, + }); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } + } + + /** + * Calculate Telemetry using appropriate shield or pioneer methods. + * + * shield: + * - Calculate the size of a ping + * + * pioneer: + * - Calculate the size of a ping that has Pioneer encrypted data + * + * @param {Object} payload Non-nested object with key strings, and key values + * @param {string} telemetryPipeline - the telemetry pipeline + * @returns {Promise} The total size of the ping. + */ + async calculateTelemetryPingSize(payload, telemetryPipeline) { + try { + const toSubmit = { + attributes: payload, + }; + return this.getTelemetryPipelineHandler(telemetryPipeline).getPingSize( + toSubmit, + "shield-study-addon", + ); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } + } +} + +// Actually create the singleton. +const studyUtils = new StudyUtils(); +/* harmony export (immutable) */ __webpack_exports__["a"] = studyUtils; + + + +/***/ }), +/* 21 */ +/***/ (function(module, exports) { + +/* eslint-env node */ + +// TODO, eventually remove this. It's used by the Template testing, for now. + +// TODO, making this a separate file means that we have to pass the error from the other compartment. + +/** + * Returns array of pings of type `type` in reverse sorted order by timestamp + * first element is most recent ping + * + * searchTelemetryQuery + * - type: string or array of ping types + * - n: positive integer. at most n pings. + * - timestamp: only pings after this timestamp. + * - headersOnly: boolean, just the 'headers' for the pings, not the full bodies. + * + * TODO: Fix shortcoming: + * Some pings are sent immediately after one another and it's + * original sending order is not reflected by the return of + * TelemetryArchive.promiseArchivedPingList + * Thus, we can currently only test that the last two pings are the + * correct ones but not that their order is correct + * + * + * @param {Object} TelemetryArchive from TelemetryArchive.jsm + * @param {ObjectsearchTelemetryQuery} searchTelemetryQuery See searchSentTelemetry + * + * @returns {Array} Array of found Telemetry Pings + */ +async function searchTelemetryArchive(TelemetryArchive, searchTelemetryQuery) { + let { type } = searchTelemetryQuery; + const { n, timestamp, headersOnly } = searchTelemetryQuery; + // {type, id, timestampCreated} + let pings = await TelemetryArchive.promiseArchivedPingList(); + if (type && !Array.isArray(type)) { + type = [type]; + } + if (type) pings = pings.filter(p => type.includes(p.type)); + + if (timestamp) pings = pings.filter(p => p.timestampCreated > timestamp); + + if (pings.length === 0) { + return Promise.resolve([]); + } + + pings.sort((a, b) => b.timestampCreated - a.timestampCreated); + + if (n) pings = pings.slice(0, n); + const pingData = headersOnly + ? pings + : pings.map(ping => TelemetryArchive.promiseArchivedPingById(ping.id)); + + return Promise.all(pingData); +} + +module.exports = { + searchTelemetryArchive, +}; + + +/***/ }), +/* 22 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var compileSchema = __webpack_require__(26) + , resolve = __webpack_require__(4) + , Cache = __webpack_require__(23) + , SchemaObject = __webpack_require__(8) + , stableStringify = __webpack_require__(14) + , formats = __webpack_require__(25) + , rules = __webpack_require__(27) + , $dataMetaSchema = __webpack_require__(29) + , util = __webpack_require__(0); + +module.exports = Ajv; + +Ajv.prototype.validate = validate; +Ajv.prototype.compile = compile; +Ajv.prototype.addSchema = addSchema; +Ajv.prototype.addMetaSchema = addMetaSchema; +Ajv.prototype.validateSchema = validateSchema; +Ajv.prototype.getSchema = getSchema; +Ajv.prototype.removeSchema = removeSchema; +Ajv.prototype.addFormat = addFormat; +Ajv.prototype.errorsText = errorsText; + +Ajv.prototype._addSchema = _addSchema; +Ajv.prototype._compile = _compile; + +Ajv.prototype.compileAsync = __webpack_require__(24); +var customKeyword = __webpack_require__(51); +Ajv.prototype.addKeyword = customKeyword.add; +Ajv.prototype.getKeyword = customKeyword.get; +Ajv.prototype.removeKeyword = customKeyword.remove; + +var errorClasses = __webpack_require__(3); +Ajv.ValidationError = errorClasses.Validation; +Ajv.MissingRefError = errorClasses.MissingRef; +Ajv.$dataMetaSchema = $dataMetaSchema; + +var META_SCHEMA_ID = 'http://json-schema.org/draft-07/schema'; + +var META_IGNORE_OPTIONS = [ 'removeAdditional', 'useDefaults', 'coerceTypes' ]; +var META_SUPPORT_DATA = ['/properties']; + +/** + * Creates validator instance. + * Usage: `Ajv(opts)` + * @param {Object} opts optional options + * @return {Object} ajv instance + */ +function Ajv(opts) { + if (!(this instanceof Ajv)) return new Ajv(opts); + opts = this._opts = util.copy(opts) || {}; + setLogger(this); + this._schemas = {}; + this._refs = {}; + this._fragments = {}; + this._formats = formats(opts.format); + var schemaUriFormat = this._schemaUriFormat = this._formats['uri-reference']; + this._schemaUriFormatFunc = function (str) { return schemaUriFormat.test(str); }; + + this._cache = opts.cache || new Cache; + this._loadingSchemas = {}; + this._compilations = []; + this.RULES = rules(); + this._getId = chooseGetId(opts); + + opts.loopRequired = opts.loopRequired || Infinity; + if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true; + if (opts.serialize === undefined) opts.serialize = stableStringify; + this._metaOpts = getMetaSchemaOptions(this); + + if (opts.formats) addInitialFormats(this); + addDraft6MetaSchema(this); + if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta); + addInitialSchemas(this); +} + + + +/** + * Validate data using schema + * Schema will be compiled and cached (using serialized JSON as key. [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize. + * @this Ajv + * @param {String|Object} schemaKeyRef key, ref or schema object + * @param {Any} data to be validated + * @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`). + */ +function validate(schemaKeyRef, data) { + var v; + if (typeof schemaKeyRef == 'string') { + v = this.getSchema(schemaKeyRef); + if (!v) throw new Error('no schema with key or ref "' + schemaKeyRef + '"'); + } else { + var schemaObj = this._addSchema(schemaKeyRef); + v = schemaObj.validate || this._compile(schemaObj); + } + + var valid = v(data); + if (v.$async !== true) this.errors = v.errors; + return valid; +} + + +/** + * Create validating function for passed schema. + * @this Ajv + * @param {Object} schema schema object + * @param {Boolean} _meta true if schema is a meta-schema. Used internally to compile meta schemas of custom keywords. + * @return {Function} validating function + */ +function compile(schema, _meta) { + var schemaObj = this._addSchema(schema, undefined, _meta); + return schemaObj.validate || this._compile(schemaObj); +} + + +/** + * Adds schema to the instance. + * @this Ajv + * @param {Object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored. + * @param {String} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`. + * @param {Boolean} _skipValidation true to skip schema validation. Used internally, option validateSchema should be used instead. + * @param {Boolean} _meta true if schema is a meta-schema. Used internally, addMetaSchema should be used instead. + * @return {Ajv} this for method chaining + */ +function addSchema(schema, key, _skipValidation, _meta) { + if (Array.isArray(schema)){ + for (var i=0; i} errors optional array of validation errors, if not passed errors from the instance are used. + * @param {Object} options optional options with properties `separator` and `dataVar`. + * @return {String} human readable string with all errors descriptions + */ +function errorsText(errors, options) { + errors = errors || this.errors; + if (!errors) return 'No errors'; + options = options || {}; + var separator = options.separator === undefined ? ', ' : options.separator; + var dataVar = options.dataVar === undefined ? 'data' : options.dataVar; + + var text = ''; + for (var i=0; i%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i; +// For the source: https://gist.github.com/dperini/729294 +// For test cases: https://mathiasbynens.be/demo/url-regex +// @todo Delete current URL in favour of the commented out URL rule when this issue is fixed https://github.com/eslint/eslint/issues/7983. +// var URL = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)(?:\.(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu; +var URL = /^(?:(?:http[s\u017F]?|ftp):\/\/)(?:(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+(?::(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?@)?(?:(?!10(?:\.[0-9]{1,3}){3})(?!127(?:\.[0-9]{1,3}){3})(?!169\.254(?:\.[0-9]{1,3}){2})(?!192\.168(?:\.[0-9]{1,3}){2})(?!172\.(?:1[6-9]|2[0-9]|3[01])(?:\.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:\.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:\.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)(?:\.(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)*(?:\.(?:(?:[KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){2,})))(?::[0-9]{2,5})?(?:\/(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?$/i; +var UUID = /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i; +var JSON_POINTER = /^(?:\/(?:[^~/]|~0|~1)*)*$/; +var JSON_POINTER_URI_FRAGMENT = /^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i; +var RELATIVE_JSON_POINTER = /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/; + + +module.exports = formats; + +function formats(mode) { + mode = mode == 'full' ? 'full' : 'fast'; + return util.copy(formats[mode]); +} + + +formats.fast = { + // date: http://tools.ietf.org/html/rfc3339#section-5.6 + date: /^\d\d\d\d-[0-1]\d-[0-3]\d$/, + // date-time: http://tools.ietf.org/html/rfc3339#section-5.6 + time: /^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d:\d\d)?$/i, + 'date-time': /^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i, + // uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js + uri: /^(?:[a-z][a-z0-9+-.]*:)(?:\/?\/)?[^\s]*$/i, + 'uri-reference': /^(?:(?:[a-z][a-z0-9+-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i, + 'uri-template': URITEMPLATE, + url: URL, + // email (sources from jsen validator): + // http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address#answer-8829363 + // http://www.w3.org/TR/html5/forms.html#valid-e-mail-address (search for 'willful violation') + email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i, + hostname: HOSTNAME, + // optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html + ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/, + // optimized http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses + ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i, + regex: regex, + // uuid: http://tools.ietf.org/html/rfc4122 + uuid: UUID, + // JSON-pointer: https://tools.ietf.org/html/rfc6901 + // uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A + 'json-pointer': JSON_POINTER, + 'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT, + // relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00 + 'relative-json-pointer': RELATIVE_JSON_POINTER +}; + + +formats.full = { + date: date, + time: time, + 'date-time': date_time, + uri: uri, + 'uri-reference': URIREF, + 'uri-template': URITEMPLATE, + url: URL, + email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&''*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i, + hostname: hostname, + ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/, + ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i, + regex: regex, + uuid: UUID, + 'json-pointer': JSON_POINTER, + 'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT, + 'relative-json-pointer': RELATIVE_JSON_POINTER +}; + + +function isLeapYear(year) { + // https://tools.ietf.org/html/rfc3339#appendix-C + return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); +} + + +function date(str) { + // full-date from http://tools.ietf.org/html/rfc3339#section-5.6 + var matches = str.match(DATE); + if (!matches) return false; + + var year = +matches[1]; + var month = +matches[2]; + var day = +matches[3]; + + return month >= 1 && month <= 12 && day >= 1 && + day <= (month == 2 && isLeapYear(year) ? 29 : DAYS[month]); +} + + +function time(str, full) { + var matches = str.match(TIME); + if (!matches) return false; + + var hour = matches[1]; + var minute = matches[2]; + var second = matches[3]; + var timeZone = matches[5]; + return ((hour <= 23 && minute <= 59 && second <= 59) || + (hour == 23 && minute == 59 && second == 60)) && + (!full || timeZone); +} + + +var DATE_TIME_SEPARATOR = /t|\s/i; +function date_time(str) { + // http://tools.ietf.org/html/rfc3339#section-5.6 + var dateTime = str.split(DATE_TIME_SEPARATOR); + return dateTime.length == 2 && date(dateTime[0]) && time(dateTime[1], true); +} + + +function hostname(str) { + // https://tools.ietf.org/html/rfc1034#section-3.5 + // https://tools.ietf.org/html/rfc1123#section-2 + return str.length <= 255 && HOSTNAME.test(str); +} + + +var NOT_URI_FRAGMENT = /\/|:/; +function uri(str) { + // http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + optional protocol + required "." + return NOT_URI_FRAGMENT.test(str) && URI.test(str); +} + + +var Z_ANCHOR = /[^\\]\\Z/; +function regex(str) { + if (Z_ANCHOR.test(str)) return false; + try { + new RegExp(str); + return true; + } catch(e) { + return false; + } +} + + +/***/ }), +/* 26 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var resolve = __webpack_require__(4) + , util = __webpack_require__(0) + , errorClasses = __webpack_require__(3) + , stableStringify = __webpack_require__(14); + +var validateGenerator = __webpack_require__(13); + +/** + * Functions below are used inside compiled validations function + */ + +var ucs2length = util.ucs2length; +var equal = __webpack_require__(5); + +// this error is thrown by async schemas to return validation errors via exception +var ValidationError = errorClasses.Validation; + +module.exports = compile; + + +/** + * Compiles schema to validation function + * @this Ajv + * @param {Object} schema schema object + * @param {Object} root object with information about the root schema for this schema + * @param {Object} localRefs the hash of local references inside the schema (created by resolve.id), used for inline resolution + * @param {String} baseId base ID for IDs in the schema + * @return {Function} validation function + */ +function compile(schema, root, localRefs, baseId) { + /* jshint validthis: true, evil: true */ + /* eslint no-shadow: 0 */ + var self = this + , opts = this._opts + , refVal = [ undefined ] + , refs = {} + , patterns = [] + , patternsHash = {} + , defaults = [] + , defaultsHash = {} + , customRules = []; + + root = root || { schema: schema, refVal: refVal, refs: refs }; + + var c = checkCompiling.call(this, schema, root, baseId); + var compilation = this._compilations[c.index]; + if (c.compiling) return (compilation.callValidate = callValidate); + + var formats = this._formats; + var RULES = this.RULES; + + try { + var v = localCompile(schema, root, localRefs, baseId); + compilation.validate = v; + var cv = compilation.callValidate; + if (cv) { + cv.schema = v.schema; + cv.errors = null; + cv.refs = v.refs; + cv.refVal = v.refVal; + cv.root = v.root; + cv.$async = v.$async; + if (opts.sourceCode) cv.source = v.source; + } + return v; + } finally { + endCompiling.call(this, schema, root, baseId); + } + + /* @this {*} - custom context, see passContext option */ + function callValidate() { + /* jshint validthis: true */ + var validate = compilation.validate; + var result = validate.apply(this, arguments); + callValidate.errors = validate.errors; + return result; + } + + function localCompile(_schema, _root, localRefs, baseId) { + var isRoot = !_root || (_root && _root.schema == _schema); + if (_root.schema != root.schema) + return compile.call(self, _schema, _root, localRefs, baseId); + + var $async = _schema.$async === true; + + var sourceCode = validateGenerator({ + isTop: true, + schema: _schema, + isRoot: isRoot, + baseId: baseId, + root: _root, + schemaPath: '', + errSchemaPath: '#', + errorPath: '""', + MissingRefError: errorClasses.MissingRef, + RULES: RULES, + validate: validateGenerator, + util: util, + resolve: resolve, + resolveRef: resolveRef, + usePattern: usePattern, + useDefault: useDefault, + useCustomRule: useCustomRule, + opts: opts, + formats: formats, + logger: self.logger, + self: self + }); + + sourceCode = vars(refVal, refValCode) + vars(patterns, patternCode) + + vars(defaults, defaultCode) + vars(customRules, customRuleCode) + + sourceCode; + + if (opts.processCode) sourceCode = opts.processCode(sourceCode); + // console.log('\n\n\n *** \n', JSON.stringify(sourceCode)); + var validate; + try { + var makeValidate = new Function( + 'self', + 'RULES', + 'formats', + 'root', + 'refVal', + 'defaults', + 'customRules', + 'equal', + 'ucs2length', + 'ValidationError', + sourceCode + ); + + validate = makeValidate( + self, + RULES, + formats, + root, + refVal, + defaults, + customRules, + equal, + ucs2length, + ValidationError + ); + + refVal[0] = validate; + } catch(e) { + self.logger.error('Error compiling schema, function code:', sourceCode); + throw e; + } + + validate.schema = _schema; + validate.errors = null; + validate.refs = refs; + validate.refVal = refVal; + validate.root = isRoot ? validate : _root; + if ($async) validate.$async = true; + if (opts.sourceCode === true) { + validate.source = { + code: sourceCode, + patterns: patterns, + defaults: defaults + }; + } + + return validate; + } + + function resolveRef(baseId, ref, isRoot) { + ref = resolve.url(baseId, ref); + var refIndex = refs[ref]; + var _refVal, refCode; + if (refIndex !== undefined) { + _refVal = refVal[refIndex]; + refCode = 'refVal[' + refIndex + ']'; + return resolvedRef(_refVal, refCode); + } + if (!isRoot && root.refs) { + var rootRefId = root.refs[ref]; + if (rootRefId !== undefined) { + _refVal = root.refVal[rootRefId]; + refCode = addLocalRef(ref, _refVal); + return resolvedRef(_refVal, refCode); + } + } + + refCode = addLocalRef(ref); + var v = resolve.call(self, localCompile, root, ref); + if (v === undefined) { + var localSchema = localRefs && localRefs[ref]; + if (localSchema) { + v = resolve.inlineRef(localSchema, opts.inlineRefs) + ? localSchema + : compile.call(self, localSchema, root, localRefs, baseId); + } + } + + if (v === undefined) { + removeLocalRef(ref); + } else { + replaceLocalRef(ref, v); + return resolvedRef(v, refCode); + } + } + + function addLocalRef(ref, v) { + var refId = refVal.length; + refVal[refId] = v; + refs[ref] = refId; + return 'refVal' + refId; + } + + function removeLocalRef(ref) { + delete refs[ref]; + } + + function replaceLocalRef(ref, v) { + var refId = refs[ref]; + refVal[refId] = v; + } + + function resolvedRef(refVal, code) { + return typeof refVal == 'object' || typeof refVal == 'boolean' + ? { code: code, schema: refVal, inline: true } + : { code: code, $async: refVal && !!refVal.$async }; + } + + function usePattern(regexStr) { + var index = patternsHash[regexStr]; + if (index === undefined) { + index = patternsHash[regexStr] = patterns.length; + patterns[index] = regexStr; + } + return 'pattern' + index; + } + + function useDefault(value) { + switch (typeof value) { + case 'boolean': + case 'number': + return '' + value; + case 'string': + return util.toQuotedString(value); + case 'object': + if (value === null) return 'null'; + var valueStr = stableStringify(value); + var index = defaultsHash[valueStr]; + if (index === undefined) { + index = defaultsHash[valueStr] = defaults.length; + defaults[index] = value; + } + return 'default' + index; + } + } + + function useCustomRule(rule, schema, parentSchema, it) { + var validateSchema = rule.definition.validateSchema; + if (validateSchema && self._opts.validateSchema !== false) { + var valid = validateSchema(schema); + if (!valid) { + var message = 'keyword schema is invalid: ' + self.errorsText(validateSchema.errors); + if (self._opts.validateSchema == 'log') self.logger.error(message); + else throw new Error(message); + } + } + + var compile = rule.definition.compile + , inline = rule.definition.inline + , macro = rule.definition.macro; + + var validate; + if (compile) { + validate = compile.call(self, schema, parentSchema, it); + } else if (macro) { + validate = macro.call(self, schema, parentSchema, it); + if (opts.validateSchema !== false) self.validateSchema(validate, true); + } else if (inline) { + validate = inline.call(self, it, rule.keyword, schema, parentSchema); + } else { + validate = rule.definition.validate; + if (!validate) return; + } + + if (validate === undefined) + throw new Error('custom keyword "' + rule.keyword + '"failed to compile'); + + var index = customRules.length; + customRules[index] = validate; + + return { + code: 'customRule' + index, + validate: validate + }; + } +} + + +/** + * Checks if the schema is currently compiled + * @this Ajv + * @param {Object} schema schema to compile + * @param {Object} root root object + * @param {String} baseId base schema ID + * @return {Object} object with properties "index" (compilation index) and "compiling" (boolean) + */ +function checkCompiling(schema, root, baseId) { + /* jshint validthis: true */ + var index = compIndex.call(this, schema, root, baseId); + if (index >= 0) return { index: index, compiling: true }; + index = this._compilations.length; + this._compilations[index] = { + schema: schema, + root: root, + baseId: baseId + }; + return { index: index, compiling: false }; +} + + +/** + * Removes the schema from the currently compiled list + * @this Ajv + * @param {Object} schema schema to compile + * @param {Object} root root object + * @param {String} baseId base schema ID + */ +function endCompiling(schema, root, baseId) { + /* jshint validthis: true */ + var i = compIndex.call(this, schema, root, baseId); + if (i >= 0) this._compilations.splice(i, 1); +} + + +/** + * Index of schema compilation in the currently compiled list + * @this Ajv + * @param {Object} schema schema to compile + * @param {Object} root root object + * @param {String} baseId base schema ID + * @return {Integer} compilation index + */ +function compIndex(schema, root, baseId) { + /* jshint validthis: true */ + for (var i=0; i= 0xD800 && value <= 0xDBFF && pos < len) { + // high surrogate, and there is a next character + value = str.charCodeAt(pos); + if ((value & 0xFC00) == 0xDC00) pos++; // low surrogate + } + } + return length; +}; + + +/***/ }), +/* 29 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var KEYWORDS = [ + 'multipleOf', + 'maximum', + 'exclusiveMaximum', + 'minimum', + 'exclusiveMinimum', + 'maxLength', + 'minLength', + 'pattern', + 'additionalItems', + 'maxItems', + 'minItems', + 'uniqueItems', + 'maxProperties', + 'minProperties', + 'required', + 'additionalProperties', + 'enum', + 'format', + 'const' +]; + +module.exports = function (metaSchema, keywordsJsonPointers) { + for (var i=0; i= 0) { + if ($breakOnError) { + out += ' if (true) { '; + } + return out; + } else { + throw new Error('unknown format "' + $schema + '" is used in schema at path "' + it.errSchemaPath + '"'); + } + } + var $isObject = typeof $format == 'object' && !($format instanceof RegExp) && $format.validate; + var $formatType = $isObject && $format.type || 'string'; + if ($isObject) { + var $async = $format.async === true; + $format = $format.validate; + } + if ($formatType != $ruleType) { + if ($breakOnError) { + out += ' if (true) { '; + } + return out; + } + if ($async) { + if (!it.async) throw new Error('async format in sync schema'); + var $formatRef = 'formats' + it.util.getProperty($schema) + '.validate'; + out += ' if (!(await ' + ($formatRef) + '(' + ($data) + '))) { '; + } else { + out += ' if (! '; + var $formatRef = 'formats' + it.util.getProperty($schema); + if ($isObject) $formatRef += '.validate'; + if (typeof $format == 'function') { + out += ' ' + ($formatRef) + '(' + ($data) + ') '; + } else { + out += ' ' + ($formatRef) + '.test(' + ($data) + ') '; + } + out += ') { '; + } + } + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('format') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { format: '; + if ($isData) { + out += '' + ($schemaValue); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should match format "'; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + (it.util.escapeQuotes($schema)); + } + out += '"\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else { '; + } + return out; +} + + +/***/ }), +/* 39 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate_if(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + $it.level++; + var $nextValid = 'valid' + $it.level; + var $thenSch = it.schema['then'], + $elseSch = it.schema['else'], + $thenPresent = $thenSch !== undefined && it.util.schemaHasRules($thenSch, it.RULES.all), + $elsePresent = $elseSch !== undefined && it.util.schemaHasRules($elseSch, it.RULES.all), + $currentBaseId = $it.baseId; + if ($thenPresent || $elsePresent) { + var $ifClause; + $it.createErrors = false; + $it.schema = $schema; + $it.schemaPath = $schemaPath; + $it.errSchemaPath = $errSchemaPath; + out += ' var ' + ($errs) + ' = errors; var ' + ($valid) + ' = true; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + out += ' ' + (it.validate($it)) + ' '; + $it.baseId = $currentBaseId; + $it.createErrors = true; + out += ' errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; + it.compositeRule = $it.compositeRule = $wasComposite; + if ($thenPresent) { + out += ' if (' + ($nextValid) + ') { '; + $it.schema = it.schema['then']; + $it.schemaPath = it.schemaPath + '.then'; + $it.errSchemaPath = it.errSchemaPath + '/then'; + out += ' ' + (it.validate($it)) + ' '; + $it.baseId = $currentBaseId; + out += ' ' + ($valid) + ' = ' + ($nextValid) + '; '; + if ($thenPresent && $elsePresent) { + $ifClause = 'ifClause' + $lvl; + out += ' var ' + ($ifClause) + ' = \'then\'; '; + } else { + $ifClause = '\'then\''; + } + out += ' } '; + if ($elsePresent) { + out += ' else { '; + } + } else { + out += ' if (!' + ($nextValid) + ') { '; + } + if ($elsePresent) { + $it.schema = it.schema['else']; + $it.schemaPath = it.schemaPath + '.else'; + $it.errSchemaPath = it.errSchemaPath + '/else'; + out += ' ' + (it.validate($it)) + ' '; + $it.baseId = $currentBaseId; + out += ' ' + ($valid) + ' = ' + ($nextValid) + '; '; + if ($thenPresent && $elsePresent) { + $ifClause = 'ifClause' + $lvl; + out += ' var ' + ($ifClause) + ' = \'else\'; '; + } else { + $ifClause = '\'else\''; + } + out += ' } '; + } + out += ' if (!' + ($valid) + ') { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('if') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { failingKeyword: ' + ($ifClause) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should match "\' + ' + ($ifClause) + ' + \'" schema\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError(vErrors); '; + } else { + out += ' validate.errors = vErrors; return false; '; + } + } + out += ' } '; + if ($breakOnError) { + out += ' else { '; + } + out = it.util.cleanUpCode(out); + } else { + if ($breakOnError) { + out += ' if (true) { '; + } + } + return out; +} + + +/***/ }), +/* 40 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +//all requires must be explicit because browserify won't work with dynamic requires +module.exports = { + '$ref': __webpack_require__(48), + allOf: __webpack_require__(30), + anyOf: __webpack_require__(31), + '$comment': __webpack_require__(32), + const: __webpack_require__(33), + contains: __webpack_require__(34), + dependencies: __webpack_require__(36), + 'enum': __webpack_require__(37), + format: __webpack_require__(38), + 'if': __webpack_require__(39), + items: __webpack_require__(41), + maximum: __webpack_require__(9), + minimum: __webpack_require__(9), + maxItems: __webpack_require__(10), + minItems: __webpack_require__(10), + maxLength: __webpack_require__(11), + minLength: __webpack_require__(11), + maxProperties: __webpack_require__(12), + minProperties: __webpack_require__(12), + multipleOf: __webpack_require__(42), + not: __webpack_require__(43), + oneOf: __webpack_require__(44), + pattern: __webpack_require__(45), + properties: __webpack_require__(46), + propertyNames: __webpack_require__(47), + required: __webpack_require__(49), + uniqueItems: __webpack_require__(50), + validate: __webpack_require__(13) +}; + + +/***/ }), +/* 41 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate_items(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + var $idx = 'i' + $lvl, + $dataNxt = $it.dataLevel = it.dataLevel + 1, + $nextData = 'data' + $dataNxt, + $currentBaseId = it.baseId; + out += 'var ' + ($errs) + ' = errors;var ' + ($valid) + ';'; + if (Array.isArray($schema)) { + var $additionalItems = it.schema.additionalItems; + if ($additionalItems === false) { + out += ' ' + ($valid) + ' = ' + ($data) + '.length <= ' + ($schema.length) + '; '; + var $currErrSchemaPath = $errSchemaPath; + $errSchemaPath = it.errSchemaPath + '/additionalItems'; + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('additionalItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schema.length) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have more than ' + ($schema.length) + ' items\' '; + } + if (it.opts.verbose) { + out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + $errSchemaPath = $currErrSchemaPath; + if ($breakOnError) { + $closingBraces += '}'; + out += ' else { '; + } + } + var arr1 = $schema; + if (arr1) { + var $sch, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $sch = arr1[$i += 1]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + out += ' ' + ($nextValid) + ' = true; if (' + ($data) + '.length > ' + ($i) + ') { '; + var $passData = $data + '[' + $i + ']'; + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; + $it.errSchemaPath = $errSchemaPath + '/' + $i; + $it.errorPath = it.util.getPathExpr(it.errorPath, $i, it.opts.jsonPointers, true); + $it.dataPathArr[$dataNxt] = $i; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + } + } + if (typeof $additionalItems == 'object' && it.util.schemaHasRules($additionalItems, it.RULES.all)) { + $it.schema = $additionalItems; + $it.schemaPath = it.schemaPath + '.additionalItems'; + $it.errSchemaPath = it.errSchemaPath + '/additionalItems'; + out += ' ' + ($nextValid) + ' = true; if (' + ($data) + '.length > ' + ($schema.length) + ') { for (var ' + ($idx) + ' = ' + ($schema.length) + '; ' + ($idx) + ' < ' + ($data) + '.length; ' + ($idx) + '++) { '; + $it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true); + var $passData = $data + '[' + $idx + ']'; + $it.dataPathArr[$dataNxt] = $idx; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!' + ($nextValid) + ') break; '; + } + out += ' } } '; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + } else if (it.util.schemaHasRules($schema, it.RULES.all)) { + $it.schema = $schema; + $it.schemaPath = $schemaPath; + $it.errSchemaPath = $errSchemaPath; + out += ' for (var ' + ($idx) + ' = ' + (0) + '; ' + ($idx) + ' < ' + ($data) + '.length; ' + ($idx) + '++) { '; + $it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true); + var $passData = $data + '[' + $idx + ']'; + $it.dataPathArr[$dataNxt] = $idx; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!' + ($nextValid) + ') break; '; + } + out += ' }'; + } + if ($breakOnError) { + out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; + } + out = it.util.cleanUpCode(out); + return out; +} + + +/***/ }), +/* 42 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate_multipleOf(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + out += 'var division' + ($lvl) + ';if ('; + if ($isData) { + out += ' ' + ($schemaValue) + ' !== undefined && ( typeof ' + ($schemaValue) + ' != \'number\' || '; + } + out += ' (division' + ($lvl) + ' = ' + ($data) + ' / ' + ($schemaValue) + ', '; + if (it.opts.multipleOfPrecision) { + out += ' Math.abs(Math.round(division' + ($lvl) + ') - division' + ($lvl) + ') > 1e-' + (it.opts.multipleOfPrecision) + ' '; + } else { + out += ' division' + ($lvl) + ' !== parseInt(division' + ($lvl) + ') '; + } + out += ' ) '; + if ($isData) { + out += ' ) '; + } + out += ' ) { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('multipleOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { multipleOf: ' + ($schemaValue) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should be multiple of '; + if ($isData) { + out += '\' + ' + ($schemaValue); + } else { + out += '' + ($schemaValue) + '\''; + } + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; +} + + +/***/ }), +/* 43 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate_not(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + $it.level++; + var $nextValid = 'valid' + $it.level; + if (it.util.schemaHasRules($schema, it.RULES.all)) { + $it.schema = $schema; + $it.schemaPath = $schemaPath; + $it.errSchemaPath = $errSchemaPath; + out += ' var ' + ($errs) + ' = errors; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + $it.createErrors = false; + var $allErrorsOption; + if ($it.opts.allErrors) { + $allErrorsOption = $it.opts.allErrors; + $it.opts.allErrors = false; + } + out += ' ' + (it.validate($it)) + ' '; + $it.createErrors = true; + if ($allErrorsOption) $it.opts.allErrors = $allErrorsOption; + it.compositeRule = $it.compositeRule = $wasComposite; + out += ' if (' + ($nextValid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT be valid\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } '; + if (it.opts.allErrors) { + out += ' } '; + } + } else { + out += ' var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT be valid\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + if ($breakOnError) { + out += ' if (false) { '; + } + } + return out; +} + + +/***/ }), +/* 44 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate_oneOf(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + var $currentBaseId = $it.baseId, + $prevValid = 'prevValid' + $lvl, + $passingSchemas = 'passingSchemas' + $lvl; + out += 'var ' + ($errs) + ' = errors , ' + ($prevValid) + ' = false , ' + ($valid) + ' = false , ' + ($passingSchemas) + ' = null; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + var arr1 = $schema; + if (arr1) { + var $sch, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $sch = arr1[$i += 1]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; + $it.errSchemaPath = $errSchemaPath + '/' + $i; + out += ' ' + (it.validate($it)) + ' '; + $it.baseId = $currentBaseId; + } else { + out += ' var ' + ($nextValid) + ' = true; '; + } + if ($i) { + out += ' if (' + ($nextValid) + ' && ' + ($prevValid) + ') { ' + ($valid) + ' = false; ' + ($passingSchemas) + ' = [' + ($passingSchemas) + ', ' + ($i) + ']; } else { '; + $closingBraces += '}'; + } + out += ' if (' + ($nextValid) + ') { ' + ($valid) + ' = ' + ($prevValid) + ' = true; ' + ($passingSchemas) + ' = ' + ($i) + '; }'; + } + } + it.compositeRule = $it.compositeRule = $wasComposite; + out += '' + ($closingBraces) + 'if (!' + ($valid) + ') { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('oneOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { passingSchemas: ' + ($passingSchemas) + ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should match exactly one schema in oneOf\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError(vErrors); '; + } else { + out += ' validate.errors = vErrors; return false; '; + } + } + out += '} else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; }'; + if (it.opts.allErrors) { + out += ' } '; + } + return out; +} + + +/***/ }), +/* 45 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate_pattern(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + var $regexp = $isData ? '(new RegExp(' + $schemaValue + '))' : it.usePattern($schema); + out += 'if ( '; + if ($isData) { + out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'string\') || '; + } + out += ' !' + ($regexp) + '.test(' + ($data) + ') ) { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('pattern') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { pattern: '; + if ($isData) { + out += '' + ($schemaValue); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' } '; + if (it.opts.messages !== false) { + out += ' , message: \'should match pattern "'; + if ($isData) { + out += '\' + ' + ($schemaValue) + ' + \''; + } else { + out += '' + (it.util.escapeQuotes($schema)); + } + out += '"\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + (it.util.toQuotedString($schema)); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += '} '; + if ($breakOnError) { + out += ' else { '; + } + return out; +} + + +/***/ }), +/* 46 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate_properties(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + var $key = 'key' + $lvl, + $idx = 'idx' + $lvl, + $dataNxt = $it.dataLevel = it.dataLevel + 1, + $nextData = 'data' + $dataNxt, + $dataProperties = 'dataProperties' + $lvl; + var $schemaKeys = Object.keys($schema || {}), + $pProperties = it.schema.patternProperties || {}, + $pPropertyKeys = Object.keys($pProperties), + $aProperties = it.schema.additionalProperties, + $someProperties = $schemaKeys.length || $pPropertyKeys.length, + $noAdditional = $aProperties === false, + $additionalIsSchema = typeof $aProperties == 'object' && Object.keys($aProperties).length, + $removeAdditional = it.opts.removeAdditional, + $checkAdditional = $noAdditional || $additionalIsSchema || $removeAdditional, + $ownProperties = it.opts.ownProperties, + $currentBaseId = it.baseId; + var $required = it.schema.required; + if ($required && !(it.opts.$data && $required.$data) && $required.length < it.opts.loopRequired) var $requiredHash = it.util.toHash($required); + out += 'var ' + ($errs) + ' = errors;var ' + ($nextValid) + ' = true;'; + if ($ownProperties) { + out += ' var ' + ($dataProperties) + ' = undefined;'; + } + if ($checkAdditional) { + if ($ownProperties) { + out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; + } else { + out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; + } + if ($someProperties) { + out += ' var isAdditional' + ($lvl) + ' = !(false '; + if ($schemaKeys.length) { + if ($schemaKeys.length > 8) { + out += ' || validate.schema' + ($schemaPath) + '.hasOwnProperty(' + ($key) + ') '; + } else { + var arr1 = $schemaKeys; + if (arr1) { + var $propertyKey, i1 = -1, + l1 = arr1.length - 1; + while (i1 < l1) { + $propertyKey = arr1[i1 += 1]; + out += ' || ' + ($key) + ' == ' + (it.util.toQuotedString($propertyKey)) + ' '; + } + } + } + } + if ($pPropertyKeys.length) { + var arr2 = $pPropertyKeys; + if (arr2) { + var $pProperty, $i = -1, + l2 = arr2.length - 1; + while ($i < l2) { + $pProperty = arr2[$i += 1]; + out += ' || ' + (it.usePattern($pProperty)) + '.test(' + ($key) + ') '; + } + } + } + out += ' ); if (isAdditional' + ($lvl) + ') { '; + } + if ($removeAdditional == 'all') { + out += ' delete ' + ($data) + '[' + ($key) + ']; '; + } else { + var $currentErrorPath = it.errorPath; + var $additionalProperty = '\' + ' + $key + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); + } + if ($noAdditional) { + if ($removeAdditional) { + out += ' delete ' + ($data) + '[' + ($key) + ']; '; + } else { + out += ' ' + ($nextValid) + ' = false; '; + var $currErrSchemaPath = $errSchemaPath; + $errSchemaPath = it.errSchemaPath + '/additionalProperties'; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('additionalProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { additionalProperty: \'' + ($additionalProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is an invalid additional property'; + } else { + out += 'should NOT have additional properties'; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + $errSchemaPath = $currErrSchemaPath; + if ($breakOnError) { + out += ' break; '; + } + } + } else if ($additionalIsSchema) { + if ($removeAdditional == 'failing') { + out += ' var ' + ($errs) + ' = errors; '; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + $it.schema = $aProperties; + $it.schemaPath = it.schemaPath + '.additionalProperties'; + $it.errSchemaPath = it.errSchemaPath + '/additionalProperties'; + $it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); + var $passData = $data + '[' + $key + ']'; + $it.dataPathArr[$dataNxt] = $key; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + out += ' if (!' + ($nextValid) + ') { errors = ' + ($errs) + '; if (validate.errors !== null) { if (errors) validate.errors.length = errors; else validate.errors = null; } delete ' + ($data) + '[' + ($key) + ']; } '; + it.compositeRule = $it.compositeRule = $wasComposite; + } else { + $it.schema = $aProperties; + $it.schemaPath = it.schemaPath + '.additionalProperties'; + $it.errSchemaPath = it.errSchemaPath + '/additionalProperties'; + $it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); + var $passData = $data + '[' + $key + ']'; + $it.dataPathArr[$dataNxt] = $key; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!' + ($nextValid) + ') break; '; + } + } + } + it.errorPath = $currentErrorPath; + } + if ($someProperties) { + out += ' } '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + var $useDefaults = it.opts.useDefaults && !it.compositeRule; + if ($schemaKeys.length) { + var arr3 = $schemaKeys; + if (arr3) { + var $propertyKey, i3 = -1, + l3 = arr3.length - 1; + while (i3 < l3) { + $propertyKey = arr3[i3 += 1]; + var $sch = $schema[$propertyKey]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + var $prop = it.util.getProperty($propertyKey), + $passData = $data + $prop, + $hasDefault = $useDefaults && $sch.default !== undefined; + $it.schema = $sch; + $it.schemaPath = $schemaPath + $prop; + $it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($propertyKey); + $it.errorPath = it.util.getPath(it.errorPath, $propertyKey, it.opts.jsonPointers); + $it.dataPathArr[$dataNxt] = it.util.toQuotedString($propertyKey); + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + $code = it.util.varReplace($code, $nextData, $passData); + var $useData = $passData; + } else { + var $useData = $nextData; + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; '; + } + if ($hasDefault) { + out += ' ' + ($code) + ' '; + } else { + if ($requiredHash && $requiredHash[$propertyKey]) { + out += ' if ( ' + ($useData) + ' === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ') { ' + ($nextValid) + ' = false; '; + var $currentErrorPath = it.errorPath, + $currErrSchemaPath = $errSchemaPath, + $missingProperty = it.util.escapeQuotes($propertyKey); + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); + } + $errSchemaPath = it.errSchemaPath + '/required'; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + $errSchemaPath = $currErrSchemaPath; + it.errorPath = $currentErrorPath; + out += ' } else { '; + } else { + if ($breakOnError) { + out += ' if ( ' + ($useData) + ' === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ') { ' + ($nextValid) + ' = true; } else { '; + } else { + out += ' if (' + ($useData) + ' !== undefined '; + if ($ownProperties) { + out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ' ) { '; + } + } + out += ' ' + ($code) + ' } '; + } + } + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + } + } + if ($pPropertyKeys.length) { + var arr4 = $pPropertyKeys; + if (arr4) { + var $pProperty, i4 = -1, + l4 = arr4.length - 1; + while (i4 < l4) { + $pProperty = arr4[i4 += 1]; + var $sch = $pProperties[$pProperty]; + if (it.util.schemaHasRules($sch, it.RULES.all)) { + $it.schema = $sch; + $it.schemaPath = it.schemaPath + '.patternProperties' + it.util.getProperty($pProperty); + $it.errSchemaPath = it.errSchemaPath + '/patternProperties/' + it.util.escapeFragment($pProperty); + if ($ownProperties) { + out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; + } else { + out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; + } + out += ' if (' + (it.usePattern($pProperty)) + '.test(' + ($key) + ')) { '; + $it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers); + var $passData = $data + '[' + $key + ']'; + $it.dataPathArr[$dataNxt] = $key; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + if ($breakOnError) { + out += ' if (!' + ($nextValid) + ') break; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else ' + ($nextValid) + ' = true; '; + } + out += ' } '; + if ($breakOnError) { + out += ' if (' + ($nextValid) + ') { '; + $closingBraces += '}'; + } + } + } + } + } + if ($breakOnError) { + out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {'; + } + out = it.util.cleanUpCode(out); + return out; +} + + +/***/ }), +/* 47 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate_propertyNames(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $errs = 'errs__' + $lvl; + var $it = it.util.copy(it); + var $closingBraces = ''; + $it.level++; + var $nextValid = 'valid' + $it.level; + if (it.util.schemaHasRules($schema, it.RULES.all)) { + $it.schema = $schema; + $it.schemaPath = $schemaPath; + $it.errSchemaPath = $errSchemaPath; + var $key = 'key' + $lvl, + $idx = 'idx' + $lvl, + $i = 'i' + $lvl, + $invalidName = '\' + ' + $key + ' + \'', + $dataNxt = $it.dataLevel = it.dataLevel + 1, + $nextData = 'data' + $dataNxt, + $dataProperties = 'dataProperties' + $lvl, + $ownProperties = it.opts.ownProperties, + $currentBaseId = it.baseId; + out += ' var ' + ($errs) + ' = errors; '; + if ($ownProperties) { + out += ' var ' + ($dataProperties) + ' = undefined; '; + } + if ($ownProperties) { + out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; '; + } else { + out += ' for (var ' + ($key) + ' in ' + ($data) + ') { '; + } + out += ' var startErrs' + ($lvl) + ' = errors; '; + var $passData = $key; + var $wasComposite = it.compositeRule; + it.compositeRule = $it.compositeRule = true; + var $code = it.validate($it); + $it.baseId = $currentBaseId; + if (it.util.varOccurences($code, $nextData) < 2) { + out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' '; + } else { + out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' '; + } + it.compositeRule = $it.compositeRule = $wasComposite; + out += ' if (!' + ($nextValid) + ') { for (var ' + ($i) + '=startErrs' + ($lvl) + '; ' + ($i) + '= it.opts.loopRequired, + $ownProperties = it.opts.ownProperties; + if ($breakOnError) { + out += ' var missing' + ($lvl) + '; '; + if ($loopRequired) { + if (!$isData) { + out += ' var ' + ($vSchema) + ' = validate.schema' + ($schemaPath) + '; '; + } + var $i = 'i' + $lvl, + $propertyPath = 'schema' + $lvl + '[' + $i + ']', + $missingProperty = '\' + ' + $propertyPath + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers); + } + out += ' var ' + ($valid) + ' = true; '; + if ($isData) { + out += ' if (schema' + ($lvl) + ' === undefined) ' + ($valid) + ' = true; else if (!Array.isArray(schema' + ($lvl) + ')) ' + ($valid) + ' = false; else {'; + } + out += ' for (var ' + ($i) + ' = 0; ' + ($i) + ' < ' + ($vSchema) + '.length; ' + ($i) + '++) { ' + ($valid) + ' = ' + ($data) + '[' + ($vSchema) + '[' + ($i) + ']] !== undefined '; + if ($ownProperties) { + out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', ' + ($vSchema) + '[' + ($i) + ']) '; + } + out += '; if (!' + ($valid) + ') break; } '; + if ($isData) { + out += ' } '; + } + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else { '; + } else { + out += ' if ( '; + var arr2 = $required; + if (arr2) { + var $propertyKey, $i = -1, + l2 = arr2.length - 1; + while ($i < l2) { + $propertyKey = arr2[$i += 1]; + if ($i) { + out += ' || '; + } + var $prop = it.util.getProperty($propertyKey), + $useData = $data + $prop; + out += ' ( ( ' + ($useData) + ' === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ') && (missing' + ($lvl) + ' = ' + (it.util.toQuotedString(it.opts.jsonPointers ? $propertyKey : $prop)) + ') ) '; + } + } + out += ') { '; + var $propertyPath = 'missing' + $lvl, + $missingProperty = '\' + ' + $propertyPath + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.opts.jsonPointers ? it.util.getPathExpr($currentErrorPath, $propertyPath, true) : $currentErrorPath + ' + ' + $propertyPath; + } + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } else { '; + } + } else { + if ($loopRequired) { + if (!$isData) { + out += ' var ' + ($vSchema) + ' = validate.schema' + ($schemaPath) + '; '; + } + var $i = 'i' + $lvl, + $propertyPath = 'schema' + $lvl + '[' + $i + ']', + $missingProperty = '\' + ' + $propertyPath + ' + \''; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers); + } + if ($isData) { + out += ' if (' + ($vSchema) + ' && !Array.isArray(' + ($vSchema) + ')) { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } else if (' + ($vSchema) + ' !== undefined) { '; + } + out += ' for (var ' + ($i) + ' = 0; ' + ($i) + ' < ' + ($vSchema) + '.length; ' + ($i) + '++) { if (' + ($data) + '[' + ($vSchema) + '[' + ($i) + ']] === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', ' + ($vSchema) + '[' + ($i) + ']) '; + } + out += ') { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } } '; + if ($isData) { + out += ' } '; + } + } else { + var arr3 = $required; + if (arr3) { + var $propertyKey, i3 = -1, + l3 = arr3.length - 1; + while (i3 < l3) { + $propertyKey = arr3[i3 += 1]; + var $prop = it.util.getProperty($propertyKey), + $missingProperty = it.util.escapeQuotes($propertyKey), + $useData = $data + $prop; + if (it.opts._errorDataPathProperty) { + it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers); + } + out += ' if ( ' + ($useData) + ' === undefined '; + if ($ownProperties) { + out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') '; + } + out += ') { var err = '; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } '; + if (it.opts.messages !== false) { + out += ' , message: \''; + if (it.opts._errorDataPathProperty) { + out += 'is a required property'; + } else { + out += 'should have required property \\\'' + ($missingProperty) + '\\\''; + } + out += '\' '; + } + if (it.opts.verbose) { + out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } '; + } + } + } + } + it.errorPath = $currentErrorPath; + } else if ($breakOnError) { + out += ' if (true) {'; + } + return out; +} + + +/***/ }), +/* 50 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = function generate_uniqueItems(it, $keyword, $ruleType) { + var out = ' '; + var $lvl = it.level; + var $dataLvl = it.dataLevel; + var $schema = it.schema[$keyword]; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); + var $errSchemaPath = it.errSchemaPath + '/' + $keyword; + var $breakOnError = !it.opts.allErrors; + var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; + var $isData = it.opts.$data && $schema && $schema.$data, + $schemaValue; + if ($isData) { + out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; + $schemaValue = 'schema' + $lvl; + } else { + $schemaValue = $schema; + } + if (($schema || $isData) && it.opts.uniqueItems !== false) { + if ($isData) { + out += ' var ' + ($valid) + '; if (' + ($schemaValue) + ' === false || ' + ($schemaValue) + ' === undefined) ' + ($valid) + ' = true; else if (typeof ' + ($schemaValue) + ' != \'boolean\') ' + ($valid) + ' = false; else { '; + } + out += ' var i = ' + ($data) + '.length , ' + ($valid) + ' = true , j; if (i > 1) { '; + var $itemType = it.schema.items && it.schema.items.type, + $typeIsArray = Array.isArray($itemType); + if (!$itemType || $itemType == 'object' || $itemType == 'array' || ($typeIsArray && ($itemType.indexOf('object') >= 0 || $itemType.indexOf('array') >= 0))) { + out += ' outer: for (;i--;) { for (j = i; j--;) { if (equal(' + ($data) + '[i], ' + ($data) + '[j])) { ' + ($valid) + ' = false; break outer; } } } '; + } else { + out += ' var itemIndices = {}, item; for (;i--;) { var item = ' + ($data) + '[i]; '; + var $method = 'checkDataType' + ($typeIsArray ? 's' : ''); + out += ' if (' + (it.util[$method]($itemType, 'item', true)) + ') continue; '; + if ($typeIsArray) { + out += ' if (typeof item == \'string\') item = \'"\' + item; '; + } + out += ' if (typeof itemIndices[item] == \'number\') { ' + ($valid) + ' = false; j = itemIndices[item]; break; } itemIndices[item] = i; } '; + } + out += ' } '; + if ($isData) { + out += ' } '; + } + out += ' if (!' + ($valid) + ') { '; + var $$outStack = $$outStack || []; + $$outStack.push(out); + out = ''; /* istanbul ignore else */ + if (it.createErrors !== false) { + out += ' { keyword: \'' + ('uniqueItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { i: i, j: j } '; + if (it.opts.messages !== false) { + out += ' , message: \'should NOT have duplicate items (items ## \' + j + \' and \' + i + \' are identical)\' '; + } + if (it.opts.verbose) { + out += ' , schema: '; + if ($isData) { + out += 'validate.schema' + ($schemaPath); + } else { + out += '' + ($schema); + } + out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; + } + out += ' } '; + } else { + out += ' {} '; + } + var __err = out; + out = $$outStack.pop(); + if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ + if (it.async) { + out += ' throw new ValidationError([' + (__err) + ']); '; + } else { + out += ' validate.errors = [' + (__err) + ']; return false; '; + } + } else { + out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; + } + out += ' } '; + if ($breakOnError) { + out += ' else { '; + } + } else { + if ($breakOnError) { + out += ' if (true) { '; + } + } + return out; +} + + +/***/ }), +/* 51 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var IDENTIFIER = /^[a-z_$][a-z0-9_$-]*$/i; +var customRuleCode = __webpack_require__(35); + +module.exports = { + add: addKeyword, + get: getKeyword, + remove: removeKeyword +}; + +/** + * Define custom keyword + * @this Ajv + * @param {String} keyword custom keyword, should be unique (including different from all standard, custom and macro keywords). + * @param {Object} definition keyword definition object with properties `type` (type(s) which the keyword applies to), `validate` or `compile`. + * @return {Ajv} this for method chaining + */ +function addKeyword(keyword, definition) { + /* jshint validthis: true */ + /* eslint no-shadow: 0 */ + var RULES = this.RULES; + + if (RULES.keywords[keyword]) + throw new Error('Keyword ' + keyword + ' is already defined'); + + if (!IDENTIFIER.test(keyword)) + throw new Error('Keyword ' + keyword + ' is not a valid identifier'); + + if (definition) { + if (definition.macro && definition.valid !== undefined) + throw new Error('"valid" option cannot be used with macro keywords'); + + var dataType = definition.type; + if (Array.isArray(dataType)) { + var i, len = dataType.length; + for (i=0; i> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} + +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = ((value * c) - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128 +} + + +/***/ }), +/* 56 */ +/***/ (function(module, exports) { + +var toString = {}.toString; + +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; + + +/***/ }), +/* 57 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(Buffer) {/*- + * Copyright 2014 Square Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var Jose = {}; + +/** + * Javascript Object Signing and Encryption library. + * + * @author Alok Menghrajani + */ + +/** + * Initializes a JoseJWE object. + */ +var JoseJWE = {}; + +/** + * Initializes a JoseJWS object. + */ +var JoseJWS = {}; + +/** + * Set crypto provider to use (window.crypto, node-webcrypto-ossl, node-webcrypto-pkcs11 etc.). + */ +exports.setCrypto = function (cp) { + Jose.crypto = cp; +}; + +/** + * Default to the global "crypto" variable + */ +if (typeof(crypto) !== 'undefined') { + exports.setCrypto(crypto); +} + +/** + * Use Node versions of atob, btoa functions outside the browser + */ +if (typeof atob !== "function") { + atob = function (str) { + return new Buffer(str, 'base64').toString('binary'); + }; +} + +if (typeof btoa !== "function") { + btoa = function (str) { + var buffer; + if (str instanceof Buffer) { + buffer = str; + } else { + buffer = new Buffer(str.toString(), 'binary'); + } + return buffer.toString('base64'); + }; +} + +/** + * Checks if we have all the required APIs. + * + * It might make sense to take a Cryptographer and delegate some of the checks + * to the cryptographer. I however wanted to keep things simple, so I put all + * the checks here for now. + * + * This list is generated manually and needs to be kept up-to-date. + * + * Casual testing shows that: + * - things work in Chrome 40.0.2214.115 + * - things work in Firefox 35.0.1 + * - Safari 7.1.3 doesn't support JWK keys. + * - Internet Explorer doesn't support Promises. + * + * Note: We don't check if the browser supports specific crypto operations. + * I.e. it's possible for this function to return true, but encryption or + * decryption to subsequently fail because the browser does not support a + * given encryption, decryption, key wrapping, key unwrapping or hmac + * operation. + * + * @return bool + */ +Jose.caniuse = function() { + var r = true; + + // Promises/A+ (https://promisesaplus.com/) + r = r && (typeof Promise == "function"); + r = r && (typeof Promise.reject == "function"); + r = r && (typeof Promise.prototype.then == "function"); + r = r && (typeof Promise.all == "function"); + + // Crypto (http://www.w3.org/TR/WebCryptoAPI/) + r = r && (typeof Jose.crypto == "object"); + r = r && (typeof Jose.crypto.subtle == "object"); + r = r && (typeof Jose.crypto.getRandomValues == "function"); + r = r && (typeof Jose.crypto.subtle.importKey == "function"); + r = r && (typeof Jose.crypto.subtle.generateKey == "function"); + r = r && (typeof Jose.crypto.subtle.exportKey == "function"); + r = r && (typeof Jose.crypto.subtle.wrapKey == "function"); + r = r && (typeof Jose.crypto.subtle.unwrapKey == "function"); + r = r && (typeof Jose.crypto.subtle.encrypt == "function"); + r = r && (typeof Jose.crypto.subtle.decrypt == "function"); + r = r && (typeof Jose.crypto.subtle.sign == "function"); + + // ArrayBuffer (http://people.mozilla.org/~jorendorff/es6-draft.html#sec-arraybuffer-constructor) + r = r && (typeof ArrayBuffer == "function"); + r = r && (typeof Uint8Array == "function" || typeof Uint8Array == "object"); // Safari uses "object" + r = r && (typeof Uint32Array == "function" || typeof Uint32Array == "object"); // Safari uses "object" + // skipping Uint32Array.prototype.buffer because https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-%typedarrayprototype%-object + + // JSON (http://www.ecma-international.org/ecma-262/5.1/#sec-15.12.3) + r = r && (typeof JSON == "object"); + r = r && (typeof JSON.parse == "function"); + r = r && (typeof JSON.stringify == "function"); + + // Base64 (http://www.w3.org/TR/html5/webappapis.html#dom-windowbase64-atob) + r = r && (typeof atob == "function"); + r = r && (typeof btoa == "function"); + + // skipping Array functions (map, join, push, length, etc.) + // skipping String functions (split, charCodeAt, fromCharCode, replace, etc.) + // skipping regexp.test and parseInt + + return r; +}; + +/** + * Feel free to override this function. + */ +Jose.assert = function(expr, msg) { + if (!expr) { + throw new Error(msg); + } +}; + +exports.Jose = Jose; +exports.JoseJWE = JoseJWE; +exports.JoseJWS = JoseJWS; +/*- + * Copyright 2014 Square Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The WebCryptographer uses http://www.w3.org/TR/WebCryptoAPI/ to perform + * various crypto operations. In theory, this should help build the library with + * different underlying crypto APIs. I'm however unclear if we'll run into code + * duplication or callback vs Promise based API issues. + */ +var WebCryptographer = function() { + this.setKeyEncryptionAlgorithm("RSA-OAEP"); + this.setContentEncryptionAlgorithm("A256GCM"); + this.setContentSignAlgorithm("RS256"); +}; + +Jose.WebCryptographer = WebCryptographer; + +/** + * Overrides the default key encryption algorithm + * @param alg string + */ +WebCryptographer.prototype.setKeyEncryptionAlgorithm = function(alg) { + this.key_encryption = getCryptoConfig(alg); +}; + +WebCryptographer.prototype.getKeyEncryptionAlgorithm = function() { + return this.key_encryption.jwe_name; +}; + +/** + * Overrides the default content encryption algorithm + * @param alg string + */ +WebCryptographer.prototype.setContentEncryptionAlgorithm = function(alg) { + this.content_encryption = getCryptoConfig(alg); +}; + +WebCryptographer.prototype.getContentEncryptionAlgorithm = function() { + return this.content_encryption.jwe_name; +}; + +/** + * Overrides the default content sign algorithm + * @param alg string + */ +WebCryptographer.prototype.setContentSignAlgorithm = function(alg) { + this.content_sign = getSignConfig(alg); +}; + +WebCryptographer.prototype.getContentSignAlgorithm = function() { + return this.content_sign.jwa_name; +}; + +/** + * Generates an IV. + * This function mainly exists so that it can be mocked for testing purpose. + * + * @return Uint8Array with random bytes + */ +WebCryptographer.prototype.createIV = function() { + var iv = new Uint8Array(new Array(this.content_encryption.iv_bytes)); + return Jose.crypto.getRandomValues(iv); +}; + +/** + * Creates a random content encryption key. + * This function mainly exists so that it can be mocked for testing purpose. + * + * @return Promise + */ +WebCryptographer.prototype.createCek = function() { + var hack = getCekWorkaround(this.content_encryption); + return Jose.crypto.subtle.generateKey(hack.id, true, hack.enc_op); +}; + +WebCryptographer.prototype.wrapCek = function(cek, key) { + return Jose.crypto.subtle.wrapKey("raw", cek, key, this.key_encryption.id); +}; + +WebCryptographer.prototype.unwrapCek = function(cek, key) { + var hack = getCekWorkaround(this.content_encryption); + var extractable = (this.content_encryption.specific_cek_bytes > 0); + var key_encryption = this.key_encryption.id; + + return Jose.crypto.subtle.unwrapKey("raw", cek, key, key_encryption, hack.id, extractable, hack.dec_op); +}; + +/** + * Returns algorithm and operation needed to create a CEK. + * + * In some cases, e.g. A128CBC-HS256, the CEK gets split into two keys. The Web + * Crypto API does not allow us to generate an arbitrary number of bytes and + * then create a CryptoKey without any associated algorithm. We therefore piggy + * back on AES-CBS and HMAC which allows the creation of CEKs of size 16, 32, 64 + * and 128 bytes. + */ +var getCekWorkaround = function(alg) { + var len = alg.specific_cek_bytes; + if (len) { + if (len == 16) { + return {id: {name: "AES-CBC", length: 128}, enc_op: ["encrypt"], dec_op: ["decrypt"]}; + } else if (len == 32) { + return {id: {name: "AES-CBC", length: 256}, enc_op: ["encrypt"], dec_op: ["decrypt"]}; + } else if (len == 64) { + return {id: {name: "HMAC", hash: {name: "SHA-256"}}, enc_op: ["sign"], dec_op: ["verify"]}; + } else if (len == 128) { + return {id: {name: "HMAC", hash: {name: "SHA-384"}}, enc_op: ["sign"], dec_op: ["verify"]}; + } else { + Jose.assert(false, "getCekWorkaround: invalid len"); + } + } + return {id: alg.id, enc_op: ["encrypt"], dec_op: ["decrypt"]}; +}; + +/** + * Encrypts plain_text with cek. + * + * @param iv Uint8Array + * @param aad Uint8Array + * @param cek_promise Promise + * @param plain_text Uint8Array + * @return Promise + */ +WebCryptographer.prototype.encrypt = function(iv, aad, cek_promise, plain_text) { + var config = this.content_encryption; + if (iv.length != config.iv_bytes) { + return Promise.reject(Error("invalid IV length")); + } + if (config.auth.aead) { + var tag_bytes = config.auth.tag_bytes; + + var enc = { + name: config.id.name, + iv: iv, + additionalData: aad, + tagLength: tag_bytes * 8 + }; + + return cek_promise.then(function(cek) { + return Jose.crypto.subtle.encrypt(enc, cek, plain_text).then(function(cipher_text) { + var offset = cipher_text.byteLength - tag_bytes; + return { + cipher: cipher_text.slice(0, offset), + tag: cipher_text.slice(offset) + }; + }); + }); + } else { + var keys = splitKey(config, cek_promise, ["encrypt"]); + var mac_key_promise = keys[0]; + var enc_key_promise = keys[1]; + + // Encrypt the plain text + var cipher_text_promise = enc_key_promise.then(function(enc_key) { + var enc = { + name: config.id.name, + iv: iv + }; + return Jose.crypto.subtle.encrypt(enc, enc_key, plain_text); + }); + + // compute MAC + var mac_promise = cipher_text_promise.then(function(cipher_text) { + return truncatedMac( + config, + mac_key_promise, + aad, + iv, + cipher_text); + }); + + return Promise.all([cipher_text_promise, mac_promise]).then(function(all) { + var cipher_text = all[0]; + var mac = all[1]; + return { + cipher: cipher_text, + tag: mac + }; + }); + } +}; + +/** + * Decrypts cipher_text with cek. Validates the tag. + * + * @param cek_promise Promise + * @param aad protected header + * @param iv IV + * @param cipher_text text to be decrypted + * @param tag to be verified + * @return Promise + */ +WebCryptographer.prototype.decrypt = function(cek_promise, aad, iv, cipher_text, tag) { + /** + * Compares two Uint8Arrays in constant time. + * + * @return Promise + */ + var compare = function(config, mac_key_promise, arr1, arr2) { + Jose.assert(arr1 instanceof Uint8Array, "compare: invalid input"); + Jose.assert(arr2 instanceof Uint8Array, "compare: invalid input"); + + return mac_key_promise.then(function(mac_key) { + var hash1 = Jose.crypto.subtle.sign(config.auth.id, mac_key, arr1); + var hash2 = Jose.crypto.subtle.sign(config.auth.id, mac_key, arr2); + return Promise.all([hash1, hash2]).then(function(all) { + var hash1 = new Uint8Array(all[0]); + var hash2 = new Uint8Array(all[1]); + if (hash1.length != hash2.length) { + throw new Error("compare failed"); + } + for (var i = 0; i < hash1.length; i++) { + if (hash1[i] != hash2[i]) { + throw new Error("compare failed"); + } + } + return Promise.resolve(null); + }); + }); + }; + + if (iv.length != this.content_encryption.iv_bytes) { + return Promise.reject(Error("decryptCiphertext: invalid IV")); + } + + var config = this.content_encryption; + if (config.auth.aead) { + var dec = { + name: config.id.name, + iv: iv, + additionalData: aad, + tagLength: config.auth.tag_bytes * 8 + }; + + return cek_promise.then(function(cek) { + var buf = Utils.arrayBufferConcat(cipher_text, tag); + return Jose.crypto.subtle.decrypt(dec, cek, buf); + }); + } else { + var keys = splitKey(config, cek_promise, ["decrypt"]); + var mac_key_promise = keys[0]; + var enc_key_promise = keys[1]; + + // Validate the MAC + var mac_promise = truncatedMac( + config, + mac_key_promise, + aad, + iv, + cipher_text); + + return Promise.all([enc_key_promise, mac_promise]).then(function(all) { + var enc_key = all[0]; + var mac = all[1]; + + return compare(config, mac_key_promise, new Uint8Array(mac), tag).then(function() { + var dec = { + name: config.id.name, + iv: iv + }; + return Jose.crypto.subtle.decrypt(dec, enc_key, cipher_text); + }).catch(function(err) { + return Promise.reject(Error("decryptCiphertext: MAC failed.")); + }); + }); + } +}; + +/** + * Signs plain_text. + * + * @param aad json + * @param payload String or json + * @param key_promise Promise + * @return Promise + */ +WebCryptographer.prototype.sign = function(aad, payload, key_promise) { + var config = this.content_sign; + + if (aad.alg) { + config = getSignConfig(aad.alg); + } + + // Encrypt the plain text + return key_promise.then(function(key) { + return Jose.crypto.subtle.sign(config.id, key, Utils.arrayFromString(Utils.Base64Url.encode(JSON.stringify(aad)) + '.' + Utils.Base64Url.encodeArray(payload))); + }); +}; + +/** + * Verify JWS. + * + * @param payload Base64Url encoded payload + * @param aad String Base64Url encoded JSON representation of the protected JWS header + * @param signature Uint8Array containing the signature + * @param key_promise Promise + * @param key_id value of the kid JoseHeader, it'll be passed as part of the result to the returned promise + * @return Promise + */ +WebCryptographer.prototype.verify = function(aad, payload, signature, key_promise, key_id) { + var config = this.content_sign; + + return key_promise.then(function(key) { + config = getSignConfig(getJwaNameForSignKey(key)); + return Jose.crypto.subtle.verify(config.id, key, signature, Utils.arrayFromString(aad + "." + payload)).then(function(res) { + return {kid: key_id, verified: res}; + }); + }); +}; + +Jose.WebCryptographer.keyId = function(rsa_key) { + return Utils.sha256(rsa_key.n + "+" + rsa_key.d); +}; + +/** + * Splits a CEK into two pieces: a MAC key and an ENC key. + * + * This code is structured around the fact that the crypto API does not provide + * a way to validate truncated MACs. The MAC key is therefore always imported to + * sign data. + * + * @param config (used for key lengths & algorithms) + * @param cek_promise Promise CEK key to split + * @param purpose Array usages of the imported key + * @return [Promise, Promise] + */ +var splitKey = function(config, cek_promise, purpose) { + // We need to split the CEK key into a MAC and ENC keys + var cek_bytes_promise = cek_promise.then(function(cek) { + return Jose.crypto.subtle.exportKey("raw", cek); + }); + var mac_key_promise = cek_bytes_promise.then(function(cek_bytes) { + if (cek_bytes.byteLength * 8 != config.id.length + config.auth.key_bytes * 8) { + return Promise.reject(Error("encryptPlainText: incorrect cek length")); + } + var bytes = cek_bytes.slice(0, config.auth.key_bytes); + return Jose.crypto.subtle.importKey("raw", bytes, config.auth.id, false, ["sign"]); + }); + var enc_key_promise = cek_bytes_promise.then(function(cek_bytes) { + if (cek_bytes.byteLength * 8 != config.id.length + config.auth.key_bytes * 8) { + return Promise.reject(Error("encryptPlainText: incorrect cek length")); + } + var bytes = cek_bytes.slice(config.auth.key_bytes); + return Jose.crypto.subtle.importKey("raw", bytes, config.id, false, purpose); + }); + return [mac_key_promise, enc_key_promise]; +}; + +/** + * Converts the Jose web algorithms into data which is + * useful for the Web Crypto API. + * + * length = in bits + * bytes = in bytes + */ +var getCryptoConfig = function(alg) { + switch (alg) { + // Key encryption + case "RSA-OAEP": + return { + jwe_name: "RSA-OAEP", + id: {name: "RSA-OAEP", hash: {name: "SHA-1"}} + }; + case "RSA-OAEP-256": + return { + jwe_name: "RSA-OAEP-256", + id: {name: "RSA-OAEP", hash: {name: "SHA-256"}} + }; + case "A128KW": + return { + jwe_name: "A128KW", + id: {name: "AES-KW", length: 128} + }; + case "A256KW": + return { + jwe_name: "A256KW", + id: {name: "AES-KW", length: 256} + }; + case "dir": + return { + jwe_name: "dir" + }; + + // Content encryption + case "A128CBC-HS256": + return { + jwe_name: "A128CBC-HS256", + id: {name: "AES-CBC", length: 128}, + iv_bytes: 16, + specific_cek_bytes: 32, + auth: { + key_bytes: 16, + id: {name: "HMAC", hash: {name: "SHA-256"}}, + truncated_bytes: 16 + } + }; + case "A256CBC-HS512": + return { + jwe_name: "A256CBC-HS512", + id: {name: "AES-CBC", length: 256}, + iv_bytes: 16, + specific_cek_bytes: 64, + auth: { + key_bytes: 32, + id: {name: "HMAC", hash: {name: "SHA-512"}}, + truncated_bytes: 32 + } + }; + case "A128GCM": + return { + jwe_name: "A128GCM", + id: {name: "AES-GCM", length: 128}, + iv_bytes: 12, + auth: { + aead: true, + tag_bytes: 16 + } + }; + case "A256GCM": + return { + jwe_name: "A256GCM", + id: {name: "AES-GCM", length: 256}, + iv_bytes: 12, + auth: { + aead: true, + tag_bytes: 16 + } + }; + default: + throw Error("unsupported algorithm: " + alg); + } +}; + +/** + * Computes a truncated MAC. + * + * @param config configuration + * @param mac_key_promise Promise mac key + * @param aad Uint8Array + * @param iv Uint8Array + * @param cipher_text Uint8Array + * @return Promise truncated MAC + */ +var truncatedMac = function(config, mac_key_promise, aad, iv, cipher_text) { + return mac_key_promise.then(function(mac_key) { + var al = new Uint8Array(Utils.arrayFromInt32(aad.length * 8)); + var al_full = new Uint8Array(8); + al_full.set(al, 4); + var buf = Utils.arrayBufferConcat(aad, iv, cipher_text, al_full); + return Jose.crypto.subtle.sign(config.auth.id, mac_key, buf).then(function(bytes) { + return bytes.slice(0, config.auth.truncated_bytes); + }); + }); +}; + +/** + * Converts the Jose web algorithms into data which is + * useful for the Web Crypto API. + */ +var getSignConfig = function(alg) { + + switch (alg) { + case "RS256": + return { + jwa_name: "RS256", + id: {name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-256"}} + }; + case "RS384": + return { + jwa_name: "RS384", + id: {name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-384"}} + }; + case "RS512": + return { + jwa_name: "RS512", + id: {name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-512"}} + }; + case "PS256": + return { + jwa_name: "PS256", + id: {name: "RSA-PSS", hash: {name: "SHA-256"}, saltLength: 20} + }; + case "PS384": + return { + jwa_name: "PS384", + id: {name: "RSA-PSS", hash: {name: "SHA-384"}, saltLength: 20} + }; + case "PS512": + return { + jwa_name: "PS512", + id: {name: "RSA-PSS", hash: {name: "SHA-512"}, saltLength: 20} + }; + case "HS256": + return { + jwa_name: "HS256", + id: {name: "HMAC", hash: {name: "SHA-256"}} + }; + case "HS384": + return { + jwa_name: "HS384", + id: {name: "HMAC", hash: {name: "SHA-384"}} + }; + case "HS512": + return { + jwa_name: "HS512", + id: {name: "HMAC", hash: {name: "SHA-512"}} + }; + case "ES256": + return { + jwa_name: "ES256", + id: {name: "ECDSA", hash: {name: "SHA-256"}} + }; + case "ES384": + return { + jwa_name: "ES384", + id: {name: "ECDSA", hash: {name: "SHA-384"}} + }; + case "ES512": + return { + jwa_name: "ES512", + id: {name: "ECDSA", hash: {name: "SHA-512"}} + }; + default: + throw Error("unsupported algorithm: " + alg); + } +}; + +/** + * Returns JWA name for a given CryptoKey + * @param key CryptoKey + */ +var getJwaNameForSignKey = function(key) { + + var rv = "", + sign_algo = key.algorithm.name, + hash_algo = key.algorithm.hash.name; + + if(sign_algo == "RSASSA-PKCS1-v1_5") { + rv = "R"; + } else if(sign_algo == "RSA-PSS") { + rv = "P"; + } else { + throw new Error("unsupported sign/verify algorithm " + sign_algo); + } + + if(hash_algo.indexOf("SHA-") === 0) { + rv += "S"; + } else { + throw new Error("unsupported hash algorithm " + sign_algo); + } + + rv += hash_algo.substring(4); + + return rv; +}; + +/** + * Derives key usage from algorithm's name + * + * @param alg String algorithm name + * @returns {*} + */ +var getKeyUsageByAlg = function(alg) { + + switch (alg) { + // signature + case "RS256": + case "RS384": + case "RS512": + case "PS256": + case "PS384": + case "PS512": + case "HS256": + case "HS384": + case "HS512": + case "ES256": + case "ES384": + case "ES512": + return { + publicKey: "verify", + privateKey: "sign" + }; + // key encryption + case "RSA-OAEP": + case "RSA-OAEP-256": + case "A128KW": + case "A256KW": + return { + publicKey: "wrapKey", + privateKey: "unwrapKey" + }; + default: + throw Error("unsupported algorithm: " + alg); + } +}; + +/*- + * Copyright 2014 Square Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Jose.Utils = {}; +var Utils = {}; + +/** + * Converts the output from `openssl x509 -text` or `openssl rsa -text` into a + * CryptoKey which can then be used with RSA-OAEP. Also accepts (and validates) + * JWK keys. + * + * TODO: this code probably belongs in the webcryptographer. + * + * @param rsa_key public RSA key in json format. Parameters can be base64 + * encoded, strings or number (for 'e'). + * @param alg String, name of the algorithm + * @return Promise + */ +Jose.Utils.importRsaPublicKey = function(rsa_key, alg) { + var jwk; + var config; + var usage = getKeyUsageByAlg(alg); + + if (usage.publicKey == "wrapKey") { + if (!rsa_key.alg) { + rsa_key.alg = alg; + } + jwk = Utils.convertRsaKey(rsa_key, ["n", "e"]); + config = getCryptoConfig(alg); + } else { + var rk = {}; + for (var name in rsa_key) { + if (rsa_key.hasOwnProperty(name)) { + rk[name] = rsa_key[name]; + } + } + + if (!rk.alg && alg) { + rk.alg = alg; + } + config = getSignConfig(rk.alg); + jwk = Utils.convertRsaKey(rk, ["n", "e"]); + jwk.ext = true; + } + return Jose.crypto.subtle.importKey("jwk", jwk, config.id, false, [usage.publicKey]); +}; + +/** + * Converts the output from `openssl x509 -text` or `openssl rsa -text` into a + * CryptoKey which can then be used with RSA-OAEP and RSA. Also accepts (and validates) + * JWK keys. + * + * TODO: this code probably belongs in the webcryptographer. + * + * @param rsa_key private RSA key in json format. Parameters can be base64 + * encoded, strings or number (for 'e'). + * @param alg String, name of the algorithm + * @return Promise + */ +Jose.Utils.importRsaPrivateKey = function(rsa_key, alg) { + var jwk; + var config; + var usage = getKeyUsageByAlg(alg); + + if (usage.privateKey == "unwrapKey") { + if (!rsa_key.alg) { + rsa_key.alg = alg; + } + jwk = Utils.convertRsaKey(rsa_key, ["n", "e", "d", "p", "q", "dp", "dq", "qi"]); + config = getCryptoConfig("RSA-OAEP"); + } else { + var rk = {}; + for (var name in rsa_key) { + if (rsa_key.hasOwnProperty(name)) { + rk[name] = rsa_key[name]; + } + } + config = getSignConfig(alg); + if (!rk.alg && alg) { + rk.alg = alg; + } + jwk = Utils.convertRsaKey(rk, ["n", "e", "d", "p", "q", "dp", "dq", "qi"]); + jwk.ext = true; + } + return Jose.crypto.subtle.importKey("jwk", jwk, config.id, false, [usage.privateKey]); +}; + +// Private functions + +Utils.isString = function(str) { + return ((typeof(str) == "string") || (str instanceof String)); +}; + +/** + * Takes an arrayish (an array, ArrayBuffer or Uint8Array) + * and returns an array or a Uint8Array. + * + * @param arr arrayish + * @return array or Uint8Array + */ +Utils.arrayish = function(arr) { + if (arr instanceof Array) { + return arr; + } + if (arr instanceof Uint8Array) { + return arr; + } + if (arr instanceof ArrayBuffer) { + return new Uint8Array(arr); + } + Jose.assert(false, "arrayish: invalid input"); +}; + +/** + * Checks if an RSA key contains all the expected parameters. Also checks their + * types. Converts hex encoded strings (or numbers) to base64. + * + * @param rsa_key RSA key in json format. Parameters can be base64 encoded, + * strings or number (for 'e'). + * @param parameters array + * @return json + */ +Utils.convertRsaKey = function(rsa_key, parameters) { + var r = {}; + var alg; + + // Check that we have all the parameters + var missing = []; + parameters.map(function(p){if (typeof(rsa_key[p]) == "undefined") { missing.push(p); }}); + + if (missing.length > 0) { + Jose.assert(false, "convertRsaKey: Was expecting " + missing.join()); + } + + // kty is either missing or is set to "RSA" + if (typeof(rsa_key.kty) != "undefined") { + Jose.assert(rsa_key.kty == "RSA", "convertRsaKey: expecting rsa_key['kty'] to be 'RSA'"); + } + r.kty = "RSA"; + + try { + getSignConfig(rsa_key.alg); + alg = rsa_key.alg; + } catch (err) { + try { + getCryptoConfig(rsa_key.alg); + alg = rsa_key.alg; + } catch (er) { + Jose.assert(alg, "convertRsaKey: expecting rsa_key['alg'] to have a valid value"); + } + } + r.alg = alg; + + // note: we punt on checking key_ops + + var intFromHex = function(e) { + return parseInt(e, 16); + }; + for (var i = 0; i < parameters.length; i++) { + var p = parameters[i]; + var v = rsa_key[p]; + if (p == "e") { + if (typeof(v) == "number") { + v = Utils.Base64Url.encodeArray(Utils.stripLeadingZeros(Utils.arrayFromInt32(v))); + } + } else if (/^([0-9a-fA-F]{2}:)+[0-9a-fA-F]{2}$/.test(v)) { + var arr = v.split(":").map(intFromHex); + v = Utils.Base64Url.encodeArray(Utils.stripLeadingZeros(arr)); + } else if (typeof(v) != "string") { + Jose.assert(false, "convertRsaKey: expecting rsa_key['" + p + "'] to be a string"); + } + r[p] = v; + } + + return r; +}; + +/** + * Converts a string into an array of ascii codes. + * + * @param str ascii string + * @return Uint8Array + */ +Utils.arrayFromString = function(str) { + Jose.assert(Utils.isString(str), "arrayFromString: invalid input"); + var arr = str.split('').map(function(c) { + return c.charCodeAt(0); + }); + return new Uint8Array(arr); +}; + +/** + * Converts a string into an array of utf-8 codes. + * +* @param str utf-8 string + * @return Uint8Array + */ +Utils.arrayFromUtf8String = function(str) { + Jose.assert(Utils.isString(str), "arrayFromUtf8String: invalid input"); + // javascript represents strings as utf-16. Jose imposes the use of + // utf-8, so we need to convert from one representation to the other. + str = unescape(encodeURIComponent(str)); + return Utils.arrayFromString(str); +}; + +/** + * Converts an array of ascii bytes into a string. + * + * @param arr arrayish + * @return ascii string + */ +Utils.stringFromArray = function(arr) { + arr = Utils.arrayish(arr); + var r = ''; + for (var i = 0; i < arr.length; i++) { + r += String.fromCharCode(arr[i]); + } + + return r; +}; + +/** + * Converts an array of ascii bytes into a string. + * + * @param arr ArrayBuffer + * @return ascii string + */ +Utils.utf8StringFromArray = function(arr) { + Jose.assert(arr instanceof ArrayBuffer, "utf8StringFromArray: invalid input"); + + // javascript represents strings as utf-16. Jose imposes the use of + // utf-8, so we need to convert from one representation to the other. + var r = Utils.stringFromArray(arr); + return decodeURIComponent(escape(r)); +}; + +/** + * Strips leading zero in an array. + * + * @param arr arrayish + * @return array + */ +Utils.stripLeadingZeros = function(arr) { + if (arr instanceof ArrayBuffer) { + arr = new Uint8Array(arr); + } + var is_leading_zero = true; + var r = []; + for (var i = 0; i < arr.length; i++) { + if (is_leading_zero && arr[i] === 0) { + continue; + } + is_leading_zero = false; + r.push(arr[i]); + } + return r; +}; + +/** + * Converts a number into an array of 4 bytes (big endian). + * + * @param i number + * @return ArrayBuffer + */ +Utils.arrayFromInt32 = function(i) { + Jose.assert(typeof(i) == "number", "arrayFromInt32: invalid input"); + Jose.assert(i == i | 0, "arrayFromInt32: out of range"); + + var buf = new Uint8Array(new Uint32Array([i]).buffer); + var r = new Uint8Array(4); + for (var j = 0; j < 4; j++) { + r[j] = buf[3 - j]; + } + return r.buffer; +}; + +/** + * Concatenates arrayishes. + * + * @param arguments two or more arrayishes + * @return Uint8Array + */ +Utils.arrayBufferConcat = function(/* ... */) { + // Compute total size + var args = []; + var total = 0; + for (var i = 0; i < arguments.length; i++) { + args.push(Utils.arrayish(arguments[i])); + total += args[i].length; + } + var r = new Uint8Array(total); + var offset = 0; + for (i = 0; i < arguments.length; i++) { + for (var j = 0; j < args[i].length; j++) { + r[offset++] = args[i][j]; + } + } + Jose.assert(offset == total, "arrayBufferConcat: unexpected offset"); + return r; +}; + +Utils.Base64Url = {}; + +/** + * Base64Url encodes a string (no trailing '=') + * + * @param str string + * @return string + */ +Utils.Base64Url.encode = function(str) { + Jose.assert(Utils.isString(str), "Base64Url.encode: invalid input"); + return btoa(str) + .replace(/\+/g, "-") + .replace(/\//g, "_") + .replace(/=+$/, ""); +}; + +/** + * Base64Url encodes an array + * + * @param arr array or ArrayBuffer + * @return string + */ +Utils.Base64Url.encodeArray = function(arr) { + return Utils.Base64Url.encode(Utils.stringFromArray(arr)); +}; + +/** + * Base64Url decodes a string + * + * @param str string + * @return string + */ +Utils.Base64Url.decode = function(str) { + Jose.assert(Utils.isString(str), "Base64Url.decode: invalid input"); + // atob is nice and ignores missing '=' + return atob(str.replace(/-/g, "+").replace(/_/g, "/")); +}; + +Utils.Base64Url.decodeArray = function(str) { + Jose.assert(Utils.isString(str), "Base64Url.decodeArray: invalid input"); + return Utils.arrayFromString(Utils.Base64Url.decode(str)); +}; + +Utils.sha256 = function(str) { + // Browser docs indicate the first parameter to crypto.subtle.digest to be a + // DOMString. This was initially implemented as an object and continues to be + // supported, so we favor the older form for backwards compatibility. + return Jose.crypto.subtle.digest({name: "SHA-256"}, Utils.arrayFromString(str)).then(function(hash) { + return Utils.Base64Url.encodeArray(hash); + }); +}; + +Utils.isCryptoKey = function(rsa_key) { + // Some browsers don't expose the CryptoKey as an object, so we need to check + // the constructor's name. + if (rsa_key.constructor.name == 'CryptoKey') { + return true; + } + + // In the presence of minifiers, relying on class names can be problematic, + // so let's also allow objects that have an 'algorithm' property. + if (rsa_key.hasOwnProperty('algorithm')) { + return true; + } + + return false; +}; + +/*- + * Copyright 2014 Square Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Handles encryption. + * + * @param cryptographer an instance of WebCryptographer (or equivalent). + * @param key_promise Promise, either RSA or shared key + */ +JoseJWE.Encrypter = function(cryptographer, key_promise) { + this.cryptographer = cryptographer; + this.key_promise = key_promise; + this.userHeaders = {}; +}; + +/** + * Adds a key/value pair which will be included in the header. + * + * The data lives in plaintext (an attacker can read the header) but is tamper + * proof (an attacker cannot modify the header). + * + * Note: some headers have semantic implications. E.g. if you set the "zip" + * header, you are responsible for properly compressing plain_text before + * calling encrypt(). + * + * @param k String + * @param v String + */ +JoseJWE.Encrypter.prototype.addHeader = function(k, v) { + this.userHeaders[k] = v; +}; + +/** + * Performs encryption. + * + * @param plain_text utf-8 string + * @return Promise + */ +JoseJWE.Encrypter.prototype.encrypt = function(plain_text) { + /** + * Encrypts plain_text with CEK. + * + * @param cek_promise Promise + * @param plain_text string + * @return Promise + */ + var encryptPlainText = function(cek_promise, plain_text) { + // Create header + var headers = {}; + for (var i in this.userHeaders) { + headers[i] = this.userHeaders[i]; + } + headers.alg = this.cryptographer.getKeyEncryptionAlgorithm(); + headers.enc = this.cryptographer.getContentEncryptionAlgorithm(); + var jwe_protected_header = Utils.Base64Url.encode(JSON.stringify(headers)); + + // Create the IV + var iv = this.cryptographer.createIV(); + + // Create the AAD + var aad = Utils.arrayFromString(jwe_protected_header); + plain_text = Utils.arrayFromUtf8String(plain_text); + + return this.cryptographer.encrypt(iv, aad, cek_promise, plain_text).then(function(r) { + r.header = jwe_protected_header; + r.iv = iv; + return r; + }); + }; + + var cek_promise, encrypted_cek; + + if (this.cryptographer.getKeyEncryptionAlgorithm() == "dir") { + // with direct encryption, this.key_promise provides the cek + // and encrypted_cek is empty + cek_promise = Promise.resolve(this.key_promise); + encrypted_cek = []; + } else { + // Create a CEK key + cek_promise = this.cryptographer.createCek(); + + // Key & Cek allows us to create the encrypted_cek + encrypted_cek = Promise.all([this.key_promise, cek_promise]).then(function (all) { + var key = all[0]; + var cek = all[1]; + return this.cryptographer.wrapCek(cek, key); + }.bind(this)); + } + + // Cek allows us to encrypy the plain text + var enc_promise = encryptPlainText.bind(this, cek_promise, plain_text)(); + + // Once we have all the promises, we can base64 encode all the pieces. + return Promise.all([encrypted_cek, enc_promise]).then(function(all) { + var encrypted_cek = all[0]; + var data = all[1]; + return data.header + "." + + Utils.Base64Url.encodeArray(encrypted_cek) + "." + + Utils.Base64Url.encodeArray(data.iv) + "." + + Utils.Base64Url.encodeArray(data.cipher) + "." + + Utils.Base64Url.encodeArray(data.tag); + }); +}; + +/*- + * Copyright 2014 Square Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Handles decryption. + * + * @param cryptographer an instance of WebCryptographer (or equivalent). Keep + * in mind that decryption mutates the cryptographer. + * @param key_promise Promise, either RSA or shared key + */ +JoseJWE.Decrypter = function(cryptographer, key_promise) { + this.cryptographer = cryptographer; + this.key_promise = key_promise; + this.headers = {}; +}; + +JoseJWE.Decrypter.prototype.getHeaders = function() { + return this.headers; +}; + +/** + * Performs decryption. + * + * @param cipher_text String + * @return Promise + */ +JoseJWE.Decrypter.prototype.decrypt = function(cipher_text) { + // Split cipher_text in 5 parts + var parts = cipher_text.split("."); + if (parts.length != 5) { + return Promise.reject(Error("decrypt: invalid input")); + } + + // part 1: header + this.headers = JSON.parse(Utils.Base64Url.decode(parts[0])); + if (!this.headers.alg) { + return Promise.reject(Error("decrypt: missing alg")); + } + if (!this.headers.enc) { + return Promise.reject(Error("decrypt: missing enc")); + } + this.cryptographer.setKeyEncryptionAlgorithm(this.headers.alg); + this.cryptographer.setContentEncryptionAlgorithm(this.headers.enc); + + if (this.headers.crit) { + // We don't support the crit header + return Promise.reject(Error("decrypt: crit is not supported")); + } + + var cek_promise; + + if (this.headers.alg == "dir") { + // with direct mode, we already have the cek + cek_promise = Promise.resolve(this.key_promise); + } else { + // part 2: decrypt the CEK + // In some modes (e.g. RSA-PKCS1v1.5), you must take precautions to prevent + // chosen-ciphertext attacks as described in RFC 3218, "Preventing + // the Million Message Attack on Cryptographic Message Syntax". We currently + // only support RSA-OAEP, so we don't generate a key if unwrapping fails. + var encrypted_cek = Utils.Base64Url.decodeArray(parts[1]); + cek_promise = this.key_promise.then(function (key) { + return this.cryptographer.unwrapCek(encrypted_cek, key); + }.bind(this)); + } + + // part 3: decrypt the cipher text + var plain_text_promise = this.cryptographer.decrypt( + cek_promise, + Utils.arrayFromString(parts[0]), + Utils.Base64Url.decodeArray(parts[2]), + Utils.Base64Url.decodeArray(parts[3]), + Utils.Base64Url.decodeArray(parts[4])); + + return plain_text_promise.then(Utils.utf8StringFromArray); +}; + +/*- + * Copyright 2015 Peculiar Ventures + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Handles decryption. + * + * @param cryptographer an instance of WebCryptographer (or equivalent). Keep + * in mind that decryption mutates the cryptographer. + * + * @author Patrizio Bruno + */ +JoseJWS.Signer = function(cryptographer) { + this.cryptographer = cryptographer; + + this.key_promises = {}; + this.waiting_kid = 0; + this.headers = {}; + this.signer_aads = {}; + this.signer_headers = {}; +}; + +/** + * Adds a signer to JoseJWS instance. It'll be the on of the signers of the resulting JWS. + * + * @param rsa_key private RSA key in json format, Parameters can be base64 + * encoded, strings or number (for 'e'). Or CryptoKey + * @param key_id a string identifying the rsa_key. OPTIONAL + * @param aad Object protected header + * @param header Object unprotected header + */ +JoseJWS.Signer.prototype.addSigner = function(rsa_key, key_id, aad, header) { + var that = this; + var key_promise; + if (Utils.isCryptoKey(rsa_key)) { + key_promise = new Promise(function(resolve) { + resolve(rsa_key); + }); + } else { + var alg; + if (aad && aad.alg) { + alg = aad.alg; + } else { + alg = that.cryptographer.getContentSignAlgorithm(); + } + key_promise = Jose.Utils.importRsaPrivateKey(rsa_key, alg, "sign"); + } + + var kid_promise; + if (key_id) { + kid_promise = new Promise(function(resolve) { + resolve(key_id); + }); + } else if (Utils.isCryptoKey(rsa_key)) { + throw new Error("key_id is a mandatory argument when the key is a CryptoKey"); + } else { + kid_promise = Jose.WebCryptographer.keyId(rsa_key); + } + + that.waiting_kid++; + + return kid_promise.then(function(kid) { + that.key_promises[kid] = key_promise; + that.waiting_kid--; + if (aad) { + that.signer_aads[kid] = aad; + } + if (header) { + that.signer_headers[kid] = header; + } + return kid; + }); +}; + +/** + * Adds a signature to a JWS object + * @param jws JWS Object to be signed or its representation + * @param aad Object protected header + * @param header Object unprotected header + * @return Promise + */ +JoseJWS.Signer.prototype.addSignature = function(jws, aad, header) { + if (Utils.isString(jws)) { + jws = JSON.parse(jws); + } + + if (jws.payload && Utils.isString(jws.payload) && + jws.protected && Utils.isString(jws.protected) && + jws.header && jws.header instanceof Object && + jws.signature && Utils.isString(jws.signature)) { + return this.sign(JWS.fromObject(jws), aad, header); + } else { + throw new Error("JWS is not a valid JWS object"); + } +}; + +/** + * Computes signature. + * + * @param payload JWS Object or utf-8 string to be signed + * @param aad Object protected header + * @param header Object unprotected header + * @return Promise + */ +JoseJWS.Signer.prototype.sign = function(payload, aad, header) { + + var that = this; + var kids = []; + + if (Object.keys(that.key_promises).length === 0) { + throw new Error("No signers defined. At least one is required to sign the JWS."); + } + + if (that.waiting_kid) { + throw new Error("still generating key IDs"); + } + + function sign (message, protectedHeader, unprotectedHeader, rsa_key_promise, kid) { + var toBeSigned; + + if (!protectedHeader) { + protectedHeader = {}; + } + + if (!protectedHeader.alg) { + protectedHeader.alg = that.cryptographer.getContentSignAlgorithm(); + protectedHeader.typ = "JWT"; + } + + if (!protectedHeader.kid) { + protectedHeader.kid = kid; + } + + if (Utils.isString(message)) { + toBeSigned = Utils.arrayFromUtf8String(message); + } else { + try { + toBeSigned = Utils.arrayish(message); + } catch (e) { + if (message instanceof JWS) { + toBeSigned = Utils.arrayFromString(Utils.Base64Url.decode(message.payload)); + } else if (message instanceof Object) { + toBeSigned = Utils.arrayFromUtf8String(JSON.stringify(message)); + } else { + throw new Error("cannot sign this message"); + } + } + } + + return that.cryptographer.sign(protectedHeader, toBeSigned, rsa_key_promise).then(function(signature) { + var jws = new JWS(protectedHeader, unprotectedHeader, toBeSigned, signature); + if (message instanceof JWS) { + delete jws.payload; + if (!message.signatures) { + message.signatures = [jws]; + } else { + message.signatures.push(jws); + } + return message; + } + return jws; + }); + } + + function doSign (pl, ph, uh, kps, kids) { + if (kids.length) { + var k_id = kids.shift(); + var rv = sign(pl, that.signer_aads[k_id] || ph, that.signer_headers[k_id] || uh, kps[k_id], k_id); + if (kids.length) { + rv = rv.then(function(jws) { + return doSign(jws, null, null, kps, kids); + }); + } + return rv; + } + } + + for(var kid in that.key_promises) { + if (that.key_promises.hasOwnProperty(kid)) { + kids.push(kid); + } + } + return doSign(payload, aad, header, that.key_promises, kids); +}; + + +/** + * Initialize a JWS object. + * + * @param protectedHeader protected header (JS object) + * @param payload Uint8Array payload to be signed + * @param signature ArrayBuffer signature of the payload + * @param header unprotected header (JS object) + * + * @constructor + */ +var JWS = function(protectedHeader, header, payload, signature) { + this.header = header; + this.payload = Utils.Base64Url.encodeArray(payload); + if (signature) { + this.signature = Utils.Base64Url.encodeArray(signature); + } + this.protected = Utils.Base64Url.encode(JSON.stringify(protectedHeader)); +}; + +JWS.fromObject = function(obj) { + var rv = new JWS(obj.protected, obj.header, obj.payload, null); + rv.signature = obj.signature; + rv.signatures = obj.signatures; + return rv; +}; + +/** + * Serialize a JWS object using the JSON serialization format + * + * @returns {Object} a copy of this + */ +JWS.prototype.JsonSerialize = function() { + return JSON.stringify(this); +}; + +/** + * Serialize a JWS object using the Compact Serialization Format + * + * @returns {string} BASE64URL(UTF8(PROTECTED HEADER)).BASE64URL(PAYLOAD).BASE64URL(SIGNATURE) + */ +JWS.prototype.CompactSerialize = function() { + return this.protected + '.' + this.payload + '.' + this.signature; +}; + +/*- + * Copyright 2015 Peculiar Ventures + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Handles signature verification. + * + * @param cryptographer an instance of WebCryptographer (or equivalent). Keep + * in mind that decryption mutates the cryptographer. + * @param message a JWS message + * @param keyfinder (optional) a function returning a Promise given + * a key id + * + * @author Patrizio Bruno + */ +JoseJWS.Verifier = function (cryptographer, message, keyfinder) { + + var that = this, + alg, + jwt, + aad, + header, + payload, + signatures, + protectedHeader, + jwtRx = /^([0-9a-z_\-]+)\.([0-9a-z_\-]+)\.([0-9a-z_\-]+)$/i; + + that.cryptographer = cryptographer; + + alg = cryptographer.getContentSignAlgorithm(); + + that.cryptographer = new Jose.WebCryptographer(); + + if (Utils.isString(message)) { + if ((jwt = jwtRx.exec(message))) { + if (jwt.length != 4) { + throw new Error("wrong JWS compact serialization format"); + } + + message = { + protected: jwt[1], + payload: jwt[2], + signature: jwt[3] + }; + } else { + message = JSON.parse(message); + } + } else if (typeof message != "object") { + throw new Error("data format not supported"); + } + + aad = message.protected; + header = message.header; + payload = message.payload; + signatures = message.signatures instanceof Array ? message.signatures.slice(0) : []; + + signatures.forEach(function (sign) { + sign.aad = sign.protected; + sign.protected = JSON.parse(Utils.Base64Url.decode(sign.protected)); + }); + + that.aad = aad; + protectedHeader = Utils.Base64Url.decode(aad); + try { + protectedHeader = JSON.parse(protectedHeader); + } catch (e) { + } + + if (!protectedHeader && !header) { + throw new Error("at least one header is required"); + } + + if (!protectedHeader.alg) { + throw new Error("'alg' is a mandatory header"); + } + + if (protectedHeader.alg != alg) { + throw new Error("the alg header '" + protectedHeader.alg + "' doesn't match the requested algorithm '" + alg + "'"); + } + + if (protectedHeader && protectedHeader.typ && protectedHeader.typ != "JWT") { + throw new Error("typ '" + protectedHeader.typ + "' not supported"); + } + + if (message.signature) { + signatures.unshift({ + aad: aad, + protected: protectedHeader, + header: header, + signature: message.signature + }); + } + + that.signatures = []; + for(var i = 0; i < signatures.length; i++) { + that.signatures[i] = JSON.parse(JSON.stringify(signatures[i])); + that.signatures[i].signature = Utils.arrayFromString(Utils.Base64Url.decode(signatures[i].signature)); + } + + that.payload = payload; + + that.key_promises = {}; + that.waiting_kid = 0; + + if (keyfinder) { + that.keyfinder = keyfinder; + } +}; + +/** + * Add supported recipients to verify multiple signatures + * + * @param rsa_key public RSA key in json format. Parameters can be base64 + * encoded, strings or number (for 'e'). + * @param key_id a string identifying the rsa_key. OPTIONAL + * @param alg String signature algorithm. OPTIONAL + * @returns Promise a Promise of a key id + */ +JoseJWS.Verifier.prototype.addRecipient = function (rsa_key, key_id, alg) { + + var that = this, + kid_promise, + key_promise = Utils.isCryptoKey(rsa_key) ? new Promise(function (resolve) { + resolve(rsa_key); + }) : Jose.Utils.importRsaPublicKey(rsa_key, alg || that.cryptographer.getContentSignAlgorithm(), "verify"); + + if (key_id) { + kid_promise = new Promise(function (resolve) { + resolve(key_id); + }); + } else if (Utils.isCryptoKey(rsa_key)) { + throw new Error("key_id is a mandatory argument when the key is a CryptoKey"); + } else { + console.log("it's not safe to not pass a key_id"); + kid_promise = Jose.WebCryptographer.keyId(rsa_key); + } + + that.waiting_kid++; + + return kid_promise.then(function (kid) { + that.key_promises[kid] = key_promise; + that.waiting_kid--; + return kid; + }); +}; + +/** + * Verifies a JWS signature + * + * @returns Promise a Promise of an array of objects { kid: string, verified: bool, payload?: string } + * + * payload is only populated and usable if verified is true + */ +JoseJWS.Verifier.prototype.verify = function () { + + var that = this, + signatures = that.signatures, + key_promises = that.key_promises, + keyfinder = that.keyfinder, + promises = [], + check = !!keyfinder || Object.keys(that.key_promises).length > 0; + + if (!check) { + throw new Error("No recipients defined. At least one is required to verify the JWS."); + } + + if (that.waiting_kid) { + throw new Error("still generating key IDs"); + } + + signatures.forEach(function (sig) { + var kid = sig.protected.kid; + if (keyfinder) { + key_promises[kid] = keyfinder(kid); + } + promises.push(that.cryptographer.verify(sig.aad, that.payload, sig.signature, key_promises[kid], kid) + .then(function (vr) { + if (vr.verified) { + vr.payload = Utils.Base64Url.decode(that.payload); + } + return vr; + })); + }); + return Promise.all(promises); +}; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(60).Buffer)) + +/***/ }), +/* 58 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var traverse = module.exports = function (schema, opts, cb) { + if (typeof opts == 'function') { + cb = opts; + opts = {}; + } + _traverse(opts, cb, schema, '', schema); +}; + + +traverse.keywords = { + additionalItems: true, + items: true, + contains: true, + additionalProperties: true, + propertyNames: true, + not: true +}; + +traverse.arrayKeywords = { + items: true, + allOf: true, + anyOf: true, + oneOf: true +}; + +traverse.propsKeywords = { + definitions: true, + properties: true, + patternProperties: true, + dependencies: true +}; + +traverse.skipKeywords = { + enum: true, + const: true, + required: true, + maximum: true, + minimum: true, + exclusiveMaximum: true, + exclusiveMinimum: true, + multipleOf: true, + maxLength: true, + minLength: true, + pattern: true, + format: true, + maxItems: true, + minItems: true, + uniqueItems: true, + maxProperties: true, + minProperties: true +}; + + +function _traverse(opts, cb, schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) { + if (schema && typeof schema == 'object' && !Array.isArray(schema)) { + cb(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex); + for (var key in schema) { + var sch = schema[key]; + if (Array.isArray(sch)) { + if (key in traverse.arrayKeywords) { + for (var i=0; i 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + for (var i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk( + uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) + )) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} + + +/***/ }), +/* 60 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + + + +var base64 = __webpack_require__(59) +var ieee754 = __webpack_require__(55) +var isArray = __webpack_require__(56) + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Due to various browser bugs, sometimes the Object implementation will be used even + * when the browser supports typed arrays. + * + * Note: + * + * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they + * get the Object implementation, which is slower but behaves correctly. + */ +Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined + ? global.TYPED_ARRAY_SUPPORT + : typedArraySupport() + +/* + * Export kMaxLength after typed array support is determined. + */ +exports.kMaxLength = kMaxLength() + +function typedArraySupport () { + try { + var arr = new Uint8Array(1) + arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} + return arr.foo() === 42 && // typed array instances can be augmented + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } +} + +function kMaxLength () { + return Buffer.TYPED_ARRAY_SUPPORT + ? 0x7fffffff + : 0x3fffffff +} + +function createBuffer (that, length) { + if (kMaxLength() < length) { + throw new RangeError('Invalid typed array length') + } + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = new Uint8Array(length) + that.__proto__ = Buffer.prototype + } else { + // Fallback: Return an object instance of the Buffer class + if (that === null) { + that = new Buffer(length) + } + that.length = length + } + + return that +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer (arg, encodingOrOffset, length) { + if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { + return new Buffer(arg, encodingOrOffset, length) + } + + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new Error( + 'If encoding is specified then the first argument must be a string' + ) + } + return allocUnsafe(this, arg) + } + return from(this, arg, encodingOrOffset, length) +} + +Buffer.poolSize = 8192 // not used by this implementation + +// TODO: Legacy, not needed anymore. Remove in next major version. +Buffer._augment = function (arr) { + arr.__proto__ = Buffer.prototype + return arr +} + +function from (that, value, encodingOrOffset, length) { + if (typeof value === 'number') { + throw new TypeError('"value" argument must not be a number') + } + + if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { + return fromArrayBuffer(that, value, encodingOrOffset, length) + } + + if (typeof value === 'string') { + return fromString(that, value, encodingOrOffset) + } + + return fromObject(that, value) +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(null, value, encodingOrOffset, length) +} + +if (Buffer.TYPED_ARRAY_SUPPORT) { + Buffer.prototype.__proto__ = Uint8Array.prototype + Buffer.__proto__ = Uint8Array + if (typeof Symbol !== 'undefined' && Symbol.species && + Buffer[Symbol.species] === Buffer) { + // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true + }) + } +} + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be a number') + } else if (size < 0) { + throw new RangeError('"size" argument must not be negative') + } +} + +function alloc (that, size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(that, size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' + ? createBuffer(that, size).fill(fill, encoding) + : createBuffer(that, size).fill(fill) + } + return createBuffer(that, size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(null, size, fill, encoding) +} + +function allocUnsafe (that, size) { + assertSize(size) + that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < size; ++i) { + that[i] = 0 + } + } + return that +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(null, size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(null, size) +} + +function fromString (that, string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('"encoding" must be a valid string encoding') + } + + var length = byteLength(string, encoding) | 0 + that = createBuffer(that, length) + + var actual = that.write(string, encoding) + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + that = that.slice(0, actual) + } + + return that +} + +function fromArrayLike (that, array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + that = createBuffer(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +function fromArrayBuffer (that, array, byteOffset, length) { + array.byteLength // this throws if `array` is not a valid ArrayBuffer + + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('\'offset\' is out of bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('\'length\' is out of bounds') + } + + if (byteOffset === undefined && length === undefined) { + array = new Uint8Array(array) + } else if (length === undefined) { + array = new Uint8Array(array, byteOffset) + } else { + array = new Uint8Array(array, byteOffset, length) + } + + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = array + that.__proto__ = Buffer.prototype + } else { + // Fallback: Return an object instance of the Buffer class + that = fromArrayLike(that, array) + } + return that +} + +function fromObject (that, obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + that = createBuffer(that, len) + + if (that.length === 0) { + return that + } + + obj.copy(that, 0, 0, len) + return that + } + + if (obj) { + if ((typeof ArrayBuffer !== 'undefined' && + obj.buffer instanceof ArrayBuffer) || 'length' in obj) { + if (typeof obj.length !== 'number' || isnan(obj.length)) { + return createBuffer(that, 0) + } + return fromArrayLike(that, obj) + } + + if (obj.type === 'Buffer' && isArray(obj.data)) { + return fromArrayLike(that, obj.data) + } + } + + throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') +} + +function checked (length) { + // Note: cannot use `length < kMaxLength()` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= kMaxLength()) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength().toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} + +Buffer.isBuffer = function isBuffer (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function compare (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError('Arguments must be Buffers') + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos) + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && + (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + string = '' + string + } + + var len = string.length + if (len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + case undefined: + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) return utf8ToBytes(string).length // assume utf8 + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + var loweredCase = false + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length + } + + if (end <= 0) { + return '' + } + + // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect +// Buffer instances. +Buffer.prototype._isBuffer = true + +function swap (b, n, m) { + var i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} + +Buffer.prototype.toString = function toString () { + var length = this.length | 0 + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) str += ' ... ' + } + return '' +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (!Buffer.isBuffer(target)) { + throw new TypeError('Argument must be a Buffer') + } + + if (start === undefined) { + start = 0 + } + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 + + if (this === target) return 0 + + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) + + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 + } + byteOffset = +byteOffset // Coerce to Number. + if (isNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (Buffer.TYPED_ARRAY_SUPPORT && + typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') +} + +function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1 + var arrLength = arr.length + var valLength = val.length + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } + } + + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + var i + if (dir) { + var foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + var found = true + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } + } + + return -1 +} + +Buffer.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} + +Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(parsed)) return i + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset | 0 + if (isFinite(length)) { + length = length | 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + // legacy write(string, encoding, offset, length) - remove in v0.13 + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; ++i) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf + if (Buffer.TYPED_ARRAY_SUPPORT) { + newBuf = this.subarray(start, end) + newBuf.__proto__ = Buffer.prototype + } else { + var sliceLen = end - start + newBuf = new Buffer(sliceLen, undefined) + for (var i = 0; i < sliceLen; ++i) { + newBuf[i] = this[i + start] + } + } + + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + this[offset] = (value & 0xff) + return offset + 1 +} + +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } +} + +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } +} + +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + var i + + if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start] + } + } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + // ascending copy from start + for (i = 0; i < len; ++i) { + target[i + targetStart] = this[i + start] + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, start + len), + targetStart + ) + } + + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (val.length === 1) { + var code = val.charCodeAt(0) + if (code < 256) { + val = code + } + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + } else if (typeof val === 'number') { + val = val & 255 + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 + + if (!val) val = 0 + + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : utf8ToBytes(new Buffer(val, encoding).toString()) + var len = bytes.length + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// HELPER FUNCTIONS +// ================ + +var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +function isnan (val) { + return val !== val // eslint-disable-line no-self-compare +} + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(18))) + +/***/ }), +/* 61 */ +/***/ (function(module, exports) { + +module.exports = {"$schema":"http://json-schema.org/draft-04/schema#","type":"object","title":"shield-study-addon","description":"`shield-study-addon` addon-specific probe data, with `attributes` sent as Map(s,s).","properties":{"version":{"type":"integer","title":"Version schema. Will be 3","enum":[3]},"study_name":{"description":"Name of a particular study. Usually the addon_id.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"branch":{"description":"Which branch (variation) of the study the user has.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"addon_version":{"description":"Semantic version of the addon.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"shield_version":{"description":"Which version of the shield-studies-addon-utils.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"testing":{"type":"boolean","description":"If `true`, this packet is a TESTING packet and can be safely ignored."},"data":{"type":"object","title":"Shield-Study-Addon 'data' field.","description":"`shield-study-addon` addon-specific probe data, with `attributes` sent as Map(s,s).","properties":{"attributes":{"type":"object","description":"Map(string, string) of attributes.","properties":{},"additionalProperties":{"type":"string"}}},"required":["attributes"]},"type":{"type":"string","description":"doc_type, restated","enum":["shield-study-addon"]}},"required":["version","study_name","branch","addon_version","shield_version","data","type"]} + +/***/ }), +/* 62 */ +/***/ (function(module, exports) { + +module.exports = {"$schema":"http://json-schema.org/draft-04/schema#","type":"object","title":"shield-study-error","description":"`shield-study-error` data used to notify, group and count some kinds of errors from shield studies.","properties":{"version":{"type":"integer","title":"Version schema. Will be 3","enum":[3]},"study_name":{"description":"Name of a particular study. Usually the addon_id.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"branch":{"description":"Which branch (variation) of the study the user has.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"addon_version":{"description":"Semantic version of the addon.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"shield_version":{"description":"Which version of the shield-studies-addon-utils.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"testing":{"type":"boolean","description":"If `true`, this packet is a TESTING packet and can be safely ignored."},"data":{"type":"object","title":"Shield-Study-Error 'data' field","description":"`shield-study-error` data used to notify, group and count some kinds of errors from shield studies.","properties":{"error_id":{"description":"between 1,100 chars, no spaces, unicode ok.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"error_source":{"type":"string","description":"Where did the error originate.","enum":["addon","shield","firefox","unknown"]},"message":{"type":"string","minLength":1,"title":"Message schema.","description":"String of an error message."},"severity":{"type":"string","description":"An explanation about the purpose of this instance.","enum":["debug","info","warn","fatal","impossible"]},"attributes":{"type":"object","description":"Map(string, string) of attributes.","properties":{},"additionalProperties":{"type":"string"}},"error":{"type":"object","description":"(Future use), things like tracebacks.","properties":{},"additionalProperties":{"type":"string"}}},"required":["error_id","error_source"]},"type":{"type":"string","description":"doc_type, restated","enum":["shield-study-error"]}},"required":["version","study_name","branch","addon_version","shield_version","data","type"]} + +/***/ }), +/* 63 */ +/***/ (function(module, exports) { + +module.exports = {"$schema":"http://json-schema.org/draft-04/schema#","type":"object","title":"shield-study","description":"`shield-study` state and outcome data.","properties":{"version":{"type":"integer","title":"Version schema. Will be 3","enum":[3]},"study_name":{"description":"Name of a particular study. Usually the addon_id.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"branch":{"description":"Which branch (variation) of the study the user has.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"addon_version":{"description":"Semantic version of the addon.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"shield_version":{"description":"Which version of the shield-studies-addon-utils.","type":"string","pattern":"^\\S+$","minLength":1,"maxLength":100},"testing":{"type":"boolean","description":"If `true`, this packet is a TESTING packet and can be safely ignored."},"data":{"type":"object","description":"`shield-study` state and outcome data.","properties":{"study_state":{"type":"string","description":"message about the most recent state of the study.","enum":["enter","exit","installed","ineligible","expired","user-disable","ended-positive","ended-neutral","ended-negative","active"]},"study_state_fullname":{"type":"string","description":"Second part of name of state, if any. Study-specific for study-defined endings."},"attributes":{"type":"object","description":"Map(string, string) of attributes.","properties":{},"additionalProperties":{"type":"string"}}},"required":["study_state"]},"type":{"type":"string","description":"doc_type, restated","enum":["shield-study"]}},"required":["version","study_name","branch","addon_version","shield_version","data","type"]} + +/***/ }), +/* 64 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__uri__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__schemes_http__ = __webpack_require__(17); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__schemes_https__ = __webpack_require__(66); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__schemes_mailto__ = __webpack_require__(67); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__schemes_urn__ = __webpack_require__(69); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__schemes_urn_uuid__ = __webpack_require__(68); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "SCHEMES", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["a"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "pctEncChar", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["b"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "pctDecChars", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["c"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "parse", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["d"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "removeDotSegments", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["e"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "serialize", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["f"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "resolveComponents", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["g"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "resolve", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["h"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "normalize", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["i"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "equal", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["j"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "escapeComponent", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["k"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "unescapeComponent", function() { return __WEBPACK_IMPORTED_MODULE_0__uri__["l"]; }); + + +__WEBPACK_IMPORTED_MODULE_0__uri__["a" /* SCHEMES */][__WEBPACK_IMPORTED_MODULE_1__schemes_http__["a" /* default */].scheme] = __WEBPACK_IMPORTED_MODULE_1__schemes_http__["a" /* default */]; + +__WEBPACK_IMPORTED_MODULE_0__uri__["a" /* SCHEMES */][__WEBPACK_IMPORTED_MODULE_2__schemes_https__["a" /* default */].scheme] = __WEBPACK_IMPORTED_MODULE_2__schemes_https__["a" /* default */]; + +__WEBPACK_IMPORTED_MODULE_0__uri__["a" /* SCHEMES */][__WEBPACK_IMPORTED_MODULE_3__schemes_mailto__["a" /* default */].scheme] = __WEBPACK_IMPORTED_MODULE_3__schemes_mailto__["a" /* default */]; + +__WEBPACK_IMPORTED_MODULE_0__uri__["a" /* SCHEMES */][__WEBPACK_IMPORTED_MODULE_4__schemes_urn__["a" /* default */].scheme] = __WEBPACK_IMPORTED_MODULE_4__schemes_urn__["a" /* default */]; + +__WEBPACK_IMPORTED_MODULE_0__uri__["a" /* SCHEMES */][__WEBPACK_IMPORTED_MODULE_5__schemes_urn_uuid__["a" /* default */].scheme] = __WEBPACK_IMPORTED_MODULE_5__schemes_urn_uuid__["a" /* default */]; + +//# sourceMappingURL=index.js.map + +/***/ }), +/* 65 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__regexps_uri__ = __webpack_require__(16); + +/* harmony default export */ __webpack_exports__["a"] = (__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__regexps_uri__["b" /* buildExps */])(true)); +//# sourceMappingURL=regexps-iri.js.map + +/***/ }), +/* 66 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__http__ = __webpack_require__(17); + +const handler = { + scheme: "https", + domainHost: __WEBPACK_IMPORTED_MODULE_0__http__["a" /* default */].domainHost, + parse: __WEBPACK_IMPORTED_MODULE_0__http__["a" /* default */].parse, + serialize: __WEBPACK_IMPORTED_MODULE_0__http__["a" /* default */].serialize +}; +/* harmony default export */ __webpack_exports__["a"] = (handler); +//# sourceMappingURL=https.js.map + +/***/ }), +/* 67 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__uri__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_punycode__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_punycode___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_punycode__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__util__ = __webpack_require__(6); + + + +const O = {}; +const isIRI = true; +//RFC 3986 +const UNRESERVED$$ = "[A-Za-z0-9\\-\\.\\_\\~" + (isIRI ? "\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF" : "") + "]"; +const HEXDIG$$ = "[0-9A-Fa-f]"; //case-insensitive +const PCT_ENCODED$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])("%[EFef]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])("%[89A-Fa-f]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])("%" + HEXDIG$$ + HEXDIG$$)); //expanded +//RFC 5322, except these symbols as per RFC 6068: @ : / ? # [ ] & ; = +//const ATEXT$$ = "[A-Za-z0-9\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~]"; +//const WSP$$ = "[\\x20\\x09]"; +//const OBS_QTEXT$$ = "[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]"; //(%d1-8 / %d11-12 / %d14-31 / %d127) +//const QTEXT$$ = merge("[\\x21\\x23-\\x5B\\x5D-\\x7E]", OBS_QTEXT$$); //%d33 / %d35-91 / %d93-126 / obs-qtext +//const VCHAR$$ = "[\\x21-\\x7E]"; +//const WSP$$ = "[\\x20\\x09]"; +//const OBS_QP$ = subexp("\\\\" + merge("[\\x00\\x0D\\x0A]", OBS_QTEXT$$)); //%d0 / CR / LF / obs-qtext +//const FWS$ = subexp(subexp(WSP$$ + "*" + "\\x0D\\x0A") + "?" + WSP$$ + "+"); +//const QUOTED_PAIR$ = subexp(subexp("\\\\" + subexp(VCHAR$$ + "|" + WSP$$)) + "|" + OBS_QP$); +//const QUOTED_STRING$ = subexp('\\"' + subexp(FWS$ + "?" + QCONTENT$) + "*" + FWS$ + "?" + '\\"'); +const ATEXT$$ = "[A-Za-z0-9\\!\\$\\%\\'\\*\\+\\-\\^\\_\\`\\{\\|\\}\\~]"; +const QTEXT$$ = "[\\!\\$\\%\\'\\(\\)\\*\\+\\,\\-\\.0-9\\<\\>A-Z\\x5E-\\x7E]"; +const VCHAR$$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["d" /* merge */])(QTEXT$$, "[\\\"\\\\]"); +const DOT_ATOM_TEXT$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])(ATEXT$$ + "+" + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])("\\." + ATEXT$$ + "+") + "*"); +const QUOTED_PAIR$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])("\\\\" + VCHAR$$); +const QCONTENT$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])(QTEXT$$ + "|" + QUOTED_PAIR$); +const QUOTED_STRING$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])('\\"' + QCONTENT$ + "*" + '\\"'); +//RFC 6068 +const DTEXT_NO_OBS$$ = "[\\x21-\\x5A\\x5E-\\x7E]"; //%d33-90 / %d94-126 +const SOME_DELIMS$$ = "[\\!\\$\\'\\(\\)\\*\\+\\,\\;\\:\\@]"; +const QCHAR$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])(UNRESERVED$$ + "|" + PCT_ENCODED$ + "|" + SOME_DELIMS$$); +const DOMAIN$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])(DOT_ATOM_TEXT$ + "|" + "\\[" + DTEXT_NO_OBS$$ + "*" + "\\]"); +const LOCAL_PART$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])(DOT_ATOM_TEXT$ + "|" + QUOTED_STRING$); +const ADDR_SPEC$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])(LOCAL_PART$ + "\\@" + DOMAIN$); +const TO$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])(ADDR_SPEC$ + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])("\\," + ADDR_SPEC$) + "*"); +const HFNAME$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])(QCHAR$ + "*"); +const HFVALUE$ = HFNAME$; +const HFIELD$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])(HFNAME$ + "\\=" + HFVALUE$); +const HFIELDS2$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])(HFIELD$ + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])("\\&" + HFIELD$) + "*"); +const HFIELDS$ = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["e" /* subexp */])("\\?" + HFIELDS2$); +const MAILTO_URI = new RegExp("^mailto\\:" + TO$ + "?" + HFIELDS$ + "?$"); +const UNRESERVED = new RegExp(UNRESERVED$$, "g"); +const PCT_ENCODED = new RegExp(PCT_ENCODED$, "g"); +const NOT_LOCAL_PART = new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["d" /* merge */])("[^]", ATEXT$$, "[\\.]", '[\\"]', VCHAR$$), "g"); +const NOT_DOMAIN = new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["d" /* merge */])("[^]", ATEXT$$, "[\\.]", "[\\[]", DTEXT_NO_OBS$$, "[\\]]"), "g"); +const NOT_HFNAME = new RegExp(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["d" /* merge */])("[^]", UNRESERVED$$, SOME_DELIMS$$), "g"); +const NOT_HFVALUE = NOT_HFNAME; +const TO = new RegExp("^" + TO$ + "$"); +const HFIELDS = new RegExp("^" + HFIELDS2$ + "$"); +function decodeUnreserved(str) { + const decStr = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__uri__["c" /* pctDecChars */])(str); + return (!decStr.match(UNRESERVED) ? str : decStr); +} +const handler = { + scheme: "mailto", + parse: function (components, options) { + const mailtoComponents = components; + const to = mailtoComponents.to = (mailtoComponents.path ? mailtoComponents.path.split(",") : []); + mailtoComponents.path = undefined; + if (mailtoComponents.query) { + let unknownHeaders = false; + const headers = {}; + const hfields = mailtoComponents.query.split("&"); + for (let x = 0, xl = hfields.length; x < xl; ++x) { + const hfield = hfields[x].split("="); + switch (hfield[0]) { + case "to": + const toAddrs = hfield[1].split(","); + for (let x = 0, xl = toAddrs.length; x < xl; ++x) { + to.push(toAddrs[x]); + } + break; + case "subject": + mailtoComponents.subject = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__uri__["l" /* unescapeComponent */])(hfield[1], options); + break; + case "body": + mailtoComponents.body = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__uri__["l" /* unescapeComponent */])(hfield[1], options); + break; + default: + unknownHeaders = true; + headers[__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__uri__["l" /* unescapeComponent */])(hfield[0], options)] = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__uri__["l" /* unescapeComponent */])(hfield[1], options); + break; + } + } + if (unknownHeaders) + mailtoComponents.headers = headers; + } + mailtoComponents.query = undefined; + for (let x = 0, xl = to.length; x < xl; ++x) { + const addr = to[x].split("@"); + addr[0] = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__uri__["l" /* unescapeComponent */])(addr[0]); + if (!options.unicodeSupport) { + //convert Unicode IDN -> ASCII IDN + try { + addr[1] = __WEBPACK_IMPORTED_MODULE_1_punycode___default.a.toASCII(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__uri__["l" /* unescapeComponent */])(addr[1], options).toLowerCase()); + } + catch (e) { + mailtoComponents.error = mailtoComponents.error || "Email address's domain name can not be converted to ASCII via punycode: " + e; + } + } + else { + addr[1] = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__uri__["l" /* unescapeComponent */])(addr[1], options).toLowerCase(); + } + to[x] = addr.join("@"); + } + return mailtoComponents; + }, + serialize: function (mailtoComponents, options) { + const components = mailtoComponents; + const to = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__util__["f" /* toArray */])(mailtoComponents.to); + if (to) { + for (let x = 0, xl = to.length; x < xl; ++x) { + const toAddr = String(to[x]); + const atIdx = toAddr.lastIndexOf("@"); + const localPart = (toAddr.slice(0, atIdx)).replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, __WEBPACK_IMPORTED_MODULE_2__util__["a" /* toUpperCase */]).replace(NOT_LOCAL_PART, __WEBPACK_IMPORTED_MODULE_0__uri__["b" /* pctEncChar */]); + let domain = toAddr.slice(atIdx + 1); + //convert IDN via punycode + try { + domain = (!options.iri ? __WEBPACK_IMPORTED_MODULE_1_punycode___default.a.toASCII(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__uri__["l" /* unescapeComponent */])(domain, options).toLowerCase()) : __WEBPACK_IMPORTED_MODULE_1_punycode___default.a.toUnicode(domain)); + } + catch (e) { + components.error = components.error || "Email address's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e; + } + to[x] = localPart + "@" + domain; + } + components.path = to.join(","); + } + const headers = mailtoComponents.headers = mailtoComponents.headers || {}; + if (mailtoComponents.subject) + headers["subject"] = mailtoComponents.subject; + if (mailtoComponents.body) + headers["body"] = mailtoComponents.body; + const fields = []; + for (const name in headers) { + if (headers[name] !== O[name]) { + fields.push(name.replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, __WEBPACK_IMPORTED_MODULE_2__util__["a" /* toUpperCase */]).replace(NOT_HFNAME, __WEBPACK_IMPORTED_MODULE_0__uri__["b" /* pctEncChar */]) + + "=" + + headers[name].replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, __WEBPACK_IMPORTED_MODULE_2__util__["a" /* toUpperCase */]).replace(NOT_HFVALUE, __WEBPACK_IMPORTED_MODULE_0__uri__["b" /* pctEncChar */])); + } + } + if (fields.length) { + components.query = fields.join("&"); + } + return components; + } +}; +/* harmony default export */ __webpack_exports__["a"] = (handler); +//# sourceMappingURL=mailto.js.map + +/***/ }), +/* 68 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +const UUID = /^[0-9A-Fa-f]{8}(?:\-[0-9A-Fa-f]{4}){3}\-[0-9A-Fa-f]{12}$/; +const UUID_PARSE = /^[0-9A-Fa-f\-]{36}/; +//RFC 4122 +const handler = { + scheme: "urn:uuid", + parse: function (urnComponents, options) { + const uuidComponents = urnComponents; + uuidComponents.uuid = uuidComponents.nss; + uuidComponents.nss = undefined; + if (!options.tolerant && (!uuidComponents.uuid || !uuidComponents.uuid.match(UUID))) { + uuidComponents.error = uuidComponents.error || "UUID is not valid."; + } + return uuidComponents; + }, + serialize: function (uuidComponents, options) { + const urnComponents = uuidComponents; + //normalize UUID + urnComponents.nss = (uuidComponents.uuid || "").toLowerCase(); + return urnComponents; + }, +}; +/* harmony default export */ __webpack_exports__["a"] = (handler); +//# sourceMappingURL=urn-uuid.js.map + +/***/ }), +/* 69 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__uri__ = __webpack_require__(1); + +const NID$ = "(?:[0-9A-Za-z][0-9A-Za-z\\-]{1,31})"; +const PCT_ENCODED$ = "(?:\\%[0-9A-Fa-f]{2})"; +const TRANS$$ = "[0-9A-Za-z\\(\\)\\+\\,\\-\\.\\:\\=\\@\\;\\$\\_\\!\\*\\'\\/\\?\\#]"; +const NSS$ = "(?:(?:" + PCT_ENCODED$ + "|" + TRANS$$ + ")+)"; +const URN_SCHEME = new RegExp("^urn\\:(" + NID$ + ")$"); +const URN_PATH = new RegExp("^(" + NID$ + ")\\:(" + NSS$ + ")$"); +const URN_PARSE = /^([^\:]+)\:(.*)/; +const URN_EXCLUDED = /[\x00-\x20\\\"\&\<\>\[\]\^\`\{\|\}\~\x7F-\xFF]/g; +//RFC 2141 +const handler = { + scheme: "urn", + parse: function (components, options) { + const matches = components.path && components.path.match(URN_PARSE); + let urnComponents = components; + if (matches) { + const scheme = options.scheme || urnComponents.scheme || "urn"; + const nid = matches[1].toLowerCase(); + const nss = matches[2]; + const urnScheme = `${scheme}:${options.nid || nid}`; + const schemeHandler = __WEBPACK_IMPORTED_MODULE_0__uri__["a" /* SCHEMES */][urnScheme]; + urnComponents.nid = nid; + urnComponents.nss = nss; + urnComponents.path = undefined; + if (schemeHandler) { + urnComponents = schemeHandler.parse(urnComponents, options); + } + } + else { + urnComponents.error = urnComponents.error || "URN can not be parsed."; + } + return urnComponents; + }, + serialize: function (urnComponents, options) { + const scheme = options.scheme || urnComponents.scheme || "urn"; + const nid = urnComponents.nid; + const urnScheme = `${scheme}:${options.nid || nid}`; + const schemeHandler = __WEBPACK_IMPORTED_MODULE_0__uri__["a" /* SCHEMES */][urnScheme]; + if (schemeHandler) { + urnComponents = schemeHandler.serialize(urnComponents, options); + } + const uriComponents = urnComponents; + const nss = urnComponents.nss; + uriComponents.path = `${nid || options.nid}:${nss}`; + return uriComponents; + }, +}; +/* harmony default export */ __webpack_exports__["a"] = (handler); +//# sourceMappingURL=urn.js.map + +/***/ }), +/* 70 */ +/***/ (function(module, exports) { + +module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + if(!module.children) module.children = []; + Object.defineProperty(module, "loaded", { + enumerable: true, + get: function() { + return module.l; + } + }); + Object.defineProperty(module, "id", { + enumerable: true, + get: function() { + return module.i; + } + }); + module.webpackPolyfill = 1; + } + return module; +}; + + +/***/ }), +/* 71 */ +/***/ (function(module, exports) { + +module.exports = {"name":"shield-studies-addon-utils","description":"Utilities for Mozilla Firefox study add-ons.","version":"6.0.0","author":"Mozilla","bin":{"copyStudyUtils":"bin/copyStudyUtils.js","importPioneerOptIn":"bin/import-pioneer-opt-in.sh"},"bugs":{"url":"https://github.com/mozilla/shield-studies-addon-utils/issues"},"dependencies":{"ajv":"^6.5.0","commander":"^2.15.1","fs-extra":"^6.0.1","jose-jwe-jws":"0.1.6","shield-study-schemas":"^0.8.3"},"devDependencies":{"assert":"^1.4.1","doctoc":"^1.3.1","eslint":"4.19.1","eslint-plugin-json":"^1.4.0","eslint-plugin-mozilla":"^0.13.0","eslint-plugin-no-unsanitized":"^3.0.2","fixpack":"^2.3.1","fx-runner":"^1.0.11","geckodriver":"^1.19.1","get-firefox":"^3.0.0","mocha":"^5.2.0","npm-run-all":"^4.1.2","pre-commit":"^1.2.2","prettier":"^1.11.0","selenium-webdriver":"^3.6.0","web-ext":"^4.0.0","webext-experiment-utils":"github:mozilla/webext-experiment-utils#v0.2.0","webpack":"^2.6.1","yamljs":"^0.3.0"},"engines":{"npm":"^6.1.0"},"files":["bin/copyStudyUtils.js","bin/import-pioneer-opt-in.sh","testUtils","webExtensionApis/study/api.js","webExtensionApis/study/schema.json","webExtensionApis/study/src/telemetry.js","weeUtils/documentSchema.js","weeUtils/generateStubApi.js","weeUtils/verifyWeeSchema.js","weeUtils/wee-schema-schema.json"],"homepage":"https://github.com/mozilla/shield-studies-addon-utils#readme","keywords":["addon","mozilla","normandy","shield","shield-study"],"license":"MPL-2.0","main":"src/index.js","pre-commit":["format"],"repository":{"type":"git","url":"git://github.com/mozilla/shield-studies-addon-utils.git"},"scripts":{"build":"npm run generate && cd webExtensionApis/study && webpack","docformat":"doctoc --title '**Contents**' docs/*.md && prettier '**/*.md' --write","eslint":"eslint . --ext js --ext json","eslint-fix":"npm run eslint -- --fix","fast-build":"npm run-all build:* # no pre and post checks","format":"prettier '**/*.{css,js,jsm,json,md}' --trailing-comma=all --ignore-path=.eslintignore --write","generate":"npm-run-all -s -n generate:generateSchema:* generate:verifyWeeSchema:* generate:documentSchema:* generate:generateStubApi:*","generate:documentSchema:study":"cd webExtensionApis/study && documentSchema schema.json > api.md","generate:generateSchema:study":"cd webExtensionApis/study && yaml2json schema.yaml -p > schema.json","generate:generateStubApi:study":"cd webExtensionApis/study && generateStubApi ./schema.json > stubApi.js","generate:verifyWeeSchema:study":"cd webExtensionApis/study && verifyWeeSchema schema.json","import-pioneer-opt-in":"bin/import-pioneer-opt-in.sh","lint":"npm-run-all lint:*","lint:eslint":"npm run eslint","lint:fixpack":"fixpack # cleans up package.json","postbuild":"if [ -z ${SKIPLINT} ]; then npm run format; fi","postformat":"run-p lint:fixpack eslint-fix","prebuild":"if [ -z ${SKIPLINT} ]; then npm run lint; fi","prepare":"export SKIPLINT=1 && fixpack && npm run build","pretest":"npm run build && npm run test-addon:bundle-utils && npm run test-addon:build && npm run import-pioneer-opt-in","pretest-addon":"npm run pretest","test":"npm run test:func","test-addon":"cd test-addon && web-ext run --no-reload","test-addon:build":"cd test-addon && web-ext build","test-addon:bundle-utils":"./bin/copyStudyUtils.js test-addon/src/privileged","test:func":"npm-run-all -pr test:func:*","test:func:selenium-mocha":"FIREFOX_BINARY=${FIREFOX_BINARY:-nightly} ADDON_ZIP=test-addon/dist/shield_utils_test_add-on-1.0.0.zip GECKODRIVER_URL=http://127.0.0.1:4444 mocha test/functional/ --bail --full-trace","test:func:start-geckodriver-server":"geckodriver -vv 1> test/results/logs/geckodriver.log 2> test/results/logs/geckodriver.errors.log"}} + +/***/ }), +/* 72 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__logger__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__studyUtils__ = __webpack_require__(20); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__dataPermissions__ = __webpack_require__(7); +/* eslint-env commonjs */ +/* eslint no-unused-vars: off */ +/* eslint no-console: ["warn", { allow: ["info", "warn", "error"] }] */ +/* global ExtensionAPI */ + + + + + + + +/** Implements the study/getApi for `browser.study` API */ +this.study = class extends ExtensionAPI { + /** + * We don't need to override the constructor for other + * reasons than to clarify the class member "extension" + * being of type Extension + * + * @param {object} extension Extension + */ + constructor(extension) { + super(extension); + /** + * @type Extension + */ + this.extension = extension; + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug("constructed!"); + } + + /** + * @param {object} context the add-on context + * @returns {object} api with study, studyDebug keys + */ + getAPI(context) { + const { extension } = this; + + const { ExtensionUtils } = ChromeUtils.import( + "resource://gre/modules/ExtensionUtils.jsm", + {}, + ); + + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug("loading web extension experiment study/api.js"); + + /* eslint-disable no-undef */ + const { ExtensionError } = ExtensionUtils; + + // Used for pref naming, telemetry + __WEBPACK_IMPORTED_MODULE_1__studyUtils__["a" /* studyUtils */].setExtensionManifest(extension.manifest); + + return { + study: { + /* Object of current dataPermissions (shield enabled true/false, pioneer enabled true/false) */ + getDataPermissions: __WEBPACK_IMPORTED_MODULE_2__dataPermissions__["a" /* getDataPermissions */], + + /** Send Telemetry using appropriate shield or pioneer methods. + * + * shield: + * - `shield-study-addon` ping, requires object string keys and string values + * + * pioneer: + * - TBD + * + * Note: + * - no conversions / coercion of data happens. + * + * Note: + * - undefined what happens if validation fails + * - undefined what happens when you try to send 'shield' from 'pioneer' + * + * TBD fix the parameters here. + * + * @param {Object} payload Non-nested object with key strings, and key values + * @param {string} telemetryPipeline - the telemetry pipeline + * @returns {undefined} + */ + sendTelemetry: async function sendTelemetry( + payload, + telemetryPipeline, + ) { + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug("called sendTelemetry payload"); + + function throwIfInvalid(obj) { + // Check: all keys and values must be strings, + for (const k in obj) { + if (typeof k !== "string") + throw new ExtensionError(`key ${k} not a string`); + if (typeof obj[k] !== "string") + throw new ExtensionError(`value ${k} ${obj[k]} not a string`); + } + return true; + } + + throwIfInvalid(payload); + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug("valid telemetry payload"); + + try { + return __WEBPACK_IMPORTED_MODULE_1__studyUtils__["a" /* studyUtils */].telemetry(payload, telemetryPipeline); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } + }, + + /** Calculate Telemetry using appropriate shield or pioneer methods. + * + * shield: + * - Calculate the size of a ping + * + * pioneer: + * - Calculate the size of a ping that has Pioneer encrypted data + * + * @param {Object} payload Non-nested object with key strings, and key values + * @param {string} telemetryPipeline - the telemetry pipeline + * @returns {Promise} The total size of the ping. + */ + calculateTelemetryPingSize: async function calculateTelemetryPingSize( + payload, + telemetryPipeline, + ) { + try { + return __WEBPACK_IMPORTED_MODULE_1__studyUtils__["a" /* studyUtils */].calculateTelemetryPingSize( + payload, + telemetryPipeline, + ); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } + }, + + /** Search locally stored telemetry pings using these fields (if set) + * + * n: + * if set, no more than `n` pings. + * type: + * Array of 'ping types' (e.g., main, crash, shield-study-addon) to filter + * mininumTimestamp: + * only pings after this timestamp. + * headersOnly: + * boolean. If true, only the 'headers' will be returned. + * + * Pings will be returned sorted by timestamp with most recent first. + * + * Usage scenarios: + * - enrollment / eligiblity using recent Telemetry behaviours or client environment + * - add-on testing scenarios + * + * @param {Object} searchTelemetryQuery see above + * @returns {Array} matchingPings + */ + async searchSentTelemetry(searchTelemetryQuery) { + try { + const { TelemetryArchive } = ChromeUtils.import( + "resource://gre/modules/TelemetryArchive.jsm", + {}, + ); + const { searchTelemetryArchive } = __webpack_require__(21); + return searchTelemetryArchive( + TelemetryArchive, + searchTelemetryQuery, + ); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } + }, + + /* Using AJV, do jsonschema validation of an object. Can be used to validate your arguments, packets at client. */ + validateJSON: async function validateJSON(someJson, jsonschema) { + try { + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug("called validateJSON someJson, jsonschema"); + return __WEBPACK_IMPORTED_MODULE_1__studyUtils__["a" /* studyUtils */].jsonschema.validate(someJson, jsonschema); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } + }, + + /* Annotates the supplied survey base url with common survey parameters (study name, variation, updateChannel, fxVersion, add-on version and client id) */ + fullSurveyUrl: async function fullSurveyUrl( + surveyBaseUrl, + reason, + telemetryPipeline, + ) { + try { + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug( + "Called fullSurveyUrl(surveyBaseUrl, reason)", + surveyBaseUrl, + reason, + ); + return __WEBPACK_IMPORTED_MODULE_1__studyUtils__["a" /* studyUtils */].fullSurveyUrl({ + surveyBaseUrl, + reason, + telemetryPipeline, + }); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } + }, + }, + + studyDebug: { + throwAnException(message) { + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug( + `Throwing an ExtensionError with message "${message}"`, + ); + throw new ExtensionError(message); + }, + + async throwAnExceptionAsync(message) { + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug( + `Throwing an ExtensionError async with message "${message}"`, + ); + throw new ExtensionError(message); + }, + + async recordSeenTelemetry() { + __WEBPACK_IMPORTED_MODULE_1__studyUtils__["a" /* studyUtils */].recordSeenTelemetry = true; + }, + + async resetSeenTelemetry() { + __WEBPACK_IMPORTED_MODULE_1__studyUtils__["a" /* studyUtils */].seenTelemetry = []; + }, + + async getSeenTelemetry() { + return __WEBPACK_IMPORTED_MODULE_1__studyUtils__["a" /* studyUtils */].seenTelemetry; + }, + }, + }; + } +}; + + +/***/ }), +/* 73 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* eslint-env commonjs */ + +/** Wraps basic jsonschema validation using Ajv */ + +ChromeUtils.import("resource://gre/modules/ExtensionUtils.jsm"); + +const Ajv = __webpack_require__(22); +const ajv = new Ajv({ + // important: these options make ajv behave like 04, not draft-07 + schemaId: "auto", // id UNLESS $id is defined. (draft 5) + meta: __webpack_require__(53), + validateSchema: false, +}); + +const jsonschema = { + /** + * Validates input data based on a specified schema + * @param {Object} data - The data to be validated + * @param {Object} schema - The schema to validate against + * @returns {boolean} - Will return true if the data is valid + */ + validate(data, schema) { + const valid = ajv.validate(schema, data); + return { valid, errors: ajv.errors || [] }; + }, +}; + +/* harmony default export */ __webpack_exports__["a"] = (jsonschema); + + +/***/ }), +/* 74 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__logger__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__dataPermissions__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__getPingSize__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__getPingSize___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2__getPingSize__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_jose_jwe_jws_dist_jose_commonjs_js__ = __webpack_require__(57); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_jose_jwe_jws_dist_jose_commonjs_js___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_jose_jwe_jws_dist_jose_commonjs_js__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__pioneer_public_keys_json__ = __webpack_require__(75); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__pioneer_public_keys_json___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4__pioneer_public_keys_json__); +/* eslint-env commonjs */ +/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "(Pioneer)" }]*/ + + + + + +const { Services } = ChromeUtils.import( + "resource://gre/modules/Services.jsm", + {}, +); +const { TelemetryController } = ChromeUtils.import( + "resource://gre/modules/TelemetryController.jsm", + {}, +); + +const { generateUUID } = Cc["@mozilla.org/uuid-generator;1"].getService( + Ci.nsIUUIDGenerator, +); + + + +// The public keys used for encryption + + +const PIONEER_ID_PREF = "extensions.pioneer.cachedClientID"; + +const EVENTS = { + INELIGIBLE: "ineligible", + EXPIRED: "expired", + USER_DISABLE: "user-disable", + ENDED_POSITIVE: "ended-positive", + ENDED_NEUTRAL: "ended-neutral", + ENDED_NEGATIVE: "ended-negative", +}; + +// Make crypto available and make jose use it. +Cu.importGlobalProperties(["crypto"]); +__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_3_jose_jwe_jws_dist_jose_commonjs_js__["setCrypto"])(crypto); + +/** + * @typedef {Object} Config + * @property {String} studyName + * Unique name of the study. + * + * @property {String?} telemetryEnv + * Optional. Which telemetry environment to send data to. Should be + * either ``"prod"`` or ``"stage"``. Defaults to ``"prod"``. + */ + +/** + * Utilities for making Pioneer Studies. + */ +class PioneerUtils { + /** + * @param {Config} config Object with Pioneer-related configuration as specified above + */ + constructor(config) { + this.config = config; + this.encrypter = null; + this._logger = null; + } + + /** + * @returns {Object} A public key + */ + getPublicKey() { + const env = this.config.telemetryEnv || "prod"; + return __WEBPACK_IMPORTED_MODULE_4__pioneer_public_keys_json__[env]; + } + + /** + * @returns {void} + */ + setupEncrypter() { + if (this.encrypter === null) { + const pk = this.getPublicKey(); + const rsa_key = __WEBPACK_IMPORTED_MODULE_3_jose_jwe_jws_dist_jose_commonjs_js__["Jose"].Utils.importRsaPublicKey(pk.key, "RSA-OAEP"); + const cryptographer = new __WEBPACK_IMPORTED_MODULE_3_jose_jwe_jws_dist_jose_commonjs_js__["Jose"].WebCryptographer(); + this.encrypter = new __WEBPACK_IMPORTED_MODULE_3_jose_jwe_jws_dist_jose_commonjs_js__["JoseJWE"].Encrypter(cryptographer, rsa_key); + } + } + + /** + * @returns {String} Unique ID for a Pioneer user. + */ + getPioneerId() { + let id = Services.prefs.getCharPref(PIONEER_ID_PREF, ""); + + if (!id) { + // generateUUID adds leading and trailing "{" and "}". strip them off. + id = generateUUID() + .toString() + .slice(1, -1); + Services.prefs.setCharPref(PIONEER_ID_PREF, id); + } + + return id; + } + + /** + * @private + * @param {String} data The data to encrypt + * @returns {String} The encrypted data + */ + async encryptData(data) { + this.setupEncrypter(); + return this.encrypter.encrypt(data); + } + + /** + * Constructs a payload object with encrypted data. + * + * @param {String} schemaName + * The name of the schema to be used for validation. + * + * @param {int} schemaVersion + * The version of the schema to be used for validation. + * + * @param {Object} data + * An object containing data to be encrypted and submitted. + * + * @returns {Object} + * A Telemetry payload object with the encrypted data. + */ + async buildEncryptedPayload(schemaName, schemaVersion, data) { + const pk = this.getPublicKey(); + + return { + encryptedData: await this.encryptData(JSON.stringify(data)), + encryptionKeyId: pk.id, + pioneerId: this.getPioneerId(), + studyName: this.config.studyName, + schemaName, + schemaVersion, + }; + } + + /** + * Encrypts the given data and submits a properly formatted + * Pioneer ping to Telemetry. + * + * @param {String} schemaName + * The name of the schema to be used for validation. + * + * @param {int} schemaVersion + * The version of the schema to be used for validation. + * + * @param {Object} data + * A object containing data to be encrypted and submitted. + * + * @param {Object} options + * An object with additional options for the function. + * + * @param {Boolean} options.force + * A boolean to indicate whether to force submission of the ping. + * + * @returns {String} + * The ID of the ping that was submitted + */ + async submitEncryptedPing(schemaName, schemaVersion, data, options = {}) { + // If the user is no longer opted in we should not be submitting pings. + const isUserOptedIn = await __WEBPACK_IMPORTED_MODULE_1__dataPermissions__["b" /* isUserOptedInToPioneer */](); + if (!isUserOptedIn && !options.force) { + return null; + } + + const payload = await this.buildEncryptedPayload( + schemaName, + schemaVersion, + data, + ); + + const telOptions = { + addClientId: true, + addEnvironment: true, + }; + + return TelemetryController.submitExternalPing( + "pioneer-study", + payload, + telOptions, + ); + } + + /** + * Gets an object that is a mapping of all the available events. + * + * @returns {Object} + * An object with all the available events. + */ + getAvailableEvents() { + return EVENTS; + } + + /** + * Submits an encrypted event ping. + * + * @param {String} eventId + * The ID of the event that occured. + * + * @param {Object} options + * An object of options to be passed through to submitEncryptedPing + * + * @returns {String} + * The ID of the event ping that was submitted. + */ + async submitEventPing(eventId, options = {}) { + if (!Object.values(EVENTS).includes(eventId)) { + throw new Error("Invalid event ID."); + } + return this.submitEncryptedPing("event", 1, { eventId }, options); + } +} + +class PioneerTelemetryPipeline { + /** + * @param {object} studyUtils The studyUtils instance from where this class was instantiated + */ + constructor(studyUtils) { + const Config = { + studyName: studyUtils._extensionManifest.applications.gecko.id, + telemetryEnv: "prod", // Currently unconfigurable parameter - defaulting to "prod" rather than "stage" + }; + this.pioneerUtils = new PioneerUtils(Config); + this.schemaVersion = 3; // Corresponds to the schema versions used in https://github.com/mozilla-services/mozilla-pipeline-schemas/tree/dev/templates/telemetry/shield-study (and the shield-study-addon, shield-study-error equivalents) + } + + /** + * @returns {Promise} The ID of the event ping that was submitted. + */ + async notifyNotEligible() { + return this.notifyEndStudy(this.EVENTS.INELIGIBLE); + } + + /** + * @param {String?} eventId The ID of the event that occured. + * @returns {Promise} The ID of the event ping that was submitted. + */ + async notifyEndStudy(eventId = EVENTS.ENDED_NEUTRAL) { + return this.pioneerUtils.submitEventPing(eventId, { force: true }); + } + + /** + * @returns {Promise} Unique ID for a Pioneer user. + */ + async getTelemetryId() { + return this.pioneerUtils.getPioneerId(); + } + + /** + * @param {String} bucket The type of telemetry payload + * @param {Object} payload The telemetry payload + * @returns {Promise} The ID of the ping that was submitted + */ + async sendTelemetry(bucket, payload) { + const schemaName = bucket; + return this._telemetry(schemaName, this.schemaVersion, payload); + } + + /** + * Encrypts the given data and submits a properly formatted + * Pioneer ping to Telemetry. + * + * @param {String} schemaName + * The name of the schema to be used for validation. + * + * @param {int} schemaVersion + * The version of the schema to be used for validation. + * + * @param {Object} payload + * A object containing data to be encrypted and submitted. + * + * @returns {Promise} The ID of the ping that was submitted + * @private + */ + async _telemetry(schemaName, schemaVersion, payload) { + const pingId = await this.pioneerUtils.submitEncryptedPing( + schemaName, + schemaVersion, + payload, + ); + if (pingId) { + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug( + "Pioneer Telemetry sent (encrypted)", + JSON.stringify(payload), + ); + } else { + __WEBPACK_IMPORTED_MODULE_0__logger__["a" /* utilsLogger */].debug( + "Pioneer Telemetry not sent due to privacy preferences", + JSON.stringify(payload), + ); + } + return pingId; + } + + /** + * Calculate the size of a ping. + * + * @param {String} bucket The type of telemetry payload + * + * @param {Object} payload + * The data payload of the ping. + * + * @returns {Promise} + * The total size of the ping. + */ + async getPingSize(bucket, payload) { + const schemaName = bucket; + return this.getEncryptedPingSize(schemaName, this.schemaVersion, payload); + } + + /** + * Calculate the size of a ping that has Pioneer encrypted data. + * + * @param {String} schemaName + * The name of the schema to be used for validation. + * + * @param {int} schemaVersion + * The version of the schema to be used for validation. + * + * @param {Object} data + * An object containing data to be encrypted and submitted. + * + * @returns {Promise} + * The total size of the ping. + */ + async getEncryptedPingSize(schemaName, schemaVersion, data) { + return __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__getPingSize__["getPingSize"])( + await this.pioneerUtils.buildEncryptedPayload( + schemaName, + schemaVersion, + data, + ), + ); + } +} + +/* harmony default export */ __webpack_exports__["a"] = (PioneerTelemetryPipeline); + + +/***/ }), +/* 75 */ +/***/ (function(module, exports) { + +module.exports = {"stage":{"id":"pioneer-20170905","key":{"e":"AQAB","kty":"RSA","n":"3nI-DQ7NoUZCvT348Vi4JfGC1h6R3Qf_yXR0dKM5DmwsuQMxguce6sZ28GWQHJjgbdcs8nTuNQihyVtr9vLsoKUVSmPs_a3QEGXEhTpuTtm7cCb_7HyAlwGtysn2AsdElG8HsDFWlZmiDaHTrTmdLnuk-Z3GRg4nnA4xs4vvUuh0fCVIKoSMFyt3Tkc6IBWJ9X3XrDEbSPrghXV7Cu8LMK3Y4avy6rjEGjWXL-WqIPhiYJcBiFnCcqUCMPvdW7Fs9B36asc_2EQAM5d7BAiBwMjoosSyU6b4JGpI530c3xhqLbX00q1ePCG732cIwp0-bGWV_q0FpQX2M9cNv2Ax4Q"}},"prod":{"id":"pioneer-20170905","key":{"e":"AQAB","kty":"RSA","n":"_uqWswIJpR-cFdwwtNdAI_B_0sPIyQyBy6hiiQ0GKLF2k1PkN6RaxtbZK8v1_BriYtEgWn3hNzJNbKBWBMFtF5-8OfvxH-hgIIeDmRmeHmynLBBCDVf2HAZYaDXJiM7s6LBubDuoPDc3Ovoj287W7E4LgzsBS0wo3ARIwlKn6x0Dj5tu6CQ5r3t0GKZoSFkiVZA7nke-VC55nlDacIIYAqkMX0dzsBaCRmf2C5JJTP-K14iRLB5VFGZ_vnoZ-Wi1BGRV2TNRl3xl0lFJIcPklFpU3hsnRPiF4y7kenU6OIhJVQMqX1CtCF698k7SFCYJt7r1ymWJE-tv0ZwF9b1MFw"}}} + +/***/ }), +/* 76 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__getPingSize__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__getPingSize___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__getPingSize__); +/* eslint-env commonjs */ + + + +const { TelemetryController } = ChromeUtils.import( + "resource://gre/modules/TelemetryController.jsm", + null, +); +const { ClientID } = ChromeUtils.import( + "resource://gre/modules/ClientID.jsm", + {}, +); +// ChromeUtils.import("resource://gre/modules/ExtensionUtils.jsm"); + +// eslint-disable-next-line no-undef +// const { ExtensionError } = ExtensionUtils; + +class ShieldTelemetryPipeline { + /** + * @param {object} studyUtils The studyUtils instance from where this class was instantiated + */ + constructor(studyUtils) { + // console.log("studyUtils", studyUtils); + } + + /** + * @returns {Promise} The telemetry client id + */ + async getTelemetryId() { + return ClientID.getClientID(); + } + + /** + * @param {String} bucket The type of telemetry payload + * @param {Object} payload The telemetry payload + * @returns {Promise} The ID of the ping that was submitted + */ + async sendTelemetry(bucket, payload) { + const telOptions = { addClientId: true, addEnvironment: true }; + return TelemetryController.submitExternalPing(bucket, payload, telOptions); + } + + /** + * Calculate the size of a ping. + * + * @param {String} bucket The type of telemetry payload + * + * @param {Object} payload + * The data payload of the ping. + * + * @returns {Promise} + * The total size of the ping. + */ + async getPingSize(bucket, payload) { + return __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__getPingSize__["getPingSize"])(payload); + } +} + +/* harmony default export */ __webpack_exports__["a"] = (ShieldTelemetryPipeline); + + +/***/ }) +/******/ ]))); \ No newline at end of file diff --git a/webExtensionApis/study/api.md b/webExtensionApis/study/api.md index 25bc03e..7fa271e 100644 --- a/webExtensionApis/study/api.md +++ b/webExtensionApis/study/api.md @@ -4,148 +4,13 @@ Interface for Shield and Pioneer studies. ## Functions -### `browser.study.setup( studySetup )` - -Attempt an setup/enrollment, with these effects: - -* sets 'studyType' as Shield or Pioneer - - * affects telemetry - * (5.2+ TODO) watches for dataPermission changes that should _always_ - stop that kind of study - -* Use or choose variation - - * `testing.variation` if present - * OR (internal) deterministicVariation - from `weightedVariations` - based on hash of - - * activeExperimentName - * clientId - -* During firstRun[1] only: - - * set firstRunTimestamp pref value - * send 'enter' ping - * if `allowEnroll`, send 'install' ping - * else endStudy("ineligible") and return - -* Every Run - * setActiveExperiment(studySetup) - * monitor shield | pioneer permission endings - * suggests alarming if `expire` is set. - -Returns: - -* studyInfo object (see `getStudyInfo`) - -Telemetry Sent (First run only) - - - enter - - install - -Fires Events - -(At most one of) - -* study:onReady OR -* study:onEndStudy - -Preferences set - -* `shield.${runtime.id}.firstRunTimestamp` - -Note: - -1. allowEnroll is ONLY used during first run (install) - -**Parameters** - -* `studySetup` - * type: studySetup - * $ref: - * optional: false - -### `browser.study.endStudy( anEndingAlias )` - -Signal to browser.study that it should end. - -Usage scenarios: - -* add-ons defined - * positive endings (tried feature) - * negative endings (client clicked 'no thanks') - * expiration / timeout (feature should last for 14 days then uninstall) - -Logic: - -* If study has already ended, do nothing. -* Else: END - -END: - -* record internally that study is ended. -* disable all methods that rely on configuration / setup. -* clear all prefs stored by `browser.study` -* fire telemetry pings for: - - * 'exit' - * the ending, one of: - - "ineligible", - "expired", - "user-disable", - "ended-positive", - "ended-neutral", - "ended-negative", - -* augment all ending URLs with query URLs -* fire 'study:end' event to `browser.study.onEndStudy` handlers. - -Add-on should then do - -* open returned URLs -* feature specific cleanup -* uninstall the add-on - -Note: - -1. calling this function multiple time is safe. - `browser.study` will choose the - -**Parameters** - -* `anEndingAlias` - * type: anEndingAlias - * $ref: - * optional: false - -### `browser.study.getStudyInfo( )` - -current study configuration, including - -* variation -* activeExperimentName -* delayInMinutes -* firstRunTimestamp -* isFirstRun - -But not: - -* telemetry clientId - -Throws Error if called before `browser.study.setup` - -**Parameters** - ### `browser.study.getDataPermissions( )` Object of current dataPermissions (shield enabled true/false, pioneer enabled true/false) **Parameters** -### `browser.study.sendTelemetry( payload )` +### `browser.study.sendTelemetry( payload, telemetryPipeline )` Send Telemetry using appropriate shield or pioneer methods. @@ -161,11 +26,17 @@ TBD fix the parameters here. **Parameters** * `payload` + * type: payload * $ref: * optional: false -### `browser.study.calculateTelemetryPingSize( payload )` +* `telemetryPipeline` + * type: telemetryPipeline + * $ref: + * optional: false + +### `browser.study.calculateTelemetryPingSize( payload, telemetryPipeline )` Calculate Telemetry using appropriate shield or pioneer methods. @@ -180,10 +51,16 @@ pioneer: **Parameters** * `payload` + * type: payload * $ref: * optional: false +* `telemetryPipeline` + * type: telemetryPipeline + * $ref: + * optional: false + ### `browser.study.searchSentTelemetry( searchTelemetryQuery )` Search locally stored telemetry pings using these fields (if set) @@ -211,17 +88,6 @@ Usage scenarios: * $ref: * optional: false -### `browser.study.getTestingOverrides( )` - -Returns an object with the following keys: -variationName - to be able to test specific variations -firstRunTimestamp - to be able to test the expiration event -expired - to be able to test the behavior of an already expired study -Used to override study testing flags in getStudySetup(). -The values are set by the corresponding preference under the `extensions.${widgetId}.test.*` preference branch. - -**Parameters** - ### `browser.study.validateJSON( someJson, jsonschema )` Using AJV, do jsonschema validation of an object. Can be used to validate your arguments, packets at client. @@ -239,7 +105,7 @@ Using AJV, do jsonschema validation of an object. Can be used to validate your a * $ref: * optional: false -### `browser.study.fullSurveyUrl( surveyBaseUrl, reason )` +### `browser.study.fullSurveyUrl( surveyBaseUrl, reason, telemetryPipeline )` Annotates the supplied survey base url with common survey parameters (study name, variation, updateChannel, fxVersion, add-on version and client id) @@ -252,39 +118,19 @@ Annotates the supplied survey base url with common survey parameters (study name * optional: false * `reason` + * type: reason * $ref: * optional: false -## Events - -### `browser.study.onReady ()` Event - -Fires when the study is 'ready' for the feature to startup. - -**Parameters** - -* `studyInfo` - * type: studyInfo +* `telemetryPipeline` + * type: telemetryPipeline * $ref: * optional: false -### `browser.study.onEndStudy ()` Event - -Listen for when the study wants to end. - -Act on it by - -* opening surveyUrls -* tearing down your feature -* uninstalling the add-on - -**Parameters** +## Events -* `ending` - * type: ending - * $ref: - * optional: false +(None) ## Properties TBD @@ -397,11 +243,11 @@ Act on it by } ``` -### [4] studyTypesEnum +### [4] telemetryPipelinesEnum ```json { - "id": "studyTypesEnum", + "id": "telemetryPipelinesEnum", "$schema": "http://json-schema.org/draft-04/schema", "type": "string", "enum": ["shield", "pioneer"], @@ -410,231 +256,7 @@ Act on it by } ``` -### [5] weightedVariationObject - -```json -{ - "id": "weightedVariationObject", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "weight": { - "type": "number", - "minimum": 0 - } - }, - "required": ["name", "weight"], - "testcase": { - "name": "feature-active", - "weight": 1.5 - } -} -``` - -### [6] weightedVariationsArray - -```json -{ - "id": "weightedVariationsArray", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "weight": { - "type": "number", - "minimum": 0 - } - }, - "required": ["name", "weight"] - }, - "testcase": [ - { - "name": "feature-active", - "weight": 1.5 - }, - { - "name": "feature-inactive", - "weight": 1.5 - } - ] -} -``` - -### [7] anEndingRequest - -```json -{ - "id": "anEndingRequest", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "properties": { - "fullname": { - "$ref": "NullableString", - "optional": true - }, - "category": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string", - "enum": ["ended-positive", "ended-neutral", "ended-negative"] - } - ], - "choices": [ - { - "type": "null" - }, - { - "type": "string", - "enum": ["ended-positive", "ended-neutral", "ended-negative"] - } - ], - "optional": true - }, - "baseUrls": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "choices": [ - { - "type": "null" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "optional": true, - "default": [] - }, - "exacturls": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "choices": [ - { - "type": "null" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "optional": "true\ndefault: []" - } - }, - "additionalProperties": true, - "testcases": [ - { - "baseUrls": ["some.url"], - "fullname": "anEnding", - "category": "ended-positive" - }, - {}, - { - "baseUrls": ["some.url"] - }, - { - "baseUrls": [], - "fullname": null, - "category": null - } - ], - "failcases": [ - { - "baseUrls": null, - "category": "not okay" - } - ] -} -``` - -### [8] onEndStudyResponse - -```json -{ - "id": "onEndStudyResponse", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "properties": { - "fields": { - "type": "object", - "additionalProperties": true - }, - "urls": { - "type": "array", - "items": { - "type": "string" - } - } - } -} -``` - -### [9] studyInfoObject - -```json -{ - "id": "studyInfoObject", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "additionalProperties": true, - "properties": { - "variation": { - "$ref": "weightedVariationObject" - }, - "firstRunTimestamp": { - "$ref": "NullableInteger" - }, - "activeExperimentName": { - "type": "string" - }, - "delayInMinutes": { - "$ref": "NullableNumber" - }, - "isFirstRun": { - "type": "boolean" - } - }, - "required": [ - "variation", - "firstRunTimestamp", - "activeExperimentName", - "isFirstRun" - ] -} -``` - -### [10] dataPermissionsObject +### [5] dataPermissionsObject ```json { @@ -653,225 +275,7 @@ Act on it by } ``` -### [11] studySetup - -```json -{ - "id": "studySetup", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "properties": { - "activeExperimentName": { - "type": "string" - }, - "studyType": { - "$ref": "studyTypesEnum" - }, - "expire": { - "type": "object", - "properties": { - "days": { - "type": "integer" - } - }, - "optional": true, - "additionalProperties": false - }, - "endings": { - "type": "object", - "additionalProperties": { - "$ref": "anEndingRequest" - } - }, - "weightedVariations": { - "$ref": "weightedVariationsArray" - }, - "telemetry": { - "type": "object", - "properties": { - "send": { - "type": "boolean" - }, - "removeTestingFlag": { - "type": "boolean" - }, - "internalTelemetryArchive": { - "optional": true, - "$ref": "NullableBoolean" - } - } - }, - "testing": { - "type": "object", - "properties": { - "variationName": { - "$ref": "NullableString", - "optional": true - }, - "firstRunTimestamp": { - "$ref": "NullableInteger", - "optional": true - }, - "expired": { - "choices": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ], - "oneOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ], - "optional": true - } - }, - "additionalProperties": false, - "optional": true - } - }, - "required": [ - "activeExperimentName", - "studyType", - "endings", - "weightedVariations", - "telemetry" - ], - "additionalProperties": true, - "testcases": [ - { - "activeExperimentName": "aStudy", - "studyType": "shield", - "expire": { - "days": 10 - }, - "endings": { - "anEnding": { - "baseUrls": ["some.url"] - } - }, - "weightedVariations": [ - { - "name": "feature-active", - "weight": 1.5 - } - ], - "telemetry": { - "send": false, - "removeTestingFlag": false - } - }, - { - "activeExperimentName": "aStudy", - "studyType": "shield", - "expire": { - "days": 10 - }, - "endings": { - "anEnding": { - "baseUrls": ["some.url"] - } - }, - "weightedVariations": [ - { - "name": "feature-active", - "weight": 1.5 - } - ], - "telemetry": { - "send": false, - "removeTestingFlag": false, - "internalTelemetryArchive": false - }, - "testing": { - "variationName": "something", - "firstRunTimestamp": 1234567890, - "expired": true - } - }, - { - "activeExperimentName": "aStudy", - "studyType": "pioneer", - "endings": { - "anEnding": { - "baseUrls": ["some.url"] - } - }, - "weightedVariations": [ - { - "name": "feature-active", - "weight": 1.5 - } - ], - "telemetry": { - "send": false, - "removeTestingFlag": true, - "internalTelemetryArchive": true - }, - "testing": { - "variationName": "something", - "firstRunTimestamp": 1234567890, - "expired": true - } - }, - { - "activeExperimentName": "shield-utils-test-addon@shield.mozilla.org", - "studyType": "shield", - "telemetry": { - "send": true, - "removeTestingFlag": false - }, - "endings": { - "user-disable": { - "baseUrls": ["http://www.example.com/?reason=user-disable"] - }, - "ineligible": { - "baseUrls": ["http://www.example.com/?reason=ineligible"] - }, - "expired": { - "baseUrls": ["http://www.example.com/?reason=expired"] - }, - "some-study-defined-ending": { - "category": "ended-neutral" - }, - "some-study-defined-ending-with-survey-url": { - "baseUrls": [ - "http://www.example.com/?reason=some-study-defined-ending-with-survey-url" - ], - "category": "ended-negative" - } - }, - "weightedVariations": [ - { - "name": "feature-active", - "weight": 1.5 - }, - { - "name": "feature-passive", - "weight": 1.5 - }, - { - "name": "control", - "weight": 1 - } - ], - "expire": { - "days": 14 - }, - "testing": {}, - "allowEnroll": true - } - ] -} -``` - -### [12] telemetryPayload +### [6] telemetryPayload ```json { @@ -885,7 +289,7 @@ Act on it by } ``` -### [13] searchTelemetryQuery +### [7] searchTelemetryQuery ```json { @@ -923,95 +327,6 @@ Act on it by } ``` -### [14] anEndingAnswer - -```json -{ - "id": "anEndingAnswer", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "additionalProperties": true -} -``` - -# Namespace: `browser.study.logger` - -For study developers to be able to log messages which are hidden by default but can -be displayed via a preference (not currently possible with avoid console.{info,log,debug,warn,error}). -Log messages will be prefixed with the add-on's widget id and the log level is controlled by the -`shieldStudy.logLevel` preference. -Note that since there is no way to handle an arbitrarily variable number of arguments in the schema, -all values to log needs to be sent as a single variable. -Usage example: await browser.study.logger.log("foo"); -Usage example (multiple things to log): await browser.study.logger.log(["foo", bar]); - -## Functions - -### `browser.study.logger.info( values )` - -Corresponds to console.info - -**Parameters** - -* `values` - * type: values - * $ref: - * optional: false - -### `browser.study.logger.log( values )` - -Corresponds to console.log - -**Parameters** - -* `values` - * type: values - * $ref: - * optional: false - -### `browser.study.logger.debug( values )` - -Corresponds to console.debug - -**Parameters** - -* `values` - * type: values - * $ref: - * optional: false - -### `browser.study.logger.warn( values )` - -Corresponds to console.warn - -**Parameters** - -* `values` - * type: values - * $ref: - * optional: false - -### `browser.study.logger.error( values )` - -Corresponds to console.error - -**Parameters** - -* `values` - * type: values - * $ref: - * optional: false - -## Events - -(None) - -## Properties TBD - -## Data Types - -(None) - # Namespace: `browser.studyDebug` Interface for Test Utilities @@ -1040,67 +355,21 @@ Throws an exception from a privileged async function - for making sure that we c * $ref: * optional: false -### `browser.studyDebug.firstSeen( )` - -**Parameters** - -### `browser.studyDebug.setActive( )` - -**Parameters** - -### `browser.studyDebug.startup( details )` - -**Parameters** - -* `details` - * type: details - * $ref: - * optional: false - -### `browser.studyDebug.setFirstRunTimestamp( timestamp )` - -Set the pref for firstRunTimestamp, to simulate: - -* 2nd run -* other useful tests around expiration and states. - -**Parameters** - -* `timestamp` - * type: timestamp - * $ref: - * optional: false - -### `browser.studyDebug.reset( )` +### `browser.studyDebug.recordSeenTelemetry( )` -Reset the studyUtils \_internals, for debugging purposes. +Record seen study telemetry **Parameters** -### `browser.studyDebug.getInternals( )` - -Return `_internals` of the studyUtils object. - -Use this for debugging state. - -About `this._internals`: +### `browser.studyDebug.getSeenTelemetry( )` -* variation: (chosen variation, `setup` ) -* isEnding: bool `endStudy` -* isSetup: bool `setup` -* isFirstRun: bool `setup`, based on pref -* studySetup: bool `setup` the config -* seenTelemetry: array of seen telemetry. Fully populated only if studySetup.telemetry.internalTelemetryArchive is true -* prefs: object of all created prefs and their names +Return array of seen telemetry. Fully populated only if recordSeenTelemetry() has been run **Parameters** -### `browser.studyDebug.getInternalTestingOverrides( )` +### `browser.studyDebug.resetSeenTelemetry( )` -Returns an object with the following keys: -studyType - to be able to test add-ons with different studyType configurations -Used to override study testing flags in getStudySetup(). -The values are set by the corresponding preference under the `extensions.${widgetId}.test.*` preference branch. +Empty the array of seen telemetry **Parameters** diff --git a/webExtensionApis/study/schema.json b/webExtensionApis/study/schema.json index 21a418c..8804629 100644 --- a/webExtensionApis/study/schema.json +++ b/webExtensionApis/study/schema.json @@ -2,7 +2,7 @@ { "namespace": "study", "description": "Interface for Shield and Pioneer studies.", - "apiVersion": 5, + "apiVersion": 6, "types": [ { "id": "NullableString", @@ -92,212 +92,13 @@ "failcases": ["1234567890", "1234567890.123", []] }, { - "id": "studyTypesEnum", + "id": "telemetryPipelinesEnum", "$schema": "http://json-schema.org/draft-04/schema", "type": "string", "enum": ["shield", "pioneer"], "testcases": ["shield", "pioneer"], "failcases": ["foo"] }, - { - "id": "weightedVariationObject", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "weight": { - "type": "number", - "minimum": 0 - } - }, - "required": ["name", "weight"], - "testcase": { - "name": "feature-active", - "weight": 1.5 - } - }, - { - "id": "weightedVariationsArray", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "weight": { - "type": "number", - "minimum": 0 - } - }, - "required": ["name", "weight"] - }, - "testcase": [ - { - "name": "feature-active", - "weight": 1.5 - }, - { - "name": "feature-inactive", - "weight": 1.5 - } - ] - }, - { - "id": "anEndingRequest", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "properties": { - "fullname": { - "$ref": "NullableString", - "optional": true - }, - "category": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string", - "enum": ["ended-positive", "ended-neutral", "ended-negative"] - } - ], - "choices": [ - { - "type": "null" - }, - { - "type": "string", - "enum": ["ended-positive", "ended-neutral", "ended-negative"] - } - ], - "optional": true - }, - "baseUrls": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "choices": [ - { - "type": "null" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "optional": true, - "default": [] - }, - "exacturls": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "choices": [ - { - "type": "null" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "optional": "true\ndefault: []" - } - }, - "additionalProperties": true, - "testcases": [ - { - "baseUrls": ["some.url"], - "fullname": "anEnding", - "category": "ended-positive" - }, - {}, - { - "baseUrls": ["some.url"] - }, - { - "baseUrls": [], - "fullname": null, - "category": null - } - ], - "failcases": [ - { - "baseUrls": null, - "category": "not okay" - } - ] - }, - { - "id": "onEndStudyResponse", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "properties": { - "fields": { - "type": "object", - "additionalProperties": true - }, - "urls": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - { - "id": "studyInfoObject", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "additionalProperties": true, - "properties": { - "variation": { - "$ref": "weightedVariationObject" - }, - "firstRunTimestamp": { - "$ref": "NullableInteger" - }, - "activeExperimentName": { - "type": "string" - }, - "delayInMinutes": { - "$ref": "NullableNumber" - }, - "isFirstRun": { - "type": "boolean" - } - }, - "required": [ - "variation", - "firstRunTimestamp", - "activeExperimentName", - "isFirstRun" - ] - }, { "id": "dataPermissionsObject", "type": "object", @@ -312,220 +113,6 @@ }, "required": ["shield", "pioneer"] }, - { - "id": "studySetup", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "properties": { - "activeExperimentName": { - "type": "string" - }, - "studyType": { - "$ref": "studyTypesEnum" - }, - "expire": { - "type": "object", - "properties": { - "days": { - "type": "integer" - } - }, - "optional": true, - "additionalProperties": false - }, - "endings": { - "type": "object", - "additionalProperties": { - "$ref": "anEndingRequest" - } - }, - "weightedVariations": { - "$ref": "weightedVariationsArray" - }, - "telemetry": { - "type": "object", - "properties": { - "send": { - "type": "boolean" - }, - "removeTestingFlag": { - "type": "boolean" - }, - "internalTelemetryArchive": { - "optional": true, - "$ref": "NullableBoolean" - } - } - }, - "testing": { - "type": "object", - "properties": { - "variationName": { - "$ref": "NullableString", - "optional": true - }, - "firstRunTimestamp": { - "$ref": "NullableInteger", - "optional": true - }, - "expired": { - "choices": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ], - "oneOf": [ - { - "type": "null" - }, - { - "type": "boolean" - } - ], - "optional": true - } - }, - "additionalProperties": false, - "optional": true - } - }, - "required": [ - "activeExperimentName", - "studyType", - "endings", - "weightedVariations", - "telemetry" - ], - "additionalProperties": true, - "testcases": [ - { - "activeExperimentName": "aStudy", - "studyType": "shield", - "expire": { - "days": 10 - }, - "endings": { - "anEnding": { - "baseUrls": ["some.url"] - } - }, - "weightedVariations": [ - { - "name": "feature-active", - "weight": 1.5 - } - ], - "telemetry": { - "send": false, - "removeTestingFlag": false - } - }, - { - "activeExperimentName": "aStudy", - "studyType": "shield", - "expire": { - "days": 10 - }, - "endings": { - "anEnding": { - "baseUrls": ["some.url"] - } - }, - "weightedVariations": [ - { - "name": "feature-active", - "weight": 1.5 - } - ], - "telemetry": { - "send": false, - "removeTestingFlag": false, - "internalTelemetryArchive": false - }, - "testing": { - "variationName": "something", - "firstRunTimestamp": 1234567890, - "expired": true - } - }, - { - "activeExperimentName": "aStudy", - "studyType": "pioneer", - "endings": { - "anEnding": { - "baseUrls": ["some.url"] - } - }, - "weightedVariations": [ - { - "name": "feature-active", - "weight": 1.5 - } - ], - "telemetry": { - "send": false, - "removeTestingFlag": true, - "internalTelemetryArchive": true - }, - "testing": { - "variationName": "something", - "firstRunTimestamp": 1234567890, - "expired": true - } - }, - { - "activeExperimentName": - "shield-utils-test-addon@shield.mozilla.org", - "studyType": "shield", - "telemetry": { - "send": true, - "removeTestingFlag": false - }, - "endings": { - "user-disable": { - "baseUrls": ["http://www.example.com/?reason=user-disable"] - }, - "ineligible": { - "baseUrls": ["http://www.example.com/?reason=ineligible"] - }, - "expired": { - "baseUrls": ["http://www.example.com/?reason=expired"] - }, - "some-study-defined-ending": { - "category": "ended-neutral" - }, - "some-study-defined-ending-with-survey-url": { - "baseUrls": [ - "http://www.example.com/?reason=some-study-defined-ending-with-survey-url" - ], - "category": "ended-negative" - } - }, - "weightedVariations": [ - { - "name": "feature-active", - "weight": 1.5 - }, - { - "name": "feature-passive", - "weight": 1.5 - }, - { - "name": "control", - "weight": 1 - } - ], - "expire": { - "days": 14 - }, - "testing": {}, - "allowEnroll": true - } - ] - }, { "id": "telemetryPayload", "$schema": "http://json-schema.org/draft-04/schema", @@ -567,74 +154,9 @@ "minimumTimestamp": 1523968204184, "headersOnly": false } - }, - { - "id": "anEndingAnswer", - "$schema": "http://json-schema.org/draft-04/schema", - "type": "object", - "additionalProperties": true } ], "functions": [ - { - "name": "setup", - "type": "function", - "async": true, - "description": - "Attempt an setup/enrollment, with these effects:\n\n- sets 'studyType' as Shield or Pioneer\n - affects telemetry\n - (5.2+ TODO) watches for dataPermission changes that should *always*\n stop that kind of study\n\n- Use or choose variation\n - `testing.variation` if present\n - OR (internal) deterministicVariation\n from `weightedVariations`\n based on hash of\n\n - activeExperimentName\n - clientId\n\n- During firstRun[1] only:\n - set firstRunTimestamp pref value\n - send 'enter' ping\n - if `allowEnroll`, send 'install' ping\n - else endStudy(\"ineligible\") and return\n\n- Every Run\n - setActiveExperiment(studySetup)\n - monitor shield | pioneer permission endings\n - suggests alarming if `expire` is set.\n\nReturns:\n- studyInfo object (see `getStudyInfo`)\n\nTelemetry Sent (First run only)\n\n - enter\n - install\n\nFires Events\n\n(At most one of)\n- study:onReady OR\n- study:onEndStudy\n\nPreferences set\n- `shield.${runtime.id}.firstRunTimestamp`\n\nNote:\n1. allowEnroll is ONLY used during first run (install)\n", - "parameters": [ - { - "name": "studySetup", - "$ref": "studySetup" - } - ], - "returns": [ - { - "$ref": "studyInfoObject" - } - ] - }, - { - "name": "endStudy", - "type": "function", - "async": true, - "defaultReturn": { - "urls": ["url1", "url2"], - "endingName": "some-reason" - }, - "description": - "Signal to browser.study that it should end.\n\nUsage scenarios:\n- add-ons defined\n - positive endings (tried feature)\n - negative endings (client clicked 'no thanks')\n - expiration / timeout (feature should last for 14 days then uninstall)\n\nLogic:\n- If study has already ended, do nothing.\n- Else: END\n\nEND:\n- record internally that study is ended.\n- disable all methods that rely on configuration / setup.\n- clear all prefs stored by `browser.study`\n- fire telemetry pings for:\n - 'exit'\n - the ending, one of:\n\n \"ineligible\",\n \"expired\",\n \"user-disable\",\n \"ended-positive\",\n \"ended-neutral\",\n \"ended-negative\",\n\n- augment all ending URLs with query URLs\n- fire 'study:end' event to `browser.study.onEndStudy` handlers.\n\nAdd-on should then do\n- open returned URLs\n- feature specific cleanup\n- uninstall the add-on\n\nNote:\n1. calling this function multiple time is safe.\n`browser.study` will choose the\n", - "parameters": [ - { - "name": "anEndingAlias", - "type": "string" - } - ], - "returns": [ - { - "$ref": "anEndingAnswer" - } - ] - }, - { - "name": "getStudyInfo", - "type": "function", - "async": true, - "description": - "current study configuration, including\n- variation\n- activeExperimentName\n- delayInMinutes\n- firstRunTimestamp\n- isFirstRun\n\nBut not:\n- telemetry clientId\n\nThrows Error if called before `browser.study.setup`\n", - "defaultReturn": { - "variation": "styleA", - "firstRunTimestamp": 1523968204184, - "activeExperimentName": "some experiment", - "delayInMinutes": 12 - }, - "parameters": [], - "returns": [ - { - "$ref": "studyInfoObject" - } - ] - }, { "name": "getDataPermissions", "type": "function", @@ -662,6 +184,10 @@ { "name": "payload", "$ref": "telemetryPayload" + }, + { + "name": "telemetryPipeline", + "$ref": "telemetryPipelinesEnum" } ], "defaultReturn": "undefined", @@ -677,6 +203,10 @@ { "name": "payload", "$ref": "telemetryPayload" + }, + { + "name": "telemetryPipeline", + "$ref": "telemetryPipelinesEnum" } ], "defaultReturn": "undefined", @@ -704,14 +234,6 @@ } ] }, - { - "name": "getTestingOverrides", - "type": "function", - "async": true, - "description": - "Returns an object with the following keys:\n variationName - to be able to test specific variations\n firstRunTimestamp - to be able to test the expiration event\n expired - to be able to test the behavior of an already expired study\nUsed to override study testing flags in getStudySetup().\nThe values are set by the corresponding preference under the `extensions.${widgetId}.test.*` preference branch.\n", - "parameters": [] - }, { "name": "validateJSON", "type": "function", @@ -751,6 +273,10 @@ { "name": "reason", "type": "string" + }, + { + "name": "telemetryPipeline", + "$ref": "telemetryPipelinesEnum" } ], "returns": [ @@ -772,107 +298,6 @@ } ] } - ], - "events": [ - { - "name": "onReady", - "type": "function", - "defaultReturn": { - "variation": "styleA", - "firstRunTimestamp": 1523968204184 - }, - "description": - "Fires when the study is 'ready' for the feature to startup.", - "parameters": [ - { - "name": "studyInfo", - "type": "object" - } - ] - }, - { - "name": "onEndStudy", - "type": "function", - "defaultReturn": { - "urls": [], - "reason": "some-reason" - }, - "description": - "Listen for when the study wants to end.\n\nAct on it by\n- opening surveyUrls\n- tearing down your feature\n- uninstalling the add-on\n", - "parameters": [ - { - "name": "ending", - "type": "object" - } - ] - } - ] - }, - { - "namespace": "study.logger", - "description": - "For study developers to be able to log messages which are hidden by default but can\nbe displayed via a preference (not currently possible with avoid console.{info,log,debug,warn,error}).\nLog messages will be prefixed with the add-on's widget id and the log level is controlled by the\n`shieldStudy.logLevel` preference.\nNote that since there is no way to handle an arbitrarily variable number of arguments in the schema,\nall values to log needs to be sent as a single variable.\nUsage example: await browser.study.logger.log(\"foo\");\nUsage example (multiple things to log): await browser.study.logger.log([\"foo\", bar]);\n", - "functions": [ - { - "name": "info", - "type": "function", - "async": true, - "description": "Corresponds to console.info", - "parameters": [ - { - "name": "values", - "type": "any" - } - ] - }, - { - "name": "log", - "type": "function", - "async": true, - "description": "Corresponds to console.log", - "parameters": [ - { - "name": "values", - "type": "any" - } - ] - }, - { - "name": "debug", - "type": "function", - "async": true, - "description": "Corresponds to console.debug", - "parameters": [ - { - "name": "values", - "type": "any" - } - ] - }, - { - "name": "warn", - "type": "function", - "async": true, - "description": "Corresponds to console.warn", - "parameters": [ - { - "name": "values", - "type": "any" - } - ] - }, - { - "name": "error", - "type": "function", - "async": true, - "description": "Corresponds to console.error", - "parameters": [ - { - "name": "values", - "type": "any" - } - ] - } ] }, { @@ -907,68 +332,25 @@ ] }, { - "name": "firstSeen", - "type": "function", - "async": true, - "description": "", - "parameters": [] - }, - { - "name": "setActive", - "type": "function", - "async": true, - "description": "", - "parameters": [] - }, - { - "name": "startup", - "type": "function", - "async": true, - "description": "", - "parameters": [ - { - "name": "details", - "type": "object", - "additionalProperties": true - } - ] - }, - { - "name": "setFirstRunTimestamp", - "type": "function", - "async": true, - "description": - "Set the pref for firstRunTimestamp, to simulate:\n- 2nd run\n- other useful tests around expiration and states.\n", - "parameters": [ - { - "name": "timestamp", - "type": "number", - "minimum": 1 - } - ] - }, - { - "name": "reset", + "name": "recordSeenTelemetry", "type": "function", "async": true, - "description": - "\nReset the studyUtils _internals, for debugging purposes.\n", + "description": "Record seen study telemetry", "parameters": [] }, { - "name": "getInternals", + "name": "getSeenTelemetry", "type": "function", "async": true, "description": - "Return `_internals` of the studyUtils object.\n\nUse this for debugging state.\n\nAbout `this._internals`:\n- variation: (chosen variation, `setup` )\n- isEnding: bool `endStudy`\n- isSetup: bool `setup`\n- isFirstRun: bool `setup`, based on pref\n- studySetup: bool `setup` the config\n- seenTelemetry: array of seen telemetry. Fully populated only if studySetup.telemetry.internalTelemetryArchive is true\n- prefs: object of all created prefs and their names\n", + "Return array of seen telemetry. Fully populated only if recordSeenTelemetry() has been run", "parameters": [] }, { - "name": "getInternalTestingOverrides", + "name": "resetSeenTelemetry", "type": "function", "async": true, - "description": - "Returns an object with the following keys:\n studyType - to be able to test add-ons with different studyType configurations\nUsed to override study testing flags in getStudySetup().\nThe values are set by the corresponding preference under the `extensions.${widgetId}.test.*` preference branch.\n", + "description": "Empty the array of seen telemetry", "parameters": [] } ] diff --git a/webExtensionApis/study/schema.yaml b/webExtensionApis/study/schema.yaml index f4ee388..b5d8bc9 100644 --- a/webExtensionApis/study/schema.yaml +++ b/webExtensionApis/study/schema.yaml @@ -1,28 +1,6 @@ -# Interface schema for `study` -# https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/schema.html -# -# - properties -# - functions -# - events -# - types -# -# Note: JSONSchema for WEE interfaces is a modified version of Draft-03. -# -# Note: possible `types` are here -# - https://dxr.mozilla.org/mozilla-central/source/toolkit/components/extensions/Schemas.jsm#2417-2427 -# - type property: -# boolean, integer, number, string, array, object, or any. - -# -# Note: "choices" is a non-standard extension to draft-03, see: -# - https://dxr.mozilla.org/mozilla-central/source/toolkit/components/extensions/Schemas.jsm#2875-2879 -# - - ---- - namespace: study description: Interface for Shield and Pioneer studies. - apiVersion: 5 # for dev use + apiVersion: 6 # for dev use types: - id: NullableString $schema: "http://json-schema.org/draft-04/schema" @@ -67,119 +45,13 @@ testcases: [null, 1234567890, 1234567890.123] failcases: ['1234567890', '1234567890.123', []] - - id: studyTypesEnum + - id: telemetryPipelinesEnum $schema: "http://json-schema.org/draft-04/schema" type: string enum: ['shield', 'pioneer'] testcases: ['shield', 'pioneer'] failcases: ['foo'] - - id: weightedVariationObject - $schema: "http://json-schema.org/draft-04/schema" - type: 'object' - properties: - name: - type: "string" - weight: - type: "number" - minimum: 0 - required: ["name", "weight"] - testcase: {name: feature-active, weight: 1.5} - - - id: weightedVariationsArray - $schema: "http://json-schema.org/draft-04/schema" - type: array - items: - # FIXME, this is a repeat of weightedVariationObject - # for unknown reasons probably around id, deref isn't working right - type: 'object' - properties: - name: - type: "string" - weight: - type: "number" - minimum: 0 - required: ["name", "weight"] - testcase: [{name: feature-active, weight: 1.5},{name: feature-inactive, weight: 1.5}] - - - id: anEndingRequest - $schema: "http://json-schema.org/draft-04/schema" - type: object - properties: - fullname: - $ref: NullableString - optional: true - category: - oneOf: [ - {type: 'null'}, - {type: 'string', enum: ['ended-positive', 'ended-neutral', 'ended-negative']}] - choices: [ - {type: 'null'}, - {type: 'string', enum: ['ended-positive', 'ended-neutral', 'ended-negative']}] - optional: true - baseUrls: - oneOf: [ - {type: 'null'}, - {type: array, items: {type: 'string'}}] - choices: [ - {type: 'null'}, - {type: array, items: {type: 'string'}}] - optional: true - default: [] - exacturls: - oneOf: [ - {type: 'null'}, - {type: array, items: {type: 'string'}}] - choices: [ - {type: 'null'}, - {type: array, items: {type: 'string'}}] - optional: true - default: [] - additionalProperties: true - testcases: [ - {baseUrls: ['some.url'], fullname: 'anEnding', category: 'ended-positive'}, - {}, - {baseUrls: ['some.url']}, - {baseUrls: [], fullname: null, category: null}, - ] - failcases: [ - {baseUrls: null, category: "not okay"}, - ] - - - id: onEndStudyResponse - $schema: "http://json-schema.org/draft-04/schema" - type: object - properties: - fields: - type: object - additionalProperties: true - urls: - type: 'array' - items: - type: 'string' - - - id: studyInfoObject - $schema: "http://json-schema.org/draft-04/schema" - type: object - additionalProperties: true - properties: - variation: - $ref: "weightedVariationObject" - firstRunTimestamp: - $ref: NullableInteger # 1523968204184, or null if the study has not started yet - activeExperimentName: - type: string # some experiment" - delayInMinutes: - $ref: NullableNumber # 123.456, or null if the study has not started yet - isFirstRun: - type: 'boolean' - - required: - - variation - - firstRunTimestamp - - activeExperimentName - - isFirstRun - - id: dataPermissionsObject type: object additionalProperties: false @@ -195,97 +67,6 @@ - shield - pioneer - - id: studySetup - $schema: "http://json-schema.org/draft-04/schema" - type: object - properties: - activeExperimentName: - type: string - studyType: - $ref: studyTypesEnum - expire: - type: 'object' - properties: - days: - type: 'integer' - optional: true - additionalProperties: false - endings: - type: object - additionalProperties: - $ref: anEndingRequest - weightedVariations: - $ref: 'weightedVariationsArray' - telemetry: - type: object - properties: - send: - type: boolean - removeTestingFlag: - type: boolean - internalTelemetryArchive: - optional: true - $ref: NullableBoolean - testing: - type: object - properties: - variationName: - $ref: NullableString - optional: true - firstRunTimestamp: - $ref: NullableInteger - optional: true - expired: - choices: [{type: 'null'}, {type: 'boolean'}] - oneOf: [{type: 'null'}, {type: 'boolean'}] - optional: true - additionalProperties: false - optional: true - - required: - - activeExperimentName - - studyType - - endings - - weightedVariations - - telemetry - additionalProperties: true - testcases: [ - { - activeExperimentName: aStudy, - studyType: 'shield', - expire: { "days": 10}, - endings: {anEnding: {baseUrls: ['some.url']}}, - weightedVariations: [{name: feature-active, weight: 1.5}], - telemetry: { send: false, removeTestingFlag: false} - }, - { - activeExperimentName: aStudy, - studyType: 'shield', - expire: { "days": 10}, - endings: {anEnding: {baseUrls: ['some.url']}}, - weightedVariations: [{name: feature-active, weight: 1.5}], - telemetry: { send: false, removeTestingFlag: false, internalTelemetryArchive: false}, - testing: { - variationName: "something", - firstRunTimestamp: 1234567890, - expired: true, - } - }, - { - activeExperimentName: aStudy, - studyType: 'pioneer', - endings: {anEnding: {baseUrls: ['some.url']}}, - weightedVariations: [{name: feature-active, weight: 1.5}], - telemetry: { send: false, removeTestingFlag: true, internalTelemetryArchive: true}, - testing: { - variationName: "something", - firstRunTimestamp: 1234567890, - expired: true, - } - }, - {"activeExperimentName":"shield-utils-test-addon@shield.mozilla.org","studyType":"shield","telemetry":{"send":true,"removeTestingFlag":false},"endings":{"user-disable":{"baseUrls":["http://www.example.com/?reason=user-disable"]},"ineligible":{"baseUrls":["http://www.example.com/?reason=ineligible"]},"expired":{"baseUrls":["http://www.example.com/?reason=expired"]},"some-study-defined-ending":{"category":"ended-neutral"},"some-study-defined-ending-with-survey-url":{"baseUrls":["http://www.example.com/?reason=some-study-defined-ending-with-survey-url"],"category":"ended-negative"}},"weightedVariations":[{"name":"feature-active","weight":1.5},{"name":"feature-passive","weight":1.5},{"name":"control","weight":1}],"expire":{"days":14},"testing":{},"allowEnroll":true} - ] - - id: telemetryPayload $schema: "http://json-schema.org/draft-04/schema" type: object @@ -303,144 +84,7 @@ additionalProperties: false testcase: {type: ['shield-study-addon', 'shield-study'], n: 100, minimumTimestamp: 1523968204184, headersOnly: false} - - id: anEndingAnswer - $schema: "http://json-schema.org/draft-04/schema" - type: object - additionalProperties: true - functions: - - name: setup - type: function - async: true - description: | - Attempt an setup/enrollment, with these effects: - - - sets 'studyType' as Shield or Pioneer - - affects telemetry - - (5.2+ TODO) watches for dataPermission changes that should *always* - stop that kind of study - - - Use or choose variation - - `testing.variation` if present - - OR (internal) deterministicVariation - from `weightedVariations` - based on hash of - - - activeExperimentName - - clientId - - - During firstRun[1] only: - - set firstRunTimestamp pref value - - send 'enter' ping - - if `allowEnroll`, send 'install' ping - - else endStudy("ineligible") and return - - - Every Run - - setActiveExperiment(studySetup) - - monitor shield | pioneer permission endings - - suggests alarming if `expire` is set. - - Returns: - - studyInfo object (see `getStudyInfo`) - - Telemetry Sent (First run only) - - - enter - - install - - Fires Events - - (At most one of) - - study:onReady OR - - study:onEndStudy - - Preferences set - - `shield.${runtime.id}.firstRunTimestamp` - - Note: - 1. allowEnroll is ONLY used during first run (install) - - parameters: - - name: studySetup - $ref: studySetup - - returns: - - $ref: studyInfoObject - - - name: endStudy - type: function - async: true - defaultReturn: {urls: ['url1','url2'], endingName:'some-reason'} - description: | - Signal to browser.study that it should end. - - Usage scenarios: - - add-ons defined - - positive endings (tried feature) - - negative endings (client clicked 'no thanks') - - expiration / timeout (feature should last for 14 days then uninstall) - - Logic: - - If study has already ended, do nothing. - - Else: END - - END: - - record internally that study is ended. - - disable all methods that rely on configuration / setup. - - clear all prefs stored by `browser.study` - - fire telemetry pings for: - - 'exit' - - the ending, one of: - - "ineligible", - "expired", - "user-disable", - "ended-positive", - "ended-neutral", - "ended-negative", - - - augment all ending URLs with query URLs - - fire 'study:end' event to `browser.study.onEndStudy` handlers. - - Add-on should then do - - open returned URLs - - feature specific cleanup - - uninstall the add-on - - Note: - 1. calling this function multiple time is safe. - `browser.study` will choose the - - parameters: - - name: anEndingAlias - type: 'string' - - returns: - - $ref: anEndingAnswer - - - ## study / client information things - - name: getStudyInfo - type: function - async: true - description: | - current study configuration, including - - variation - - activeExperimentName - - delayInMinutes - - firstRunTimestamp - - isFirstRun - - But not: - - telemetry clientId - - Throws Error if called before `browser.study.setup` - - defaultReturn: {variation: "styleA", firstRunTimestamp: 1523968204184, activeExperimentName: "some experiment", delayInMinutes: 12} - parameters: [] - returns: - - $ref: studyInfoObject - - name: getDataPermissions type: function async: true @@ -468,6 +112,8 @@ parameters: - name: payload $ref: telemetryPayload + - name: telemetryPipeline + $ref: telemetryPipelinesEnum defaultReturn: undefined # exception if out of policy based on config returns: @@ -487,6 +133,8 @@ parameters: - name: payload $ref: telemetryPayload + - name: telemetryPipeline + $ref: telemetryPipelinesEnum defaultReturn: undefined returns: @@ -520,18 +168,6 @@ # utilities - - name: getTestingOverrides - type: 'function' - async: true - description: | - Returns an object with the following keys: - variationName - to be able to test specific variations - firstRunTimestamp - to be able to test the expiration event - expired - to be able to test the behavior of an already expired study - Used to override study testing flags in getStudySetup(). - The values are set by the corresponding preference under the `extensions.${widgetId}.test.*` preference branch. - parameters: [] - - name: validateJSON type: function async: true @@ -556,6 +192,8 @@ type: string - name: reason type: string + - name: telemetryPipeline + $ref: telemetryPipelinesEnum # aValidation returns: @@ -566,99 +204,6 @@ errors: - type: array - # things that would be 'listeners' are 'events' in webExtensions - # https://github.com/motin/shield-studies-addon-template/blob/convert-to-webextension-experiments/src/privileged/introductionNotificationBar/api.js#L107 - # https://github.com/motin/shield-studies-addon-template/blob/convert-to-webextension-experiments/src/privileged/introductionNotificationBar/schema.json#L15 - - # https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/background.html#javascript-apis - # https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/events.html - # https://dxr.mozilla.org/mozilla-central/source/toolkit/components/extensions/parent/ext-runtime.js#41 - #https://dxr.mozilla.org/mozilla-central/source/toolkit/components/extensions/ExtensionCommon.jsm?q=file%3AExtensionCommon.jsm&redirect_type=single#1673 - - events: - - name: onReady - type: function - defaultReturn: {variation: 'styleA', firstRunTimestamp: 1523968204184} - description: Fires when the study is 'ready' for the feature to startup. - parameters: # for the callback - - name: studyInfo - type: object - - - name: onEndStudy - type: function - defaultReturn: {urls: [], reason: 'some-reason'} - description: | - Listen for when the study wants to end. - - Act on it by - - opening surveyUrls - - tearing down your feature - - uninstalling the add-on - - parameters: # for the callback - - name: ending - type: object - - # TODO 5.2+ - # - name: onDataPermissionsChange - # type: function - # defaultReturn: {shield: true, pioneer: false} - # description: Fires whenever any 'dataPermission' changes, with the new dataPermission object. Allows watching for shield or pioneer revocation. - # parameters: # for the callback - # - name: updatedPermissions - # type: object - -- namespace: study.logger - description: | - For study developers to be able to log messages which are hidden by default but can - be displayed via a preference (not currently possible with avoid console.{info,log,debug,warn,error}). - Log messages will be prefixed with the add-on's widget id and the log level is controlled by the - `shieldStudy.logLevel` preference. - Note that since there is no way to handle an arbitrarily variable number of arguments in the schema, - all values to log needs to be sent as a single variable. - Usage example: await browser.study.logger.log("foo"); - Usage example (multiple things to log): await browser.study.logger.log(["foo", bar]); - functions: - - name: info - type: function - async: true - description: Corresponds to console.info - parameters: - - name: values - type: 'any' - - - name: log - type: function - async: true - description: Corresponds to console.log - parameters: - - name: values - type: 'any' - - - name: debug - type: function - async: true - description: Corresponds to console.debug - parameters: - - name: values - type: 'any' - - - name: warn - type: function - async: true - description: Corresponds to console.warn - parameters: - - name: values - type: 'any' - - - name: error - type: function - async: true - description: Corresponds to console.error - parameters: - - name: values - type: 'any' - - namespace: studyDebug description: Interface for Test Utilities apiVersion: 5 # for dev use @@ -679,74 +224,20 @@ - name: message type: string - - name: firstSeen + - name: recordSeenTelemetry type: function async: true - description: '' + description: Record seen study telemetry parameters: [] - - name: setActive + - name: getSeenTelemetry type: function async: true - description: '' + description: Return array of seen telemetry. Fully populated only if recordSeenTelemetry() has been run parameters: [] - - name: startup + - name: resetSeenTelemetry type: function async: true - description: '' - parameters: - - name: details - type: object - additionalProperties: true - - - name: setFirstRunTimestamp - type: function - async: true - description: | - Set the pref for firstRunTimestamp, to simulate: - - 2nd run - - other useful tests around expiration and states. - - parameters: - - name: timestamp - type: number - minimum: 1 - - - name: reset - type: function - async: true - description: | - - Reset the studyUtils _internals, for debugging purposes. - - parameters: [] - - - name: getInternals - type: function - async: true - description: | - Return `_internals` of the studyUtils object. - - Use this for debugging state. - - About `this._internals`: - - variation: (chosen variation, `setup` ) - - isEnding: bool `endStudy` - - isSetup: bool `setup` - - isFirstRun: bool `setup`, based on pref - - studySetup: bool `setup` the config - - seenTelemetry: array of seen telemetry. Fully populated only if studySetup.telemetry.internalTelemetryArchive is true - - prefs: object of all created prefs and their names - - parameters: [] - - - name: getInternalTestingOverrides - type: 'function' - async: true - description: | - Returns an object with the following keys: - studyType - to be able to test add-ons with different studyType configurations - Used to override study testing flags in getStudySetup(). - The values are set by the corresponding preference under the `extensions.${widgetId}.test.*` preference branch. + description: Empty the array of seen telemetry parameters: [] diff --git a/webExtensionApis/study/src/index.js b/webExtensionApis/study/src/index.js index 686eb31..b0912a5 100644 --- a/webExtensionApis/study/src/index.js +++ b/webExtensionApis/study/src/index.js @@ -1,43 +1,13 @@ /* eslint-env commonjs */ -/* eslint no-logger: off */ +/* eslint no-unused-vars: off */ +/* eslint no-console: ["warn", { allow: ["info", "warn", "error"] }] */ /* global ExtensionAPI */ -/** 1. Provides the WebExtension Experiment `getApi` - * 2. Handles 'user-disable' telemetry. - * 3. Does NOT handle 'user-disable' surveys, see #194 - */ +"use strict"; -import { utilsLogger, createLogger } from "./logger"; -import makeWidgetId from "./makeWidgetId"; -import * as testingOverrides from "./testingOverrides"; -import * as dataPermissions from "./dataPermissions"; - -ChromeUtils.import("resource://gre/modules/ExtensionCommon.jsm"); -ChromeUtils.import("resource://gre/modules/ExtensionUtils.jsm"); - -utilsLogger.debug("loading web extension experiment study/api.js"); - -/* eslint-disable no-undef */ -const { EventManager } = ExtensionCommon; -const { ExtensionError } = ExtensionUtils; -const EventEmitter = - ExtensionCommon.EventEmitter || ExtensionUtils.EventEmitter; - -/** Event emitter to handle Events defined in the API - * - * - onReady - * - onEndStudy - * - */ -class StudyApiEventEmitter extends EventEmitter { - emitReady(studyInfo) { - this.emit("ready", studyInfo); - } - - emitEndStudy(endingResponse) { - this.emit("endStudy", endingResponse); - } -} +import { utilsLogger } from "./logger"; +import { studyUtils } from "./studyUtils"; +import { getDataPermissions } from "./dataPermissions"; /** Implements the study/getApi for `browser.study` API */ this.study = class extends ExtensionAPI { @@ -54,36 +24,9 @@ this.study = class extends ExtensionAPI { * @type Extension */ this.extension = extension; - this.studyApiEventEmitter = new StudyApiEventEmitter(); utilsLogger.debug("constructed!"); } - /** - * Extension Uninstall - * APIs that allocate any resources (e.g., adding elements to the browser’s - * user interface, setting up internal event listeners, etc.) must free - * these resources when the extension for which they are allocated is - * shut down. - * - * https://searchfox.org/mozilla-central/source/toolkit/components/extensions/parent/ext-protocolHandlers.js#46 - * - * @param {string} shutdownReason one of the reasons - * @returns {undefined} - */ - async onShutdown(shutdownReason) { - utilsLogger.debug("possible uninstalling", shutdownReason); - if ( - shutdownReason === "ADDON_UNINSTALL" || - shutdownReason === "ADDON_DISABLE" - ) { - utilsLogger.debug("definitely uninstall | disable", shutdownReason); - const anEndingAlias = "user-disable"; - const endingResponse = await this.studyUtils.endStudy(anEndingAlias); - // See #194, getApi is already torn down, so cannot hear it. - await this.studyApiEventEmitter.emitEndStudy(endingResponse); - } - } - /** * @param {object} context the add-on context * @returns {object} api with study, studyDebug keys @@ -91,216 +34,23 @@ this.study = class extends ExtensionAPI { getAPI(context) { const { extension } = this; - // Load studyUtils - const { studyUtils } = require("./studyUtils.js"); + const { ExtensionUtils } = ChromeUtils.import( + "resource://gre/modules/ExtensionUtils.jsm", + {}, + ); - // Make studyUtils available for onShutdown handler - this.studyUtils = studyUtils; + utilsLogger.debug("loading web extension experiment study/api.js"); - /* eslint no-shadow: off */ - const { studyApiEventEmitter } = this; + /* eslint-disable no-undef */ + const { ExtensionError } = ExtensionUtils; - // once. Used for pref naming, telemetry + // Used for pref naming, telemetry studyUtils.setExtensionManifest(extension.manifest); - studyUtils._internals = studyUtils._createInternals(); - - // for add-on logging via browser.study.logger.log() - const widgetId = makeWidgetId(extension.manifest.applications.gecko.id); - const addonLogger = createLogger(widgetId, `shieldStudy.logLevel`); - - async function endStudy(anEndingAlias) { - utilsLogger.debug("called endStudy with anEndingAlias:", anEndingAlias); - const endingResponse = await studyUtils.endStudy(anEndingAlias); - studyApiEventEmitter.emitEndStudy(endingResponse); - } - - // Add normandy unenroll listener - const { AddonStudies } = ChromeUtils.import( - "resource://normandy/lib/AddonStudies.jsm", - {}, - ); - AddonStudies.addUnenrollListener(extension.id, async reason => { - utilsLogger.debug( - "AddonStudies.addUnenrollListener fired with reason:", - reason, - ); - await endStudy(reason); - // Normandy will wait until this promise resolves before uninstalling the add-on - // We need to give the add-on a chance to do its clean-up after receiving the endStudy event above - // Note that the add-on uninstalls by itself upon the endStudy event - utilsLogger.debug( - "Stalling for a few seconds before allowing Normandy to uninstall the add-on", - ); - await new Promise(resolve => { - const id = setTimeout(() => { - clearTimeout(id); - resolve(); - }, 5 * 1000); - }); - }); return { study: { - /** Attempt an setup/enrollment, with these effects: - * - * - sets 'studyType' as Shield or Pioneer - * - affects telemetry - * - watches for dataPermission changes that should *always* - * stop that kind of study - * - * - Use or choose variation - * - `testing.variation` if present - * - OR deterministicVariation - * for the studyType using `weightedVariations` - * - * - During firstRun[1] only: - * - set firstRunTimestamp pref value - * - send 'enter' ping - * - if `allowEnroll`, send 'install' ping - * - else endStudy("ineligible") and return - * - * - Every Run - * - setActiveExperiment(studySetup) - * - monitor shield | pioneer permission endings - * - suggests alarming if `expire` is set. - * - * Returns: - * - studyInfo object (see `getStudyInfo`) - * - * Telemetry Sent (First run only) - * - * - enter - * - install - * - * Fires Events - * - * (At most one of) - * - study:onReady OR - * - study:onEndStudy - * - * Preferences set - * - `shield.${runtime.id}.firstRunTimestamp` - * - * Note: - * 1. allowEnroll is ONLY used during first run (install) - * - * @param {Object} studySetup See API.md - * @returns {Object} studyInfo. See studyInfo - **/ - setup: async function setup(studySetup) { - // 0. testing overrides, if any - if (!studySetup.testing) { - studySetup.testing = {}; - } - - // Setup and sets the variation / _internals - // includes possible 'firstRun' handling. - await studyUtils.setup(studySetup); - - // current studyInfo. - let studyInfo = studyUtils.info(); - - // Check if the user is eligible to run this study using the |isEligible| - // function when the study is initialized - if (studyInfo.isFirstRun) { - if (!studySetup.allowEnroll) { - utilsLogger.debug("User is ineligible, ending study."); - // 1. uses studySetup.endings.ineligible.url if any, - // 2. sends UT for "ineligible" - // 3. then uninstalls add-on - await endStudy("ineligible"); - return studyUtils.info(); - } - } - - if (studyInfo.delayInMinutes === 0) { - utilsLogger.debug("encountered already expired study"); - await endStudy("expired"); - return studyUtils.info(); - } - - /* - * Adds the study to the active list of telemetry experiments, - * and sends the "installed" telemetry ping if applicable, - * if it's a firstRun - */ - await studyUtils.startup(); - - // update what the study variation and other info is. - studyInfo = studyUtils.info(); - utilsLogger.debug(`api info: ${JSON.stringify(studyInfo)}`); - try { - studyApiEventEmitter.emitReady(studyInfo); - } catch (e) { - utilsLogger.error("browser.study.setup error"); - utilsLogger.error(e); - } - return studyUtils.info(); - }, - - /* Signal to browser.study that it should end. - * - * Usage scenarios: - * - add-ons defined - * - postive endings (tried feature) - * - negative endings (client clicked 'no thanks') - * - expiration / timeout (feature should last for 14 days then uninstall) - * - * Logic: - * - If study has already ended, do nothing. - * - Else: END - * - * END: - * - record internally that study is ended. - * - disable all methods that rely on configuration / setup. - * - clear all prefs stored by `browser.study` - * - fire telemetry pings for: - * - 'exit' - * - the ending, one of: - * - * "ineligible", - * "expired", - * "user-disable", - * "ended-positive", - * "ended-neutral", - * "ended-negative", - * - * - augment all ending urls with query urls - * - fire 'study:end' event to `browser.study.onEndStudy` handlers. - * - * Addon should then do - * - open returned urls - * - feature specific cleanup - * - uninstall the add-on - * - * Note: - * 1. calling this function multiple time is safe. - * `browser.study` will choose the first in. - * 2. the 'user-disable' case is handled above - * 3. throws if the endStudy fails - **/ - endStudy, - - /* current study configuration, including - * - variation - * - activeExperimentName - * - delayInMinutes - * - firstRunTimestamp - * - * But not: - * - telemetry clientId - * - * Throws ExtensionError if called before `browser.study.setup` - **/ - getStudyInfo: async function getStudyInfo() { - utilsLogger.debug("called getStudyInfo "); - return studyUtils.info(); - }, - /* Object of current dataPermissions (shield enabled true/false, pioneer enabled true/false) */ - getDataPermissions: async function getDataPermissions() { - return dataPermissions.getDataPermissions(); - }, + getDataPermissions, /** Send Telemetry using appropriate shield or pioneer methods. * @@ -320,9 +70,13 @@ this.study = class extends ExtensionAPI { * TBD fix the parameters here. * * @param {Object} payload Non-nested object with key strings, and key values + * @param {string} telemetryPipeline - the telemetry pipeline * @returns {undefined} */ - sendTelemetry: async function sendTelemetry(payload) { + sendTelemetry: async function sendTelemetry( + payload, + telemetryPipeline, + ) { utilsLogger.debug("called sendTelemetry payload"); function throwIfInvalid(obj) { @@ -337,7 +91,15 @@ this.study = class extends ExtensionAPI { } throwIfInvalid(payload); - return studyUtils.telemetry(payload); + utilsLogger.debug("valid telemetry payload"); + + try { + return studyUtils.telemetry(payload, telemetryPipeline); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } }, /** Calculate Telemetry using appropriate shield or pioneer methods. @@ -349,12 +111,23 @@ this.study = class extends ExtensionAPI { * - Calculate the size of a ping that has Pioneer encrypted data * * @param {Object} payload Non-nested object with key strings, and key values + * @param {string} telemetryPipeline - the telemetry pipeline * @returns {Promise} The total size of the ping. */ calculateTelemetryPingSize: async function calculateTelemetryPingSize( payload, + telemetryPipeline, ) { - return studyUtils.calculateTelemetryPingSize(payload); + try { + return studyUtils.calculateTelemetryPingSize( + payload, + telemetryPipeline, + ); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } }, /** Search locally stored telemetry pings using these fields (if set) @@ -378,137 +151,85 @@ this.study = class extends ExtensionAPI { * @returns {Array} matchingPings */ async searchSentTelemetry(searchTelemetryQuery) { - const { TelemetryArchive } = ChromeUtils.import( - "resource://gre/modules/TelemetryArchive.jsm", - {}, - ); - const { searchTelemetryArchive } = require("./telemetry.js"); - return searchTelemetryArchive(TelemetryArchive, searchTelemetryQuery); + try { + const { TelemetryArchive } = ChromeUtils.import( + "resource://gre/modules/TelemetryArchive.jsm", + {}, + ); + const { searchTelemetryArchive } = require("./telemetry.js"); + return searchTelemetryArchive( + TelemetryArchive, + searchTelemetryQuery, + ); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } }, /* Using AJV, do jsonschema validation of an object. Can be used to validate your arguments, packets at client. */ validateJSON: async function validateJSON(someJson, jsonschema) { - utilsLogger.debug("called validateJSON someJson, jsonschema"); - return studyUtils.jsonschema.validate(someJson, jsonschema); - // return { valid: true, errors: [] }; + try { + utilsLogger.debug("called validateJSON someJson, jsonschema"); + return studyUtils.jsonschema.validate(someJson, jsonschema); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } }, /* Annotates the supplied survey base url with common survey parameters (study name, variation, updateChannel, fxVersion, add-on version and client id) */ - fullSurveyUrl: async function fullSurveyUrl(surveyBaseUrl, reason) { - utilsLogger.debug( - "Called fullSurveyUrl(surveyBaseUrl, reason)", - surveyBaseUrl, - reason, - ); - return studyUtils.fullSurveyUrl(surveyBaseUrl, reason); - }, - - /* Returns an object with the following keys: - variationName - to be able to test specific variations - firstRunTimestamp - to be able to test the expiration event - expired - to be able to test the behavior of an already expired study - The values are set by the corresponding preference under the `extensions.${widgetId}.test.*` preference branch. */ - getTestingOverrides: async function getTestingOverrides() { - utilsLogger.info( - "The preferences that can be used to override study testing flags: ", - testingOverrides.listPreferences(widgetId), - ); - return testingOverrides.getTestingOverrides(widgetId); - }, - - /** - * Schema.json `events` - * - * See https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/events.html - */ - - /* Fires when the study is 'ready' for the feature to startup. */ - onReady: new EventManager(context, "study:onReady", fire => { - const listener = (eventReference, studyInfo) => { - fire.async(studyInfo); - }; - studyApiEventEmitter.once("ready", listener); - return () => { - studyApiEventEmitter.off("ready", listener); - }; - }).api(), - - /* Listen for when the study wants to end. - * - * Act on it by - * - opening surveyUrls - * - tearing down your feature - * - uninstalling the add-on - */ - onEndStudy: new EventManager(context, "study:onEndStudy", fire => { - const listener = (eventReference, ending) => { - fire.async(ending); - }; - studyApiEventEmitter.on("endStudy", listener); - return () => { - studyApiEventEmitter.off("endStudy", listener); - }; - }).api(), - - logger: { - /* Corresponds to console.info */ - info: async function info(values) { - addonLogger.info(values); - }, - - /* Corresponds to console.log */ - log: async function log(values) { - addonLogger.log(values); - }, - - /* Corresponds to console.debug */ - debug: async function debug(values) { - addonLogger.debug(values); - }, - - /* Corresponds to console.warn */ - warn: async function warn(values) { - addonLogger.warn(values); - }, - - /* Corresponds to console.error */ - error: async function error(values) { - addonLogger.error(values); - }, + fullSurveyUrl: async function fullSurveyUrl( + surveyBaseUrl, + reason, + telemetryPipeline, + ) { + try { + utilsLogger.debug( + "Called fullSurveyUrl(surveyBaseUrl, reason)", + surveyBaseUrl, + reason, + ); + return studyUtils.fullSurveyUrl({ + surveyBaseUrl, + reason, + telemetryPipeline, + }); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } }, }, studyDebug: { throwAnException(message) { + utilsLogger.debug( + `Throwing an ExtensionError with message "${message}"`, + ); throw new ExtensionError(message); }, async throwAnExceptionAsync(message) { + utilsLogger.debug( + `Throwing an ExtensionError async with message "${message}"`, + ); throw new ExtensionError(message); }, - async setActive() { - return studyUtils.setActive(); - }, - - async startup({ reason }) { - return studyUtils.startup({ reason }); - }, - - async setFirstRunTimestamp(timestamp) { - return studyUtils.setFirstRunTimestamp(timestamp); - }, - - async reset() { - return studyUtils.reset(); + async recordSeenTelemetry() { + studyUtils.recordSeenTelemetry = true; }, - async getInternals() { - return studyUtils._internals; + async resetSeenTelemetry() { + studyUtils.seenTelemetry = []; }, - getInternalTestingOverrides: async function getInternalTestingOverrides() { - return testingOverrides.getInternalTestingOverrides(widgetId); + async getSeenTelemetry() { + return studyUtils.seenTelemetry; }, }, }; diff --git a/webExtensionApis/study/src/makeWidgetId.js b/webExtensionApis/study/src/makeWidgetId.js deleted file mode 100644 index 92c1b16..0000000 --- a/webExtensionApis/study/src/makeWidgetId.js +++ /dev/null @@ -1,6 +0,0 @@ -function makeWidgetId(id) { - id = id.toLowerCase(); - return id.replace(/[^a-z0-9_-]/g, "_"); -} - -export default makeWidgetId; diff --git a/webExtensionApis/study/src/sampling.js b/webExtensionApis/study/src/sampling.js deleted file mode 100644 index 27f0f3b..0000000 --- a/webExtensionApis/study/src/sampling.js +++ /dev/null @@ -1,104 +0,0 @@ -/** Sampling utilies, including hashing functions */ - -const { Services } = ChromeUtils.import( - "resource://gre/modules/Services.jsm", - {}, -); -const { TextEncoder } = Cu.getGlobalForObject(Services); - -/** - * Given sample weights (weightedVariations) and a particular position - * (fraction), return a variation. If no fraction given, return a variation - * at random fraction proportional to the weightVariations object - * @param {Object[]} weightedVariations - the array of branch name:weight pairs - * used to randomly assign the user to a branch - * @param {Number} fraction - a number (0 <= fraction < 1) - * @returns {Object} - the variation object in weightedVariations for the given - * fraction - * - */ -export function chooseWeighted(weightedVariations, fraction = Math.random()) { - /* - weightedVariations, list of: - { - name: string of any length - weight: float >= 0 - } - */ - - const weights = weightedVariations.map(x => x.weight || 1); - const partial = cumsum(weights); - const total = weights.reduce((a, b) => a + b); - for (let ii = 0; ii < weightedVariations.length; ii++) { - if (fraction <= partial[ii] / total) { - return weightedVariations[ii]; - } - } - return null; -} - -/** - * Converts a string into a fraction (0 <= fraction < 1) based on the first - * X bits of its sha256 hexadecimal representation - * Note: Salting (adding the study name to the telemetry clientID) ensures - * that the same user gets a different bucket/hash for each study. - * Hashing of the salted string ensures uniform hashing; i.e. that every - * bucket/variation gets filled. - * @param {string} saltedString - a salted string used to create a hash for - * the user - * @param {Number} bits - The first number of bits to use in the sha256 hex - * representation - * @returns {Number} - a fraction (0 <= fraction < 1) - */ -export async function hashFraction(saltedString, bits = 12) { - const hash = await sha256(saltedString); - return parseInt(hash.substr(0, bits), 16) / Math.pow(16, bits); -} - -/** - * Converts a string into its sha256 hexadecimal representation. - * Note: This is ultimately used to make a hash of the user's telemetry clientID - * and the study name. - * @param {string} message - The message to convert. - * @returns {string} - a hexadecimal, 256-bit hash - */ -export async function sha256(message) { - // encode as UTF-8 - const msgBuffer = new TextEncoder("utf-8").encode(message); - // hash the message - const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer); - // convert ArrayBuffer to Array - const hashArray = Array.from(new Uint8Array(hashBuffer)); - // convert bytes to hex string - const hashHex = hashArray - .map(b => ("00" + b.toString(16)).slice(-2)) - .join(""); - return hashHex; -} - -/** - * Converts an array of length N into a cumulative sum array of length N, - * where n_i = sum(array.slice(0,i)) i.e. each element is the sum of all - * elements up to and including that element - * This is ultimately used for turning sample weights (AKA weightedVariations) - * into right hand limits (>= X) to deterministically select which variation - * a user receives. - * @example [.25,.3,.45] => [.25,.55,1.0]; if a user's sample weight were .25, - * they would fall into the left-most bucket - * @param {Number[]} arr - An array of sample weights (0 <= sample weight < 1) - * @returns {Number[]} - A cumulative sum array of sample weights - * (0 <= sample weight <= 1) - */ -export function cumsum(arr) { - return arr.reduce(function(r, c, i) { - r.push((r[i - 1] || 0) + c); - return r; - }, []); -} - -export default { - chooseWeighted, - cumsum, - hashFraction, - sha256, -}; diff --git a/webExtensionApis/study/src/studyUtils.js b/webExtensionApis/study/src/studyUtils.js index 7feb61c..0f3d38d 100644 --- a/webExtensionApis/study/src/studyUtils.js +++ b/webExtensionApis/study/src/studyUtils.js @@ -1,60 +1,27 @@ +/* eslint no-console: ["warn", { allow: ["info", "warn", "error"] }] */ /* eslint-env commonjs */ "use strict"; -import sampling from "./sampling"; import { utilsLogger } from "./logger"; -import makeWidgetId from "./makeWidgetId"; -import ShieldStudyType from "./studyTypes/shield"; -import PioneerStudyType from "./studyTypes/pioneer"; - -/* -* Supports the `browser.study` webExtensionExperiment api. -* -* - Conversion of v4 "StudyUtils.jsm". -* - Contains the 'dangerous' code. -* - Creates and exports the `studyUtils` singleton -* - does all the actuall privileged work including Telemetry -* -* See API.md at: -* https://github.com/mozilla/shield-studies-addon-utils/blob/develop/docs/api.md -* -* Note: There are a number of methods that won't work if the -* setup method has not executed (they perform a check with the -* `throwIfNotSetup` method). The setup method ensures that the -* studySetup data passed in is valid per the studySetup schema. -* -* Tests for this module are at /test-addon. -*/ +import ShieldTelemetryPipeline from "./telemetryPipelines/shield"; +import PioneerTelemetryPipeline from "./telemetryPipelines/pioneer"; const UTILS_VERSION = require("../../../package.json").version; const PACKET_VERSION = 3; -const Ajv = require("ajv"); - const { Services } = ChromeUtils.import( "resource://gre/modules/Services.jsm", {}, ); -const { Preferences } = ChromeUtils.import( - "resource://gre/modules/Preferences.jsm", - {}, -); - -Cu.importGlobalProperties(["URL", "crypto", "URLSearchParams"]); - const { ExtensionUtils } = ChromeUtils.import( "resource://gre/modules/ExtensionUtils.jsm", {}, ); -// eslint-disable-next-line no-undef +/* eslint-disable no-undef */ const { ExtensionError } = ExtensionUtils; -// telemetry utils -const { TelemetryEnvironment } = ChromeUtils.import( - "resource://gre/modules/TelemetryEnvironment.jsm", - null, -); +Cu.importGlobalProperties(["URL", "crypto", "URLSearchParams"]); /** * Telemetry Probe JSON schema validation (via AJV at runtime) @@ -77,52 +44,6 @@ const schemas = { }; import jsonschema from "./jsonschema"; -/** - * Schemas for enforcing objects relating to the public `browser.study` api - */ -class Guard { - /** - * @param {object} identifiedSchemas a jsonschema with ids - * - */ - constructor(identifiedSchemas) { - utilsLogger.debug("wanting guard"); - const ajv = new Ajv({ - // important: these options make ajv behave like 04, not draft-07 - schemaId: "auto", // id UNLESS $id is defined. (draft 5) - meta: require("ajv/lib/refs/json-schema-draft-04.json"), - extendRefs: true, // optional, current default is to 'fail', spec behaviour is to 'ignore' - unknownFormats: "ignore", // optional, current default is true (fail) - validateSchema: false, // used by addSchema. - - // schemas used by this *particular guard* - // schemas: identifiedSchemas, - /* NOTE: adding these at constructor isn't validating against 04 */ - }); - - for (const s of identifiedSchemas) { - utilsLogger.debug(`adding schemas ${s}`); - - ajv.addSchema(s); - } - this.ajv = ajv; - utilsLogger.debug("Ajv schemas", Object.keys(this.ajv._schemas)); - } - - it(schemaId, arg, msg = null) { - utilsLogger.debug("about to guard", schemaId, arg); - const valid = this.ajv.validate(schemaId, arg); - if (!valid) { - throw new ExtensionError( - `GuardError: ${schemaId} ${JSON.stringify( - this.ajv.errors, - )} ${JSON.stringify(arg)} ${msg}`, - ); - } - } -} -const guard = new Guard(require("../schema.json")[0].types); - /** Simple spread/rest based merge, using Object.assign. * * Right-most overrides, top level only, by full value replacement. @@ -169,170 +90,20 @@ class StudyUtils { /** * Create a StudyUtils instance to power the `browser.study` API * - * About `this._internals`: - * - variation: (chosen variation, `setup` ) - * - isEnding: bool `endStudy` - * - isSetup: bool `setup` - * - isFirstRun: bool `setup`, based on pref - * - studySetup: bool `setup` the config - * - seenTelemetry: array of seen telemetry. Fully populated only if studySetup.telemetry.internalTelemetryArchive is true - * - prefs: object of all created prefs and their names - * - endingRequested: string of ending name - * - endingReturns: object with useful ending instructions - * - * Returned by `studyDebug.getInternals()` for testing - * Reset by `studyDebug.reset` and `studyUtils.reset` - * - * About: `this._extensionManifest` - * - mirrors the extensionManifest at the time of api creation - * - used by uninstall, and to name the firstRunTimestamp pref - * + * - `this._extensionManifest`: mirrors the extensionManifest at the time of api creation + * - `this.seenTelemetry`: array of seen telemetry. Fully populated only if this.recordSeenTelemetry is true */ constructor() { - // Expose sampling methods onto the exported studyUtils singleton - this.sampling = sampling; // expose schemas this.schemas = schemas; + // expose jsonschema validation methods this.jsonschema = jsonschema; this._extensionManifest = {}; - - // internals, also used by `studyDebug.getInternals()` - // either setup() or reset() will create, using extensionManifest - this._internals = {}; - } - - _createInternals() { - if (!this._extensionManifest) { - throw new ExtensionError( - "_createInternals needs `setExtensionManifest`. This should be done by `getApi`.", - ); - } - - const widgetId = makeWidgetId( - this._extensionManifest.applications.gecko.id, - ); - - const internals = { - widgetId, - variation: undefined, - studySetup: undefined, - isFirstRun: false, - isSetup: false, - isEnding: false, - isEnded: false, - seenTelemetry: [], - prefs: { - firstRunTimestamp: `shield.${widgetId}.firstRunTimestamp`, - }, - endingRequested: undefined, - endingReturned: undefined, - }; - Object.seal(internals); - return internals; - } - - /** - * Checks if the StudyUtils.setup method has been called - * @param {string} name - the name of a StudyUtils method - * @returns {void} - */ - throwIfNotSetup(name = "unknown") { - if (!this._internals.isSetup) - throw new ExtensionError( - name + ": this method can't be used until `setup` is called", - ); - } - - /** - * Validates the studySetup object passed in from the add-on. - * @param {Object} studySetup - the studySetup object, see schema.studySetup.json - * @returns {StudyUtils} - the StudyUtils class instance - */ - async setup(studySetup) { - if (!this._internals) { - throw new ExtensionError("StudyUtils internals are not initiated"); - } - - utilsLogger.debug(`setting up! -- ${JSON.stringify(studySetup)}`); - - if (this._internals.isSetup) { - throw new ExtensionError("StudyUtils is already setup"); - } - guard.it("studySetup", studySetup, "(in studySetup)"); - this._internals.studySetup = studySetup; - - // Different study types treat data and configuration differently - if (studySetup.studyType === "shield") { - this.studyType = new ShieldStudyType(this); - } - if (studySetup.studyType === "pioneer") { - this.studyType = new PioneerStudyType(this); - } - - function getVariationByName(name, variations) { - if (!name) return null; - const chosen = variations.filter(x => x.name === name)[0]; - if (!chosen) { - throw new ExtensionError( - `setup error: testing.variationName "${name}" not in ${JSON.stringify( - variations, - )}`, - ); - } - return chosen; - } - // variation: decide and set - const variation = - getVariationByName( - studySetup.testing.variationName, - studySetup.weightedVariations, - ) || - (await this._deterministicVariation( - studySetup.activeExperimentName, - studySetup.weightedVariations, - )); - utilsLogger.debug(`setting up: variation ${variation.name}`); - - this._internals.variation = variation; - this._internals.isSetup = true; - - // isFirstRun? ever seen before? - const firstRunTimestamp = this.getFirstRunTimestamp(); - // 'firstSeen' is the first telemetry we attempt to send. needs 'isSetup' - if (firstRunTimestamp !== null) { - this._internals.isFirstRun = false; - } else { - // 'enter' telemetry, and firstSeen - await studyUtils.firstSeen(); - } - - // Note: is allowed to enroll is handled at API. - // FIXME: 5.1 maybe do it here? - return this; - } - - /** - * Resets the state of the study. Suggested use is for testing. - * @returns {Object} internals internals - */ - reset() { - this._internals = this._createInternals(); - this.studyType = null; - this.resetFirstRunTimestamp(); - } - - /** - * Gets the variation for the StudyUtils instance. - * @returns {Object} - the study variation for this user - */ - getVariation() { - this.throwIfNotSetup("getvariation"); - utilsLogger.debug( - `getVariation: ${JSON.stringify(this._internals.variation)}`, - ); - return this._internals.variation; + this.telemetryPipelineHandler = null; + this.recordSeenTelemetry = false; + this.seenTelemetry = []; } setExtensionManifest(extensionManifest) { @@ -340,68 +111,35 @@ class StudyUtils { } /** - * @returns {any} the firstRunTimestamp as a number in case the preference is set, or null if the preference is not set - */ - getFirstRunTimestamp() { - if ( - typeof this._internals.studySetup.testing.firstRunTimestamp !== - "undefined" && - this._internals.studySetup.testing.firstRunTimestamp !== null - ) { - return Number(this._internals.studySetup.testing.firstRunTimestamp); - } - const firstRunTimestampPreferenceValue = Services.prefs.getStringPref( - this._internals.prefs.firstRunTimestamp, - null, - ); - return firstRunTimestampPreferenceValue !== null - ? Number(firstRunTimestampPreferenceValue) - : null; - } - - setFirstRunTimestamp(timestamp) { - const pref = this._internals.prefs.firstRunTimestamp; - return Services.prefs.setStringPref(pref, "" + timestamp); - } - - resetFirstRunTimestamp() { - const pref = this._internals.prefs.firstRunTimestamp; - Preferences.reset(pref); - } - - /** Calculate time left in study given `studySetup.expire.days` and firstRunTimestamp - * - * Safe to use with `browser.alarms.create{ delayInMinutes, }` - * - * A value of 0 means "the past / now". - * - * @return {Number} delayInMinutes Either the time left or Number.MAX_SAFE_INTEGER + * @param {string} telemetryPipeline - the telemetry pipeline + * @returns {Object} The instance of the appropriate handler class */ - getDelayInMinutes() { - if (this._internals.studySetup.testing.expired === true) { - return 0; - } - const toMinutes = 1 / (1000 * 60); - const days = this._internals.studySetup.expire.days; - let delayInMs = Number.MAX_SAFE_INTEGER; // approx 286,000 years - if (days) { - // days in ms - const ms = days * 86400 * 1000; - const firstrun = this.getFirstRunTimestamp(); - if (firstrun === null) { - return null; + getTelemetryPipelineHandler(telemetryPipeline) { + if (!this.telemetryPipelineHandler) { + // Different telemetry pipelines treat data and configuration differently + switch (telemetryPipeline) { + case "shield": + this.telemetryPipelineHandler = new ShieldTelemetryPipeline(this); + break; + case "pioneer": + this.telemetryPipelineHandler = new PioneerTelemetryPipeline(this); + break; + default: + throw new ExtensionError( + `Unknown telemetryPipeline: "${telemetryPipeline}"`, + ); } - delayInMs = Math.max(firstrun + ms - Date.now(), 0); } - return delayInMs * toMinutes; + return this.telemetryPipelineHandler; } /** * Gets the telemetry client ID for the user. + * @param {string} telemetryPipeline - the telemetry pipeline * @returns {string} - the telemetry client ID */ - async getTelemetryId() { - return this.studyType.getTelemetryId(); + async getTelemetryId(telemetryPipeline) { + return this.getTelemetryPipelineHandler(telemetryPipeline).getTelemetryId(); } /** @@ -413,266 +151,14 @@ class StudyUtils { return Services.prefs.getStringPref(key, ""); } - /** - * Packages information about the study into an object. - * @returns {Object} - study information, see schema.studySetup.json - */ - info() { - utilsLogger.debug("getting info"); - this.throwIfNotSetup("info"); - - const studyInfo = { - activeExperimentName: this._internals.studySetup.activeExperimentName, - isFirstRun: this._internals.isFirstRun, - firstRunTimestamp: this.getFirstRunTimestamp(), - variation: this.getVariation(), - shieldId: this.getShieldId(), - delayInMinutes: this.getDelayInMinutes(), - }; - const now = new Date(); - const diff = Number(now) - studyInfo.firstRunTimestamp; - utilsLogger.debug( - "Study info date information: now, new Date(firstRunTimestamp), firstRunTimestamp, diff (in minutes), delayInMinutes", - now, - new Date(studyInfo.firstRunTimestamp), - studyInfo.firstRunTimestamp, - diff / 1000 / 60, - studyInfo.delayInMinutes, - ); - guard.it("studyInfoObject", studyInfo, "(in studyInfo)"); - return studyInfo; - } - - /** - * Get the telemetry configuration for the study. - * @returns {Object} - the telemetry configuration, see schema.studySetup.json - */ - get telemetryConfig() { - this.throwIfNotSetup("telemetryConfig"); - return this._internals.studySetup.telemetry; - } - - /** - * Deterministically selects and returns the study variation for the user. - * @param {string} activeExperimentName name to use as part of the hash - * @param {Object[]} weightedVariations - see schema.weightedVariations.json - * @param {Number} fraction - a number (0 <= fraction < 1); can be set explicitly for testing - * @returns {Object} - the study variation for this user - */ - async _deterministicVariation( - activeExperimentName, - weightedVariations, - fraction = null, - ) { - // this is the standard arm choosing method, used by both shield and pioneer studies - if (fraction === null) { - // hash the studyName and telemetryId to get the same branch every time. - const clientId = await this.getTelemetryId(); - fraction = await this.sampling.hashFraction( - activeExperimentName + clientId, - 12, - ); - } - utilsLogger.debug(`_deterministicVariation`, weightedVariations); - return this.sampling.chooseWeighted(weightedVariations, fraction); - } - - /** - * Sends an 'enter' telemetry ping for the study; should be called on add-on - * startup for the reason ADDON_INSTALL. For more on study states like 'enter' - * see ABOUT.md at github.com/mozilla/shield-studies-addon-template - * - * Side effects: - * - sends 'enter' - * - sets this._internals.prefs.firstRunTimestamp to Date.now() - * - * @returns {void} - */ - async firstSeen() { - this.throwIfNotSetup("firstSeen uses telemetry."); - utilsLogger.debug(`attempting firstSeen`); - this._internals.isFirstRun = true; - await this._telemetry({ study_state: "enter" }, "shield-study"); - this.setFirstRunTimestamp(Date.now()); - } - - /** - * Marks the study's telemetry pings as being part of this experimental - * cohort in a way that downstream data pipeline tools - * (like ExperimentsViewer) can use it. - * @returns {void} - */ - setActive() { - this.throwIfNotSetup("setActive uses telemetry."); - const info = this.info(); - utilsLogger.debug( - "marking TelemetryEnvironment", - info.activeExperimentName, - info.variation.name, - ); - TelemetryEnvironment.setExperimentActive( - info.activeExperimentName, - info.variation.name, - ); - } - - /** - * Removes the study from the active list of telemetry experiments - * @returns {void} - */ - unsetActive() { - this.throwIfNotSetup("unsetActive uses telemetry."); - const info = this.info(); - utilsLogger.debug( - "unmarking TelemetryEnvironment", - info.activeExperimentName, - info.variation.name, - ); - TelemetryEnvironment.setExperimentInactive(info.activeExperimentName); - } - - /** - * Adds the study to the active list of telemetry experiments and sends the - * "installed" telemetry ping if applicable - * @param {string} reason - The reason the add-on has started up - * @returns {void} - */ - async startup() { - this.throwIfNotSetup("startup"); - const isFirstRun = this._internals.isFirstRun; - utilsLogger.debug(`startup. setting active. isFirstRun? ${isFirstRun}`); - this.setActive(); - if (isFirstRun) { - await this._telemetry({ study_state: "installed" }, "shield-study"); - } - } - - /** - * Ends the study: - * - Removes the study from the active list of telemetry experiments - * - Sends a telemetry ping about the nature of the ending - * (positive, neutral, negative) - * - Sends an exit telemetry ping - * @param {string} endingName - The reason the study is ending, see - * schema.studySetup.json - * @returns {Object} endingReturned _internals.endingReturned - */ - async endStudy(endingName) { - this.throwIfNotSetup("endStudy"); - - // also handle default endings. - const alwaysHandle = [ - "ineligible", - "expired", - "user-disable", - "install-failure", - "individual-opt-out", - "general-opt-out", - "recipe-not-seen", - "uninstalled", - "uninstalled-sideload", - "unknown", - ]; - let ending = this._internals.studySetup.endings[endingName]; - if (!ending) { - // a 'no-action' ending is okay for the 'always handle' - if (alwaysHandle.includes(endingName)) { - ending = {}; - } else { - throw new ExtensionError(`${endingName} isn't known ending`); - } - } - - // throw if already ending - if (this._internals.isEnding) { - utilsLogger.debug("endStudy, already ending!"); - throw new ExtensionError( - `endStudy, requested: ${endingName}, but already ending ${ - this._internals.endingRequested - }`, - ); - } - - // if not already ending, claim it. We are first! - this._internals.isEnding = true; - this._internals.endingRequested = endingName; - - utilsLogger.debug(`endStudy ${endingName}`); - await this.unsetActive(); - - // do the work to end the studyUtils involvement - - // 1. Telemetry for ending - const { fullname } = ending; - let finalName = endingName; - switch (endingName) { - // handle the 'formal' endings (defined in parquet) - case "ineligible": - case "expired": - case "user-disable": - case "ended-positive": - case "ended-neutral": - case "ended-negative": - await this._telemetry( - { - study_state: endingName, - study_state_fullname: fullname || endingName, - }, - "shield-study", - ); - break; - default: - (finalName = ending.category || "ended-neutral"), - // call all 'unknowns' as "ended-neutral" - await this._telemetry( - { - study_state: finalName, - study_state_fullname: endingName, - }, - "shield-study", - ); - break; - } - await this._telemetry({ study_state: "exit" }, "shield-study"); - - // 2. create ending instructions for the webExt to use - const out = { - shouldUninstall: true, - urls: [], - endingName, - }; - - // baseUrls: needs to be appended with query arguments before use, - // exactUrls: used as is - const { baseUrls, exactUrls } = ending; - if (exactUrls) { - out.urls.push(...exactUrls); - } - const qa = await this.endingQueryArgs(); - qa.reason = finalName; - qa.fullreason = endingName; - - if (baseUrls) { - for (const baseUrl of baseUrls) { - const fullUrl = mergeQueryArgs(baseUrl, qa); - out.urls.push(fullUrl); - } - } - - out.queryArgs = qa; - - // 3. Temporarily store information about the ending for test purposes - this._internals.endingReturned = out; - this._internals.isEnded = true; // done! - - // 4. Make sure that future add-on installations are treated as new studies rather than a continuation of the previous one - this.resetFirstRunTimestamp(); - - return out; - } - - async fullSurveyUrl(surveyBaseUrl, reason) { - const queryArgs = await this.endingQueryArgs(); + async fullSurveyUrl({ surveyBaseUrl, reason, telemetryPipeline }) { + const study = this._extensionManifest.applications.gecko.id; + const variation = this._extensionManifest.applications.gecko.id; + const queryArgs = await this.endingQueryArgs({ + telemetryPipeline, + study, + variation, + }); queryArgs.reason = reason; queryArgs.fullreason = reason; return mergeQueryArgs(surveyBaseUrl, queryArgs); @@ -683,147 +169,179 @@ class StudyUtils { * appended to a study ending url * @returns {Object} - the query arguments for the study */ - async endingQueryArgs() { - this.throwIfNotSetup("endingQueryArgs"); - const info = this.info(); - const who = await this.getTelemetryId(); - const queryArgs = { - shield: PACKET_VERSION, - study: info.activeExperimentName, - variation: info.variation.name, - updateChannel: Services.appinfo.defaultUpdateChannel, - fxVersion: Services.appinfo.version, - addon: this._extensionManifest.version, // addon version - who, // telemetry clientId - }; - queryArgs.testing = Number(!this.telemetryConfig.removeTestingFlag); - return queryArgs; + async endingQueryArgs({ telemetryPipeline, study, variation }) { + try { + const who = await this.getTelemetryId(telemetryPipeline); + const queryArgs = { + shield: PACKET_VERSION, + study, + variation, + updateChannel: Services.appinfo.defaultUpdateChannel, + fxVersion: Services.appinfo.version, + addon: this._extensionManifest.version, // addon version + who, // telemetry clientId + }; + queryArgs.testing = "-1"; // Currently unconfigurable but surveygizmo-expected parameter - filling with "-1" as placeholder + return queryArgs; + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } } /** * Validates and submits telemetry pings from StudyUtils. * @param {Object} data - the data to send as part of the telemetry packet * @param {string} bucket - the type of telemetry packet to be sent + * @param {string} telemetryPipeline - the telemetry pipeline * @returns {Promise|boolean} - A promise that resolves with the ping id * once the ping is stored or sent, or false if * - there is a validation error, * - the packet is of type "shield-study-error" * - the study's telemetryConfig.send is set to false */ - async _telemetry(data, bucket = "shield-study-addon") { - this.throwIfNotSetup("_telemetry"); - utilsLogger.debug(`telemetry in: ${bucket} ${JSON.stringify(data)}`); - const info = this.info(); - utilsLogger.debug(`telemetry INFO: ${JSON.stringify(info)}`); - - const payload = { - version: PACKET_VERSION, - study_name: info.activeExperimentName, - branch: info.variation.name, - addon_version: this._extensionManifest.version, - shield_version: UTILS_VERSION, - type: bucket, - data, - testing: !this.telemetryConfig.removeTestingFlag, - }; - - let validation; + async _telemetry(data, { bucket, telemetryPipeline }) { try { - validation = jsonschema.validate(payload, schemas[bucket]); - } catch (err) { - // Catch failures of unknown origin (could be library, add-on, system...) - // if validation broke, GIVE UP. - utilsLogger.error(err); - return false; - } - /* - * Handle validation errors by sending a "shield-study-error" - * telemetry ping with the error report. - * If the invalid payload is itself of type "shield-study-error", - * throw an error (to avoid a possible infinite loop). - */ - if (validation.errors.length) { - const errorReport = { - error_id: "jsonschema-validation", - error_source: "addon", - severity: "fatal", - message: JSON.stringify(validation.errors), + utilsLogger.debug(`telemetry in: ${bucket} ${JSON.stringify(data)}`); + + const study_name = this._extensionManifest.applications.gecko.id; + const branch = this._extensionManifest.applications.gecko.id; + const testing = false; // Currently unconfigurable schema-expected parameter - defaulting to false + const payload = { + version: PACKET_VERSION, + study_name, + branch, + addon_version: this._extensionManifest.version, + shield_version: UTILS_VERSION, + type: bucket, + data, + testing, }; - if (bucket === "shield-study-error") { - utilsLogger.warn("cannot validate shield-study-error", data, bucket); - return false; // just die, maybe should have a super escape hatch? - } - return this.telemetryError(errorReport); - } - utilsLogger.debug(`telemetry: ${JSON.stringify(payload)}`); - - let pingId; - // during development, don't actually send - if (!this.telemetryConfig.send) { - utilsLogger.debug("NOT sending. `telemetryConfig.send` is false"); - pingId = false; - } else { - pingId = await this.studyType.sendTelemetry(bucket, payload); - } + let validation; + try { + validation = jsonschema.validate(payload, schemas[bucket]); + } catch (err) { + // Catch failures of unknown origin (could be library, add-on, system...) + // if validation broke, GIVE UP. + utilsLogger.error(err); + return false; + } + /* + * Handle validation errors by sending a "shield-study-error" + * telemetry ping with the error report. + * If the invalid payload is itself of type "shield-study-error", + * throw an error (to avoid a possible infinite loop). + */ + if (validation.errors.length) { + const errorReport = { + error_id: "jsonschema-validation", + error_source: "addon", + severity: "fatal", + message: JSON.stringify(validation.errors), + }; + if (bucket === "shield-study-error") { + utilsLogger.warn("cannot validate shield-study-error", data, bucket); + return false; // just die, maybe should have a super escape hatch? + } + return this.telemetryError(errorReport, telemetryPipeline); + } + utilsLogger.debug(`telemetry: ${JSON.stringify(payload)}`); + + const pingId = await this.getTelemetryPipelineHandler( + telemetryPipeline, + ).sendTelemetry(bucket, payload); + + // Store a copy of the ping if it's a shield-study or error ping, which are few in number, or if we have activated the internal telemetry archive configuration + if ( + bucket === "shield-study" || + bucket === "shield-study-error" || + this.recordSeenTelemetry + ) { + this.seenTelemetry.push({ id: pingId, payload }); + } - // Store a copy of the ping if it's a shield-study or error ping, which are few in number, or if we have activated the internal telemetry archive configuration - if ( - bucket === "shield-study" || - bucket === "shield-study-error" || - this.telemetryConfig.internalTelemetryArchive - ) { - this._internals.seenTelemetry.push({ id: pingId, payload }); + return pingId; + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); } - - return pingId; } /** * Validates and submits telemetry pings from the add-on; mostly from * webExtension messages. * @param {Object} payload - the data to send as part of the telemetry packet + * @param {string} telemetryPipeline - the telemetry pipeline * @returns {Promise|boolean} - see StudyUtils._telemetry */ - async telemetry(payload) { - this.throwIfNotSetup("telemetry"); - utilsLogger.debug(`telemetry ${JSON.stringify(payload)}`); - const toSubmit = { - attributes: payload, - }; - return this._telemetry(toSubmit, "shield-study-addon"); + async telemetry(payload, telemetryPipeline) { + try { + utilsLogger.debug(`telemetry ${JSON.stringify(payload)}`); + const toSubmit = { + attributes: payload, + }; + return this._telemetry(toSubmit, { + telemetryPipeline, + bucket: "shield-study-addon", + }); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } } /** * Submits error report telemetry pings. * @param {Object} errorReport - the error report, see StudyUtils._telemetry + * @param {string} telemetryPipeline - the telemetry pipeline * @returns {Promise|boolean} - see StudyUtils._telemetry */ - telemetryError(errorReport) { - return this._telemetry(errorReport, "shield-study-error"); + telemetryError(errorReport, telemetryPipeline) { + try { + return this._telemetry(errorReport, { + bucket: "shield-study-error", + telemetryPipeline, + }); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } } - /** Calculate Telemetry using appropriate shield or pioneer methods. + /** + * Calculate Telemetry using appropriate shield or pioneer methods. * * shield: * - Calculate the size of a ping * - * pioneer: + * pioneer: * - Calculate the size of a ping that has Pioneer encrypted data * * @param {Object} payload Non-nested object with key strings, and key values + * @param {string} telemetryPipeline - the telemetry pipeline * @returns {Promise} The total size of the ping. */ - async calculateTelemetryPingSize(payload) { - this.throwIfNotSetup("calculateTelemetryPingSize"); - const toSubmit = { - attributes: payload, - }; - return this.studyType.getPingSize(toSubmit, "shield-study-addon"); + async calculateTelemetryPingSize(payload, telemetryPipeline) { + try { + const toSubmit = { + attributes: payload, + }; + return this.getTelemetryPipelineHandler(telemetryPipeline).getPingSize( + toSubmit, + "shield-study-addon", + ); + } catch (error) { + // Surface otherwise silent or obscurely reported errors + console.error(error.message, error.stack); + throw new ExtensionError(error.message); + } } } -// TODO, use the usual es6 exports // Actually create the singleton. -const studyUtils = new StudyUtils(); -this.studyUtils = studyUtils; +export const studyUtils = new StudyUtils(); diff --git a/webExtensionApis/study/src/studyTypes/pioneer.js b/webExtensionApis/study/src/telemetryPipelines/pioneer.js similarity index 97% rename from webExtensionApis/study/src/studyTypes/pioneer.js rename to webExtensionApis/study/src/telemetryPipelines/pioneer.js index 7096dfe..dcd9520 100644 --- a/webExtensionApis/study/src/studyTypes/pioneer.js +++ b/webExtensionApis/study/src/telemetryPipelines/pioneer.js @@ -217,15 +217,14 @@ class PioneerUtils { } } -class PioneerStudyType { +class PioneerTelemetryPipeline { /** * @param {object} studyUtils The studyUtils instance from where this class was instantiated */ constructor(studyUtils) { - const studySetup = studyUtils._internals.studySetup; const Config = { - studyName: studySetup.activeExperimentName, - telemetryEnv: studySetup.telemetry.removeTestingFlag ? "prod" : "stage", + studyName: studyUtils._extensionManifest.applications.gecko.id, + telemetryEnv: "prod", // Currently unconfigurable parameter - defaulting to "prod" rather than "stage" }; this.pioneerUtils = new PioneerUtils(Config); this.schemaVersion = 3; // Corresponds to the schema versions used in https://github.com/mozilla-services/mozilla-pipeline-schemas/tree/dev/templates/telemetry/shield-study (and the shield-study-addon, shield-study-error equivalents) @@ -341,4 +340,4 @@ class PioneerStudyType { } } -export default PioneerStudyType; +export default PioneerTelemetryPipeline; diff --git a/webExtensionApis/study/src/studyTypes/pioneer.public_keys.json b/webExtensionApis/study/src/telemetryPipelines/pioneer.public_keys.json similarity index 100% rename from webExtensionApis/study/src/studyTypes/pioneer.public_keys.json rename to webExtensionApis/study/src/telemetryPipelines/pioneer.public_keys.json diff --git a/webExtensionApis/study/src/studyTypes/shield.js b/webExtensionApis/study/src/telemetryPipelines/shield.js similarity index 95% rename from webExtensionApis/study/src/studyTypes/shield.js rename to webExtensionApis/study/src/telemetryPipelines/shield.js index 31e1d0d..0ab2ae1 100644 --- a/webExtensionApis/study/src/studyTypes/shield.js +++ b/webExtensionApis/study/src/telemetryPipelines/shield.js @@ -15,7 +15,7 @@ const { ClientID } = ChromeUtils.import( // eslint-disable-next-line no-undef // const { ExtensionError } = ExtensionUtils; -class ShieldStudyType { +class ShieldTelemetryPipeline { /** * @param {object} studyUtils The studyUtils instance from where this class was instantiated */ @@ -56,4 +56,4 @@ class ShieldStudyType { } } -export default ShieldStudyType; +export default ShieldTelemetryPipeline; diff --git a/webExtensionApis/study/src/testingOverrides.js b/webExtensionApis/study/src/testingOverrides.js deleted file mode 100644 index 1b85132..0000000 --- a/webExtensionApis/study/src/testingOverrides.js +++ /dev/null @@ -1,34 +0,0 @@ -const { Preferences } = ChromeUtils.import( - "resource://gre/modules/Preferences.jsm", - {}, -); - -export function getTestingOverrides(widgetId) { - const testingOverrides = {}; - testingOverrides.variationName = - Preferences.get(`extensions.${widgetId}.test.variationName`) || null; - const firstRunTimestamp = Preferences.get( - `extensions.${widgetId}.test.firstRunTimestamp`, - ); - testingOverrides.firstRunTimestamp = firstRunTimestamp - ? Number(firstRunTimestamp) - : null; - testingOverrides.expired = - Preferences.get(`extensions.${widgetId}.test.expired`) || null; - return testingOverrides; -} - -export function listPreferences(widgetId) { - return [ - `extensions.${widgetId}.test.variationName`, - `extensions.${widgetId}.test.firstRunTimestamp`, - `extensions.${widgetId}.test.expired`, - ]; -} - -export function getInternalTestingOverrides(widgetId) { - const internalTestingOverrides = {}; - internalTestingOverrides.studyType = - Preferences.get(`extensions.${widgetId}.test.studyType`) || null; - return internalTestingOverrides; -}